RSA algorithm and CRT in program

Explained the way to compute the RSA encryption and decryption in C sharp program, and also the way to calculate of the private key provided you know the public key, P and Q by using the extended Euclidean algorithm, reference to the Python implementation of RSA.

Testing material with RSA

For understand the using CRT with RSA, refer to this Link. And I am not going to explain the detail as I am not quite familiar with the math in detail myself.

As long as CRT will speed up the computing of RSA, here suppose we have all the detail as Public modulus, Public Exponent, P, Q, DP1, DQ1 and PQ, we use example as below, as I have tested it, it is valid,

0x80 length of public modulus, below is the value.

83934BA65BFC8C67C9394F1AFA9D3F1025BD8DC13B566B364463A6E2F772391C722D070BA4ED2CDC1A46DD58F1C187BA6153472B63FDF568B32D34F4464528E6711BDE6DC27A8EDCD0631014CC5855DBD6DE73B506044B0B0F2F06082AF68F185F1F88804CF9A71B04864453F029701E2E976340911E97C0B7127DDDD07C4AB7

Public Exponent,below is the value

010001

0x40 – length of P, below is the value,

BBC7927F74C2A55E988059F01FF75011A9ED035C1133D1689079E6AADEDDC641FF7949B15795712A4BDC66FD881D33A1A86FA257291BFF9BB9623410F0D16797

0x40– length of Q, below is the value,

B3607464B59AD805B5E46B47E73C59125140F41DD7384281F11092BF8216D5E3A4F02BA06ECEE0E2A0D9EB511B5AEACA26CF2FFEB46F290B5806556BF39199E1

0x40– length of DP1, below is the value,

B4F74D78E5D69C3680F3D93930255095E55454538B048C40A053CA784BD621360376290DEEE147B14270C3147CF3DF8960E14CEB80E3C9BF92B650852F00303B

0x40– length of DQ1, below is the value,

14DD484C9A8F1B4776C3CDF2BC23D9DC76950E9016039640D5106F71552960D1ACD2BED057733AD7418C7781A4A3EBA17DE8259603D8D6365A93CA05D77BFD21

0x40– length of PQ, below is the value,

998F654098C0B83C27D4E55C562FEB9F3774D1B5F850422BDA573973CEBA520614E74527B9CF6D874181741DD3C01E4A488782BC3194EACCA8F6F78661D76C75

Private exponent(d) as below,

4EDD50F0CC1E1A4273386893F137A37F183FFFE19CA175EDB71C4C01AAF3CA0BA4DC1C66FC5A351350A4BD33FCE455687FC19CDD03384B8A902B3E9C542A4C12C812D25464DAB78815D2C8287FFA35949697B83EEEC437F6C92FA22149DDD5336C7A8A10CF165F3EED42F4FBFC362493D7D68C3641A0D36CFA015EBB6188DE81

We use below value as the plain text to encrypt:

004AA63B4EB37767D863C8EF8139E1DE8A04DDD7FC96C8C0897B0094F95736DA28C79B8862F636327CABD310251BB2169F2A9692D5C434B9CE627E88FD3591AED6B693557D60A44F1CA53321B83F9C4EC11CF8F75F46AD39ECD318542299587E1A4638AF03F98C338F0043E2DD917F4C2CC67B490FE7323A25BE480B7BED469E

Encrypted text as below,

6ED55DE6502C37EC2D4AA5B88752EEE88F89F246AE49432B4C02058CFADAB08A716049EDC04BE4CC1B40C889C3F726671A5E5CFD5CAEECAE01DB5FA06B7745DC7DE56818D2D0179F50EAF9C328CAB16303D5D47E30A98F477B9A9C76AE4017568F341944A832A0CF747A8FB93322D884D7F9D0DBE3737C39E44BF0954090ACD2

Can use this link to verify the RSA encryption and decryption result.

Verify the CRT parameters are valid

The interface of the RSA computing GUI is as below screenshot shows,

RSA_Calculator

Make sure you have the correct version Visual studio to import "System.Numerics" support. as below screenshot,

RSA_Calculator_Numerics


To convert from hex string on the GUI to the byte array, can refer to this Link, by using below methods,

public static byte[] ConvertToByteArray(string value)

Convert all the RSA parameters to the BigIntegers,

BigInteger P = Program.FromBigEndian(P2);
BigInteger Q = Program.FromBigEndian(Q2);
BigInteger DP = Program.FromBigEndian(DP2);
BigInteger DQ = Program.FromBigEndian(DQ2);
BigInteger InverseQ = Program.FromBigEndian(InverseQ2);
BigInteger E = Program.FromBigEndian(Exponent2);
BigInteger M = Program.FromBigEndian(Modulus2);
BigInteger M1 = BigInteger.Multiply(P, Q); // M = P*Q

Verify M = P*Q

if (M1.CompareTo(M) == 0)
{
    //MessageBox.Show("Modulus is correct!");
}
else
{
    MessageBox.Show("Modulus is not correct as M!=P*Q");
    return;
}

Calculate the private key D,

BigInteger PMinus1 = BigInteger.Subtract(P, BigInteger.One); // P-1
BigInteger QMinus1 = BigInteger.Subtract(Q, BigInteger.One); // Q-1
BigInteger Phi = BigInteger.Multiply(PMinus1, QMinus1);
BigInteger D1 = Program.modinv(E, Phi);
Here the Program.modinv(E, Phi) is to use the Extended Euclidean algorithm to calculate the modular inverse, the result is the private key D, E is the public key, refer to this link. The source code is as below,

public static BigInteger modinv(BigInteger u, BigInteger v)
{
   BigInteger inv, u1, u3, v1, v3, t1, t3, q;
   BigInteger iter;
   /* Step X1. Initialise */
   u1 = 1;
   u3 = u;
   v1 = 0;
   v3 = v;
   /* Remember odd/even iterations */
   iter = 1;
   /* Step X2. Loop while v3 != 0 */
   while (v3 != 0)
   {
       /* Step X3. Divide and "Subtract" */
       q = u3 / v3;
       t3 = u3 % v3;
       t1 = u1 + q * v1;
       /* Swap */
       u1 = v1; v1 = t1; u3 = v3; v3 = t3;
       iter = -iter;
   }
   /* Make sure u3 = gcd(u,v) == 1 */
   if (u3 != 1)
       return 0;   /* Error: No inverse exists */
       /* Ensure a positive result */
       if (iter < 0)
           inv = v - u1;
       else
           inv = u1;
       return inv;
}

After calculate the private key D, display on the GUI.

Verify the DQ,

BigInteger DQ1 = BigInteger.Remainder(D, QMinus1); // dQ = (1/e) mod (q-1)
if (DQ1.CompareTo(DQ) == 0)
{
    //Console.WriteLine("  DQ Ok :)");
}
else
{
    MessageBox.Show("DQ1 is not correct as dQ = (1/e) mod (q-1)");
    return;
}

Verify DP,

BigInteger DP1 = BigInteger.Remainder(D, PMinus1); // dP = (1/e) mod (p-1)
if (DP1.CompareTo(DP) == 0)
{
    //Console.WriteLine("  DP Ok :)");
}
else
{
    MessageBox.Show("DP1 is not correct as dP != (1/e) mod (p-1)");
    return;
}

Verify PQ,

//qInv = (1/q) mod p
BigInteger InverseQ1 = Program.modinv(Q, P);
if (InverseQ1.CompareTo(InverseQ) == 0)
{
   //Console.WriteLine("  qInv = (1/q) mod p Ok :)");
}
else
{
   MessageBox.Show("InverseQ1 is not correct as qInv = (1/q) mod p");
   return;
}

RSA encryption and decryption

By using the C# function to encrypt and decrypt, there will be length restriction, 1024 bit length key may only encrypt 117 bytes material, refer to this link (Modulus size - 11. (11 bytes is the minimum padding possible.)). ,

rsa.ImportParameters(Program.key);
byte[] encoded = rsa.Encrypt(input, false);
//   byte[] encoded = rsa.Decrypt(input, false);

instead I am using the BigInteger calculation, but not sure it will work in all the case, but at least it works at my example material above,

BigInteger c = Program.FromBigEndian(input);
BigInteger m = BigInteger.ModPow(c, D, M); //decrypt
//BigInteger c = BigInteger.ModPow(m, E, M); //encrypt if it is encryption, it will like this line..

byte[] Plaintext = ConvertToByteArray(m.ToString("X"));

if (Plaintext[0] == 0x0)
{
    byte[] newPlaintext = new byte[Plaintext.Length - 1]; //remove the first 0x00
    Array.Copy(Plaintext, 1, newPlaintext, 0, Plaintext.Length - 1);
    result_txt.Text = ByteArrayToHex(newPlaintext);  //remove first 0
}
else
{
    result_txt.Text = ByteArrayToHex(Plaintext);
}

String, Array, BigInteger convert in process

As above mentioned, to convert from hex string on the GUI to the byte array, can refer to this Link, by using below methods,

public static byte[] ConvertToByteArray(string value)
After converted to byte array, then converted to BigInteger, here if the highest bit is 1, needs to add 0x00 at the beginning to prevent the negative value, and we can see there is Array.Reverse() function call, it seems Microsoft BigInteger is LittleEndian,

public static BigInteger FromBigEndian(byte[] p)
{
    Array.Reverse(p);
    if (p[p.Length - 1] > 127)
    {
       Array.Resize(ref p, p.Length + 1);  //this is to prevent the negative value.
       p[p.Length - 1] = 0;
    }
    return new BigInteger(p);
}

It is much easier to convert from BigInteger to the hex string and display on the GUI,

byte[] C = ConvertToByteArray(c.ToString("X"));
result_txt.Text = ByteArrayToHex(C);

RSA compute in Python

There is Python program available online to calculate RSA, refer to this Link, and source code download from Here. The software screenshot is as below,

RSA_Calculator_Python




Reference:

1, RSA Algorithm in Wiki

2, Extended Euclidean algorithm in Wiki

3, Using the CRT with RSA

4, Finding the modular inverse  

5,  RSACryptoServiceProvider.Encrypt Method (Byte[], Boolean)

6, Big number equation calculation

7, how-to-calculate-d-for-rsa-encryption-from-p-q-and-e

8,  http://www.di-mgt.com.au/euclidean.html#extendedeuclidean

9, http://www.di-mgt.com.au/crt_rsa.html

10, Why is RSAParameters Modulus not equal product of P and Q?

11, Mapping RSA Encryption Parameters from CRT (Chinese remainder theorem) to .NET format

12, RSA: Private key calculation with Extended Euclidean Algorithm

13, RSA Encryption Problem [Size of payload data]

14, Signing a byte array of 128 bytes with RSA in C sharp

15, Bad length in RSACryptoserviceProvider 

16, Converting Hex String To Corresponding Byte Array Using C#

Below references are for the Python implement RSA computing,

17, http://nmichaels.org/rsa.py

18, https://pypi.python.org/pypi/rsa#downloads

19, https://stuvel.eu/python-rsa-doc/usage.html#key-size-requirements

20, https://bitbucket.org/nmichaels/rsatool/src

21, https://pypi.python.org/pypi/pycrypto

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值