I consider feasibility and performance under .NET (using C#) of the verification part of a standard RSA signature scheme that is not directly supported. Towards that goals, I need the raw RSA public-key encryption function x → (x65537) mod N (where x is a byte array as wide as the public modulus N is, like 256 bytes).
On other platforms, the standard technique is to implement that function using RSA encryption with no padding (Java's Cipher with "RSA/ECB/NoPadding"). But I can't find how to perform this under .NET. What are my options?
.NET doesn't provide this functionality inbox. If you're just doing public key operations then you can use the BigInteger class without having security liabilities. (Don't use it for private key operations, because a) it'll have your private key fairly obviously in memory and b) it doesn't have a Montgomery Ladder based ModPow, so it would leak the Hamming Weight of your private key)
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With