.NET 下的原始 RSA 加密(又名 ECB/NoPadding)?
Raw RSA encryption (aka ECB/NoPadding) under .NET?
我考虑了不直接支持的标准RSA签名方案的验证部分在.NET(使用C#)下的可行性和性能。为了实现这个目标,我需要原始 RSA public-key 加密函数 x → (x65537) mod N (其中 x 是一个字节数组,与 public modulus N 一样宽,例如 256 字节)。
在其他平台上,标准技术是使用不带填充的 RSA 加密(Java 的密码 "RSA/ECB/NoPadding")来实现该功能。但我找不到如何在 .NET 下执行此操作。我有哪些选择?
.NET收件箱不提供此功能。如果您只是在进行 public 键操作,那么您可以使用 BigInteger
class 而无需承担安全责任。 (不要将它用于私钥操作,因为 a)它会在内存中相当明显地保存您的私钥,并且 b)它没有基于 Montgomery Ladder 的 ModPow,因此它会泄漏您私钥的汉明权重)
RSA existingKey = HoweverYouWereGettingAKey();
RSAParameters rsaParams = existingKey.ExportParameters(false);
BigInteger n = PrepareBigInteger(rsaParams.Modulus);
BigInteger e = PrepareBigInteger(rsaParams.Exponent);
BigInteger sig = PrepareBigInteger(signature);
BigInteger paddedMsgVal = BigInteger.ModPow(sig, e, n);
byte[] paddedMsg = paddedMsgVal.ToArray();
if (paddedMsg[paddedMsg.Length - 1] == 0)
{
Array.Resize(ref paddedMsg, paddedMsg.Length - 1);
}
Array.Reverse(paddedMsg);
// paddedMsg is now ready.
private static BigInteger PrepareBigInteger(byte[] unsignedBigEndian)
{
// Leave an extra 0x00 byte so that the sign bit is clear
byte[] tmp = new byte[unsignedBigEndian.Length + 1];
Buffer.BlockCopy(unsignedBigEndian, 0, tmp, 1, unsignedBigInteger.Length);
Array.Reverse(tmp);
return new BigInteger(tmp);
}
我考虑了不直接支持的标准RSA签名方案的验证部分在.NET(使用C#)下的可行性和性能。为了实现这个目标,我需要原始 RSA public-key 加密函数 x → (x65537) mod N (其中 x 是一个字节数组,与 public modulus N 一样宽,例如 256 字节)。
在其他平台上,标准技术是使用不带填充的 RSA 加密(Java 的密码 "RSA/ECB/NoPadding")来实现该功能。但我找不到如何在 .NET 下执行此操作。我有哪些选择?
.NET收件箱不提供此功能。如果您只是在进行 public 键操作,那么您可以使用 BigInteger
class 而无需承担安全责任。 (不要将它用于私钥操作,因为 a)它会在内存中相当明显地保存您的私钥,并且 b)它没有基于 Montgomery Ladder 的 ModPow,因此它会泄漏您私钥的汉明权重)
RSA existingKey = HoweverYouWereGettingAKey();
RSAParameters rsaParams = existingKey.ExportParameters(false);
BigInteger n = PrepareBigInteger(rsaParams.Modulus);
BigInteger e = PrepareBigInteger(rsaParams.Exponent);
BigInteger sig = PrepareBigInteger(signature);
BigInteger paddedMsgVal = BigInteger.ModPow(sig, e, n);
byte[] paddedMsg = paddedMsgVal.ToArray();
if (paddedMsg[paddedMsg.Length - 1] == 0)
{
Array.Resize(ref paddedMsg, paddedMsg.Length - 1);
}
Array.Reverse(paddedMsg);
// paddedMsg is now ready.
private static BigInteger PrepareBigInteger(byte[] unsignedBigEndian)
{
// Leave an extra 0x00 byte so that the sign bit is clear
byte[] tmp = new byte[unsignedBigEndian.Length + 1];
Buffer.BlockCopy(unsignedBigEndian, 0, tmp, 1, unsignedBigInteger.Length);
Array.Reverse(tmp);
return new BigInteger(tmp);
}