The RSA algorithm is the first algorithm that can be used for both encryption and digital signature, and it is easy to understand and manipulate. RSA is the most widely researched public-key algorithm, from the proposed to now nearly 20 years, experienced a variety of attacks, gradually accepted by people, generally considered to be one of the best public key scheme at present. RSA's security relies on the factorization of large number of factors, but it does not theoretically prove that the difficulty of deciphering RSA is equivalent to the difficulty of large number decomposition.
The security of RSA relies on the decomposition of large numbers. Both the public and private keys are functions of two large primes (greater than 100 decimal digits). It is speculated that the difficulty of inferring clear text from a key and cipher is equivalent to decomposing the product of two large primes.
The creation of a key pair. Select two large primes, p and Q. Calculation:
n = p * Q
Then randomly select the Encryption key E (PS: The most commonly used e values are 3, 17, and 65537, Microsoft is using 65537, the use of any one of the 3 does not have security issues), requires E and (p-1) * (q-1) coprime. Finally, the Euclid algorithm is used to compute the decryption key D to meet
E * d = 1 (mod (p-1) * (q-1))
where N and D are also coprime. The number e and n are public keys, and D is the private key. Two primes p and Q no longer needed, should be discarded, do not let anyone know.
When encrypting information m (binary representation), first divide m into equal length data block M1, M2,..., mi, block length s, wherein 2^s <= N, s as large as possible. The corresponding ciphertext is:
ci = mi^e (mod n) (a)
The following calculations are made when decrypting:
mi = ci^d (mod n) (b)
. NET provides commonly used cryptographic algorithm classes, the class that supports RSA is RSACryptoServiceProvider (namespace: System.Security.Cryptography), but only public key encryption and private key decryption are supported. The RSACryptoServiceProvider class includes 8 properties, modulus, Exponent, P, Q, DP, DQ, Inverseq, D, and so on, where modulus and Exponent are public keys, and modulus and d are private keys. The RSACryptoServiceProvider class provides a way to export the public key, and also provides a way to export the private key, but the exported private key contains the above 8 properties, obviously it is not feasible to use RSACryptoServiceProvider to implement the private key encryption public key.
From 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 use the private key to encrypt the registration code or registration file, sent to the user, the user with the public key decryption registration code or registration file for legitimacy verification.
I use the internet to find a C # version of the large integer class BigInteger (I think this is the most efficient C # version of a large integer class) to implement private key encryption public key encryption (in fact, also fully support public rental encryption private key decryption), but did not use the class BigInteger large prime number generation function, Instead, use the class RSACryptoServiceProvider directly to generate large primes. The implementation of cryptographic functions and decryption functions is as follows:
/*
Function: Encrypts the specified string source with the specified private key (N,D)
*/
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 *, 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: Decrypts the specified string source with the specified public key (n,e)
*/
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 *, 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 process and the decryption procedure Code are as follows:
/*
The encryption process, where D, N is the RSACryptoServiceProvider generated D, modulus
*/
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, where E and n are RSACryptoServiceProvider generated exponent, modulus
*/
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);
}
C # Implementation of RSA algorithm based on private key encryption public key decryption