如何解密 .NET 中的 RSA 内容?
Posted
技术标签:
【中文标题】如何解密 .NET 中的 RSA 内容?【英文标题】:How to decrypt RSA content in .NET? 【发布时间】:2016-03-04 03:36:58 【问题描述】:我正在使用 OpenSSL 生成 RSA 私钥和公钥,将公钥发送到 html 页面以加密用户名和密码(使用 JSEncrypt)。加密的内容发送到服务器以使用私钥解密。
这是我的解密函数:
public string RsaDecrypt(string xmlPrivateKey, string mStrDecryptString)
string str2;
try
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
provider.FromXmlString(xmlPrivateKey);
byte[] rgb = Convert.FromBase64String(mStrDecryptString);
byte[] buffer2 = provider.Decrypt(rgb, false);
str2 = new UnicodeEncoding().GetString(buffer2);
catch (Exception exception)
throw exception;
return str2;
xmlPrivateKey 值为:
mStrDecryptString 是:MIICWwIBAAKBgQCt8y + vx9Y3Iik9l / 8r6x + wjcrgPskbjVpt7fSJqtpCA / XaYl / 3O2uvrRUPzyqr1wA + ejsdhdm285nYSbSaHTPem1 + N / JHynp + cLQiBV6a8PayOvtrSBaHLZDDhgvntk / BLeplU406kiMltnVDko33H + Y3yaNuY2TNDEMe5Z8OlUQIDAQABAoGAdYIChMyKeVQqZ + F2D0UWcz5V / oZrdKFYpUpKF3XDWzUxsAUkru8FH / fccoGQYeUr1QjdRmRVXrHRC7s + tZ1km68oiUFD6sbCYyPQy0Se95050FncM3lEndGUJTiTelVqAYh + DPVnRURcfgA + HSvWek1 / YnOZ8UNZJ36jiogSKcECQQDbRfn / UODXud7MKO7zfYOLvPhtFMgtA0Ac5w6tTJ / llZs0QtjMKCNHF9bGRxKdFvKTMA1DGBNN0chdWAc7UET / AkEAyxXUJAk1 + 46fRhzTH4uXRX7SEMCwEjY79DHqE23pPx8Q8VC3j2aPETQerT4EHNzaMBg6hneJE2p7xB5Rm / SFrwJAIWasaT7psRLIJHNLyt1gr2WOthcHUwv + tShhLPbSGIfMh45zNc4baZXxCm0DIdjABLm6G3FMZ3tAOS / Ski9tAwJAMYWQJn1sgXwk0KcEwIN8jsC / HsCt7rL06bYmOzipEPBVZFLnf / tlVa + c72fY / UTH + 8RcuR96 + JYVuhwekGYPFwJAQXbsOkyVTvZGcqRk9 + SF7AUsGcHYPrImH6iafYEBsVCOrMJfjEai0zmd / 9A1j + NHFq31KPAQGV0zHmV2NXscDg ==
fW9H + /新西兰/ yp6my / EwY0I + KP1CX / QPY8TL3bFDvfJYJDJ50LHEPfiR / RGhHl9rvViXOgD4IiXYF2 / KbNPQNmno + Bioi3r8Xc5 + PVNyFDJy + X4 / YjX4O830g9vAhyRJ1RKbJOmJYWT4sdP0jfxwaRL2 + FAl6yIsrcsH / 7bRZvjDTU = P>
在服务器端解密时,报错:
第 1 行中的语法无效。
我该怎么做才能使它正确?
【问题讨论】:
xmlPrivateKey
不是 XML 字符串,所以不能使用 provider.FromXmlString
。
你最好显示加密代码。
【参考方案1】:
OpenSSL 生成的 RSA 格式与 .NET 不同,需要将 OpenSSL RSA xmlPrivateKey
转换为 XML 格式,以便RSACryptoServiceProvider
能够识别。
private static RSACryptoServiceProvider DecodeRsaPrivateKey(string priKey)
var privkey = Convert.FromBase64String(priKey);
byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
// --------- Set up stream to decode the asn.1 encoded RSA private key ------
var mem = new MemoryStream(privkey);
var binr = new BinaryReader(mem); // wrap Memory Stream with BinaryReader for easy reading
try
var twobytes = binr.ReadUInt16();
if (twobytes == 0x8130) // data read as little endian order (actual data order for Sequence is 30 81)
binr.ReadByte(); // advance 1 byte
else if (twobytes == 0x8230)
binr.ReadInt16(); // advance 2 bytes
else
return null;
twobytes = binr.ReadUInt16();
if (twobytes != 0x0102) // version number
return null;
var bt = binr.ReadByte();
if (bt != 0x00)
return null;
//------ all private key components are Integer sequences ----
var elems = GetIntegerSize(binr);
MODULUS = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
E = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
D = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
P = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
Q = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
DP = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
DQ = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
IQ = binr.ReadBytes(elems);
// ------- create RSACryptoServiceProvider instance and initialize with public key -----
var rsa = new RSACryptoServiceProvider();
var rsAparams = new RSAParameters
Modulus = MODULUS,
Exponent = E,
D = D,
P = P,
Q = Q,
DP = DP,
DQ = DQ,
InverseQ = IQ
;
rsa.ImportParameters(rsAparams);
return rsa;
catch (Exception e)
LogHelper.Logger.Error("DecodeRsaPrivateKey failed", e);
return null;
finally
binr.Close();
private static int GetIntegerSize(BinaryReader binary)
byte binaryReadByte = 0;
var count = 0;
binaryReadByte = binary.ReadByte();
if (binaryReadByte != 0x02) // expect integer
return 0;
binaryReadByte = binary.ReadByte();
if (binaryReadByte == 0x81)
count = binary.ReadByte(); // data size in next byte
else
if (binaryReadByte == 0x82)
var highbyte = binary.ReadByte();
var lowbyte = binary.ReadByte();
byte[] modint = lowbyte, highbyte, 0x00, 0x00 ;
count = BitConverter.ToInt32(modint, 0);
else
count = binaryReadByte; // we already have the data size
while (binary.ReadByte() == 0x00)
//remove high order zeros in data
count -= 1;
binary.BaseStream.Seek(-1, SeekOrigin.Current); // last ReadByte wasn't a removed zero, so back up a byte
return count;
所以RSACryptoServiceProvider
可以解密原始上下文。
【讨论】:
能否使用相同的代码 (DecodeRsaPrivateKey) 构建使用公钥加密 (OpenSSL) 所需的 RSACryptoServiceProvider? 为了继续使用密钥导出到 PFX,我必须设置一个 csp KeyContainerName。代替 new RSACryptoServiceProvder(),执行 new RSACryptoServiceProvider(new CspParameters() KeyContainerName = Guid.NewGuid().ToString("B").ToUpper() );名称的内容可能根本不重要,但大写括号 GUID 是我在其他地方看到的,现在我可以 X509Certificate2.Export 并保留私钥。以上是关于如何解密 .NET 中的 RSA 内容?的主要内容,如果未能解决你的问题,请参考以下文章
在.NET中实现RSA公钥/私钥解密到Java/Spring
使用 RSA/ECB/OAEPWithSHA-256AndMGF1Padding 的 Java 加密无法在 .NET 中解密