I have a c# program using System.Security.Cryptography (standard provider) that needs to generate RSA keys of a particular bit size and exponent to interface with another long standing system. This code seems reasonable to me:
for (int trix = 0; trix < 1000; trix++)
{
using (var rsa2 = new RSACryptoServiceProvider(1024)) // public key length in bits
{ // PROBLEM: MS seems stuck on the big exponent
RSAParameters key2 = rsa2.ExportParameters(true);
key2.Exponent = new byte[1] { 3 }; // public key exponent
rsa2.ImportParameters(key2);
PrintToFeedback(rsa2.ToXmlString(true));
byte[] bm0 = Utilities.HexStringToByteArray("1002030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
byte[] bm1 = rsa2.Encrypt(bm0, false);
byte[] bm2 = rsa2.Decrypt(bm1, false);
string szbm0 = Utilities.ByteArrayToHexString(bm0);
string szbm2 = Utilities.ByteArrayToHexString(bm2);
if (szbm0 != szbm2)
{
PrintToFeedback("RSA module test FAILED with MS RSA keys with small exponent, bm0, bm1, bm2 follow:");
PrintToFeedback(szbm0);
PrintToFeedback(Utilities.ByteArrayToHexString(bm1));
PrintToFeedback(szbm2);
ok = false;
break;
}
}
}
Most of the time but not always, I get a Bad Parameter exception on rsa2.ImportParameters with the 3 exponent. Sometimes it works, and I have had runs where rsa2.ToXmlString shows an Exponent of 3:
<Exponent>Aw==</Exponent>
>base64 -d | xxd
Aw==
00000000: 03
The test loop sometimes fails with nonzero trix, so it works a little. See the screenshot and this MSDN social network post from 2019
What is the right way to get a 1024 bit key with exponent 3 from System.Security.Cryptography?
(edited to add MSDN link)
After changing the public exponent, the remaining dependent components (namely
P
,Q
,Modulus
,D
,DP
,DQ
,InverseQ
) of the key must also be adjusted. To achieve this, it is definitely better to use specialized tools, e.g. BouncyCastle.In pure C# you can do something like:
Here is
UpdatePublicExponent
with the other helper functions: