RSA algorithm C # implemented based on private key encryption and Public Key decryption,
The RSA algorithm is the first algorithm that can be used for both encryption and digital signature, and is easy to understand and operate. RSA is the most widely studied public key algorithm. It has been nearly two decades since it was proposed. It has been tested by various attacks and is gradually accepted by people, it is generally regarded as one of the best public key solutions. The security of RSA depends on the factorization of large numbers, but it is not theoretically proved that the difficulty of deciphering RSA is equivalent to the difficulty of decomposing large numbers.
The security of RSA depends on the decomposition of large numbers. Both the public key and the private key are functions with two large prime numbers (more than 100 decimal digits. It is estimated that it is difficult to deduce plaintext from a key and ciphertext to separate the product of two prime numbers.
Generation of key pairs. Select two prime numbers, p and q. Computing:
N = p * q
Then randomly select the encryption key e (PS: The most common values of e are 3, 17, and 65537. Microsoft uses 65537, and none of the three has security issues ), e and (p-1) * (q-1) are required. Finally, the Euclid algorithm is used to calculate the decryption key d.
E * d = 1 (mod (p-1) * (q-1 ))
N and d must also be mutually dependent. Numbers e and n are public keys, and d is private keys. The two prime numbers p and q are no longer needed. They should be discarded and should not be known to anyone.
When encrypting information m (binary representation), we first divide m into long data blocks m1, m2 ,..., mi, block length s, where 2 ^ s <= n, s is as big as possible. The corresponding ciphertext is:
Ci = mi ^ e (mod n) ()
Perform the following calculation during decryption:
Mi = ci ^ d (mod n) (B)
. NET provides common encryption algorithm classes. The class supporting RSA is RSACryptoServiceProvider (namespace: System. Security. Cryptography), but only supports public key encryption and Private Key decryption. The RSACryptoServiceProvider class includes eight attributes: Modulus, Exponent, P, Q, DP, DQ, InverseQ, and D. Among them, Modulus and Exponent are public keys, while Modulus and D are private keys, the RSACryptoServiceProvider class provides the method for exporting the public key and the method for exporting the private key. However, the exported private key contains the above eight attributes. Obviously, using RSACryptoServiceProvider to encrypt the public key is not feasible.
According to the principle of RSA, public key encryption Private Key decryption and private key encryption Public Key decryption should be equivalent. In some cases, such as shared Software Encryption, we need to encrypt the registration code or registration file with the private key and send it to the user. The user uses the public key to decrypt the registration code or registration file for validity verification.
I am using BigInteger, a big integer class of C #, which I found on the Internet (I think this is the most efficient C # Big integer class) private Key Encryption (in fact, it fully supports public-rent encryption and Private Key decryption), but does not use the BigInteger-like large prime number generation function, instead directly uses the class RSACryptoServiceProvider to generate a large prime number. The encryption and decryption functions are implemented as follows:
/*
Function: uses the specified private key (n, d) to encrypt the specified string source.
*/
Private string EncryptString (string source, BigInteger d, BigInteger n)
{
Int len = source. Length;
Int len1 = 0;
Int blockLen = 0;
If (len % 128) = 0)
Len1 = len/128;
Else
Len1 = len/128 + 1;
String block = "";
String temp = "";
For (int I = 0; I <len1; I ++)
{
If (len >=128)
Blocklen= 128;
Else
BlockLen = len;
Block = source. Substring (I * 128, blockLen );
Byte [] oText = System. Text. Encoding. Default. GetBytes (block );
BigInteger biText = new BigInteger (oText );
BigInteger biEnText = biText. modPow (d, n );
String temp1 = biEnText. ToHexString ();
Temp + = temp1;
Len-= blockLen;
}
Return temp;
}
/*
Function: uses the specified public key (n, e) to decrypt the specified string source.
*/
Private string DecryptString (string source, BigInteger e, BigInteger n)
{
Int len = source. Length;
Int len1 = 0;
Int blockLen = 0;
If (len % 256) = 0)
Len1 = len/256;
Else
Len1 = len/256 + 1;
String block = "";
String temp = "";
For (int I = 0; I <len1; I ++)
{
If (len >=256)
Blocklen= 256;
Else
BlockLen = len;
Block = source. Substring (I * 256, blockLen );
BigInteger biText = new BigInteger (block, 16 );
BigInteger biEnText = biText. modPow (e, n );
String temp1 = System. Text. Encoding. Default. GetString (biEnText. getBytes ());
Temp + = temp1;
Len-= blockLen;
}
Return temp;
}
The encryption and decryption process code is as follows:
/*
In the encryption process, d and n are the D and Modulus generated by RSACryptoServiceProvider.
*/
Private string EncryptProcess (string source, string d, string n)
{
Byte [] N = Convert. FromBase64String (n );
Byte [] D = Convert. FromBase64String (d );
BigInteger biN = new BigInteger (N );
BigInteger biD = new BigInteger (D );
Return EncryptString (source, biD, biN );
}
/*
The decryption process. e and n are the Exponent and Modulus generated by RSACryptoServiceProvider.
*/
Private string DecryptProcess (string source, string e, string n)
{
Byte [] N = Convert. FromBase64String (n );
Byte [] E = Convert. FromBase64String (e );
BigInteger biN = new BigInteger (N );
BigInteger biE = new BigInteger (E );
Return DecryptString (source, biE, biN );
}