0

I'm working on RSA encryption and have my public key in C#. But i have my public key modulus and exponent in decimal format as below :

modulus: 18597082174523508716390621410767314599038866539779750637065684697259605002694360104971398651747704217448206242771805831180528356170981586469477958663193117845356353634469679095227815268434823260637917891539622982485837392495877800705071553435850492058570460745900129552907596604479063007676795998193064078987369363544131073880694736862904482385332020513837955197528182597410203652025183467149166026077910473816908590029574674997850683021938033561647681780168764842253700974777073181357779101690539999736174329578178742236883520017849893817175274405622018571899733008344137833140207194792223664500885734080606246950229

public exponent: 65537

How can i use above for RSA encryption in c#?

2 Answers2

2

For anyone else finding this, we can use native built in support for this functionality now. https://github.com/dotnet/runtime/issues/23812

var bi1 = BigInteger.Parse("18597082174523508716390621410767314599038866539779750637065684697259605002694360104971398651747704217448206242771805831180528356170981586469477958663193117845356353634469679095227815268434823260637917891539622982485837392495877800705071553435850492058570460745900129552907596604479063007676795998193064078987369363544131073880694736862904482385332020513837955197528182597410203652025183467149166026077910473816908590029574674997850683021938033561647681780168764842253700974777073181357779101690539999736174329578178742236883520017849893817175274405622018571899733008344137833140207194792223664500885734080606246950229");
var bi2 = BigInteger.Parse("65537");
var bytes1 = bi1.ToByteArray(true, true); // isUnsigned: true, isBigEndian: true
var bytes2 = bi2.ToByteArray(true, true);

var pars = new RSAParameters();
pars.Modulus = bytes1;
pars.Exponent = bytes2;
Eliott Robson
  • 960
  • 9
  • 20
1

You can try:

public static class BigIntegerExtensions
{
    public static byte[] ToByteArrayBigEndianUnsigned(this BigInteger bi, int minSize = 0)
    {
        byte[] bytes = bi.ToByteArray();

        int length;

        if (bytes[bytes.Length - 1] != 0)
        {
            if (minSize == 0 || minSize <= bytes.Length)
            {
                Array.Reverse(bytes);
                return bytes;
            }

            length = bytes.Length;
        }
        else
        {
            length = bytes.Length - 1;
        }

        var bytes2 = new byte[minSize == 0 ? length : Math.Max(minSize, length)];

        for (int i = 0, j = bytes2.Length - 1; i < length && j >= 0; i++, j--)
        {
            bytes2[j] = bytes[i];
        }

        return bytes2;
    }
}

var bi1 = BigInteger.Parse("18597082174523508716390621410767314599038866539779750637065684697259605002694360104971398651747704217448206242771805831180528356170981586469477958663193117845356353634469679095227815268434823260637917891539622982485837392495877800705071553435850492058570460745900129552907596604479063007676795998193064078987369363544131073880694736862904482385332020513837955197528182597410203652025183467149166026077910473816908590029574674997850683021938033561647681780168764842253700974777073181357779101690539999736174329578178742236883520017849893817175274405622018571899733008344137833140207194792223664500885734080606246950229");
var bi2 = BigInteger.Parse("65537");
var bytes1 = bi1.ToByteArrayBigEndianUnsigned();
var bytes2 = bi2.ToByteArrayBigEndianUnsigned();

var pars = new RSAParameters();
pars.Modulus = bytes1;
pars.Exponent = bytes2;

There are two differences about how BigInteger.ToByteArray() exports to byte[] and how RsaParameters expects its parameters: BigInteger is signed and little endian, so some Modulus have a 0 appended to make them positive (and for 1024 bits keys are 129 bytes long instead of 128) and the most significant digit is the last one, RsaParameters expects its parameters to be unsigned (so a 1024 bit key must be 128 bytes long) and big endian (so the most significant digit is the first one).

Note that importing the private key from BigInteger is even more complex :-)

Note 2: the minSize in ToByteArrayBigEndianUnsigned() is for importing private keys with InvariantQ.Length < Exponent.Length / 2. Ignore it.

xanatos
  • 109,618
  • 12
  • 197
  • 280
  • BigInteger ToByteArray() is Little Endian. RSAParameters values are Big Endian. You need to Array.Reverse before returning it. (You can't notice for 65537 since it's a palindrome in base 256) – bartonjs Jul 13 '18 at 16:38
  • @bartonjs Ah... Yes... You are right! :-) Corrected. – xanatos Jul 14 '18 at 07:45