前阵子写的,RSA的算法。
/**/
/*
* A wrapper of Rsa algorithm
*/
public class Rsa : _Rsa
... {
private RsaPublicProvider publicProvider;
private RsaPrivateProvider privateProvider;
public Rsa(int e, int pq, int d)
: base(e, pq, d) ...{
this.publicProvider = new RsaPublicProvider(this);
this.privateProvider = new RsaPrivateProvider(this);
}
public RsaPublicProvider RsaPublicProvider ...{ get ...{ return this.publicProvider; } }
public RsaPrivateProvider RsaPrivateProvider ...{ get ...{ return this.privateProvider; } }
}
/**/ /*
* Rsa algorithm
*/
public class _Rsa
... {
private int e; // public key A
private int pq; // public key B
private int d; // private key
protected _Rsa(int e, int pq, int d) ...{
this.e = e;
this.pq = pq;
this.d = d;
}
public int[] PublicKey ...{
get ...{ return new int[] ...{ e, pq }; }
}
public int[] PrivateKey ...{
get ...{ return new int[] ...{ d, pq }; }
}
/**//* Encryptino algorithm:
* encrypt(T) = (T^E) mod PQ */
public int[] Encrypt(int[] text) ...{
int[] cipher = new int[text.Length];
for (int i = 0; i < cipher.Length; i++) ...{
cipher[i] = CalculateMod(text[i], e, pq);
}
return cipher;
}
public unsafe void Encrypt(int* text, int* cipher, int length) ...{
for (int i = 0; i < length; i++) ...{
cipher[i] = CalculateMod(text[i], e, pq);
}
}
/**//* Decryptino algorithm:
* decrypt(C) = (C^D) mod PQ */
public int[] Decrypt(int[] cipher) ...{
int[] text = new int[cipher.Length];
for (int i = 0; i < text.Length; i++) ...{
text[i] = CalculateMod(cipher[i], d, pq);
}
return text;
}
public unsafe void Decrypt(int* cipher, int* text, int length) ...{
for (int i = 0; i < length; i++) ...{
text[i] = CalculateMod(cipher[i], d, pq);
}
}
/**//*
* Calculate (a^b mod c)
*/
private unsafe int CalculateMod(int a, int b, int c) ...{
/**//* Compute base 2 expression of b
* i.e., 2753 = 101011000001 base 2
* = 1 + 2^6 + 2^7 + 2^9 + 2^11
* = 1 + 64 + 128 + 512 + 2048
*/
int* b2 = stackalloc int[31];
for (int i = b, j = 0; i > 0; i = i >> 1, j++) ...{
b2[j] = i % 2;
}
/**//*
* Consider this table of powers of 855:
* 855^1 = 855 (mod 3233)
* 855^2 = 367 (mod 3233)
* 855^4 = 367^2 (mod 3233) = 2136 (mod 3233)
* 855^8 = 2136^2 (mod 3233) = 733 (mod 3233)
* 855^16 = 733^2 (mod 3233) = 611 (mod 3233)
* 855^32 = 611^2 (mod 3233) = 1526 (mod 3233)
* 855^64 = 1526^2 (mod 3233) = 916 (mod 3233)
* 855^128 = 916^2 (mod 3233) = 1709 (mod 3233)
* 855^256 = 1709^2 (mod 3233) = 1282 (mod 3233)
* 855^512 = 1282^2 (mod 3233) = 1160 (mod 3233)
* 855^1024 = 1160^2 (mod 3233) = 672 (mod 3233)
* 855^2048 = 672^2 (mod 3233) = 2197 (mod 3233)
*
* Given the above, we know this:
*
* 855^2753 (mod 3233)
* = 855^(1 + 64 + 128 + 512 + 2048) (mod 3233)
* = 855^1 * 855^64 * 855^128 * 855^512 * 855^2048 (mod 3233)
* = 855 * 916 * 1709 * 1160 * 2197 (mod 3233)
* = 794 * 1709 * 1160 * 2197 (mod 3233)
* = 2319 * 1160 * 2197 (mod 3233)
* = 184 * 2197 (mod 3233)
* = 123 (mod 3233)
* = 123
*
* Since int.MaxValue * int.MaxValue < long.MaxValue, there will not
* be aithmetic overflow there. Remove check for performance increment
*/
long mod = 1; long temp = a % c;
unchecked ...{
for (long i = 0; i < 31; i++) ...{
if (b2[i] == 1) ...{
mod = (mod * temp) % c;
}
temp = temp * temp % c;
}
}
return (int)mod;
}
}
public static class RsaFactory
... {
public static Rsa GenerateRsaKeyPair(int minimalKeyStrength) ...{
int topNumber = 1 << minimalKeyStrength;
int[] primeNumbers = GeneratePrimeNumberList(topNumber);
Random ran = new Random();
// Randomly select two distinct prime numbers p, q such that p*q > topNumber
int p = 2, q = 2, pq = 4;
while ((p == q) || (pq = p * q) < topNumber) ...{
p = primeNumbers[ran.Next(1, primeNumbers.Length - 1)];
q = primeNumbers[ran.Next(1, primeNumbers.Length - 1)];
}
// Use Euclidean algorithm to determine e
int t = (p - 1) * (q - 1);
int e = 0;
for (e = 3; e <= topNumber; e++) ...{
if (GetGreatestCommonDivisor(t, e) == 1) ...{
break;
}
}
// Compute d such that d*e = 1 + k*t for some integer k
int d = 1;
for (int k = 2; k < topNumber; k++) ...{
int sum = 1 + k * t;
if (sum % e == 0) ...{
d = sum / e;
break;
}
}
return new Rsa(e, pq, d);
}
public static int[] GeneratePrimeNumberList(int topNumber) ...{
List<int> primeNumbers = new List<int>();
for (int i = 2; i < topNumber; i++) ...{
bool divisible = false;
foreach (int number in primeNumbers)
if (i % number == 0) ...{
divisible = true;
}
if (!divisible) ...{
primeNumbers.Add(i);
}
}
return primeNumbers.ToArray();
}
public static bool IsPrime(int number) ...{
bool isPrime = true;
for (int i = 2; i <= Math.Sqrt(number) && isPrime; i++) ...{
isPrime = (number % i != 0);
}
return isPrime;
}
public static int GetGreatestCommonDivisor(int a, int b) ...{
while (b != 0) ...{
if (a > b) ...{
a = a - b;
} else ...{
b = b - a;
}
}
return a;
}
}
* A wrapper of Rsa algorithm
*/
public class Rsa : _Rsa
... {
private RsaPublicProvider publicProvider;
private RsaPrivateProvider privateProvider;
public Rsa(int e, int pq, int d)
: base(e, pq, d) ...{
this.publicProvider = new RsaPublicProvider(this);
this.privateProvider = new RsaPrivateProvider(this);
}
public RsaPublicProvider RsaPublicProvider ...{ get ...{ return this.publicProvider; } }
public RsaPrivateProvider RsaPrivateProvider ...{ get ...{ return this.privateProvider; } }
}
/**/ /*
* Rsa algorithm
*/
public class _Rsa
... {
private int e; // public key A
private int pq; // public key B
private int d; // private key
protected _Rsa(int e, int pq, int d) ...{
this.e = e;
this.pq = pq;
this.d = d;
}
public int[] PublicKey ...{
get ...{ return new int[] ...{ e, pq }; }
}
public int[] PrivateKey ...{
get ...{ return new int[] ...{ d, pq }; }
}
/**//* Encryptino algorithm:
* encrypt(T) = (T^E) mod PQ */
public int[] Encrypt(int[] text) ...{
int[] cipher = new int[text.Length];
for (int i = 0; i < cipher.Length; i++) ...{
cipher[i] = CalculateMod(text[i], e, pq);
}
return cipher;
}
public unsafe void Encrypt(int* text, int* cipher, int length) ...{
for (int i = 0; i < length; i++) ...{
cipher[i] = CalculateMod(text[i], e, pq);
}
}
/**//* Decryptino algorithm:
* decrypt(C) = (C^D) mod PQ */
public int[] Decrypt(int[] cipher) ...{
int[] text = new int[cipher.Length];
for (int i = 0; i < text.Length; i++) ...{
text[i] = CalculateMod(cipher[i], d, pq);
}
return text;
}
public unsafe void Decrypt(int* cipher, int* text, int length) ...{
for (int i = 0; i < length; i++) ...{
text[i] = CalculateMod(cipher[i], d, pq);
}
}
/**//*
* Calculate (a^b mod c)
*/
private unsafe int CalculateMod(int a, int b, int c) ...{
/**//* Compute base 2 expression of b
* i.e., 2753 = 101011000001 base 2
* = 1 + 2^6 + 2^7 + 2^9 + 2^11
* = 1 + 64 + 128 + 512 + 2048
*/
int* b2 = stackalloc int[31];
for (int i = b, j = 0; i > 0; i = i >> 1, j++) ...{
b2[j] = i % 2;
}
/**//*
* Consider this table of powers of 855:
* 855^1 = 855 (mod 3233)
* 855^2 = 367 (mod 3233)
* 855^4 = 367^2 (mod 3233) = 2136 (mod 3233)
* 855^8 = 2136^2 (mod 3233) = 733 (mod 3233)
* 855^16 = 733^2 (mod 3233) = 611 (mod 3233)
* 855^32 = 611^2 (mod 3233) = 1526 (mod 3233)
* 855^64 = 1526^2 (mod 3233) = 916 (mod 3233)
* 855^128 = 916^2 (mod 3233) = 1709 (mod 3233)
* 855^256 = 1709^2 (mod 3233) = 1282 (mod 3233)
* 855^512 = 1282^2 (mod 3233) = 1160 (mod 3233)
* 855^1024 = 1160^2 (mod 3233) = 672 (mod 3233)
* 855^2048 = 672^2 (mod 3233) = 2197 (mod 3233)
*
* Given the above, we know this:
*
* 855^2753 (mod 3233)
* = 855^(1 + 64 + 128 + 512 + 2048) (mod 3233)
* = 855^1 * 855^64 * 855^128 * 855^512 * 855^2048 (mod 3233)
* = 855 * 916 * 1709 * 1160 * 2197 (mod 3233)
* = 794 * 1709 * 1160 * 2197 (mod 3233)
* = 2319 * 1160 * 2197 (mod 3233)
* = 184 * 2197 (mod 3233)
* = 123 (mod 3233)
* = 123
*
* Since int.MaxValue * int.MaxValue < long.MaxValue, there will not
* be aithmetic overflow there. Remove check for performance increment
*/
long mod = 1; long temp = a % c;
unchecked ...{
for (long i = 0; i < 31; i++) ...{
if (b2[i] == 1) ...{
mod = (mod * temp) % c;
}
temp = temp * temp % c;
}
}
return (int)mod;
}
}
public static class RsaFactory
... {
public static Rsa GenerateRsaKeyPair(int minimalKeyStrength) ...{
int topNumber = 1 << minimalKeyStrength;
int[] primeNumbers = GeneratePrimeNumberList(topNumber);
Random ran = new Random();
// Randomly select two distinct prime numbers p, q such that p*q > topNumber
int p = 2, q = 2, pq = 4;
while ((p == q) || (pq = p * q) < topNumber) ...{
p = primeNumbers[ran.Next(1, primeNumbers.Length - 1)];
q = primeNumbers[ran.Next(1, primeNumbers.Length - 1)];
}
// Use Euclidean algorithm to determine e
int t = (p - 1) * (q - 1);
int e = 0;
for (e = 3; e <= topNumber; e++) ...{
if (GetGreatestCommonDivisor(t, e) == 1) ...{
break;
}
}
// Compute d such that d*e = 1 + k*t for some integer k
int d = 1;
for (int k = 2; k < topNumber; k++) ...{
int sum = 1 + k * t;
if (sum % e == 0) ...{
d = sum / e;
break;
}
}
return new Rsa(e, pq, d);
}
public static int[] GeneratePrimeNumberList(int topNumber) ...{
List<int> primeNumbers = new List<int>();
for (int i = 2; i < topNumber; i++) ...{
bool divisible = false;
foreach (int number in primeNumbers)
if (i % number == 0) ...{
divisible = true;
}
if (!divisible) ...{
primeNumbers.Add(i);
}
}
return primeNumbers.ToArray();
}
public static bool IsPrime(int number) ...{
bool isPrime = true;
for (int i = 2; i <= Math.Sqrt(number) && isPrime; i++) ...{
isPrime = (number % i != 0);
}
return isPrime;
}
public static int GetGreatestCommonDivisor(int a, int b) ...{
while (b != 0) ...{
if (a > b) ...{
a = a - b;
} else ...{
b = b - a;
}
}
return a;
}
}
public
interface
IRsaProvider
... {
int[] Key ...{ get;}
byte[] Transform(byte[] input);
}
public class RsaPrivateProvider : IRsaProvider, ICloneable
... {
private Rsa rsa;
public RsaPrivateProvider(Rsa rsa) ...{
this.rsa = rsa;
}
public int[] Key ...{
get ...{ return this.rsa.PrivateKey; }
}
public byte[] Transform(byte[] input) ...{
int[] input2 = Converter.ConvertBytesToInts(input);
int[] output = rsa.Encrypt(input2);
return Converter.ConvertIntsToBytes(output);
}
public object Clone() ...{
return new RsaPrivateProvider(this.rsa);
}
}
public class RsaPublicProvider : IRsaProvider, ICloneable
... {
private Rsa rsa;
public RsaPublicProvider(Rsa rsa) ...{
this.rsa = rsa;
}
public int[] Key ...{
get ...{ return this.rsa.PublicKey; }
}
public byte[] Transform(byte[] input) ...{
int[] input2 = Converter.ConvertBytesToInts(input);
int[] output = rsa.Decrypt(input2);
return Converter.ConvertIntsToBytes(output);
}
public object Clone() ...{
return new RsaPrivateProvider(this.rsa);
}
}
/**/ /*
* Convert byte array from and to an int array
*/
public static class Converter
... {
public static int[] ConvertBytesToInts(byte[] bytes) ...{
int[] ints = new int[bytes.Length / 4];
for (int i = 0; i < ints.Length; i++) ...{
ints[i] = bytes[i * 4] |
bytes[i * 4 + 1] << 8 |
bytes[i * 4 + 2] << 16 |
bytes[i * 4 + 3] << 24;
}
return ints;
}
public static byte[] ConvertIntsToBytes(int[] ints) ...{
byte[] bytes = new byte[ints.Length * 4];
for (int i = 0; i < ints.Length; i++) ...{
bytes[4 * i] = (byte)ints[i];
bytes[4 * i + 1] = (byte)(ints[i] >> 8);
bytes[4 * i + 2] = (byte)(ints[i] >> 16);
bytes[4 * i + 3] = (byte)(ints[i] >> 24);
}
return bytes;
}
}
... {
int[] Key ...{ get;}
byte[] Transform(byte[] input);
}
public class RsaPrivateProvider : IRsaProvider, ICloneable
... {
private Rsa rsa;
public RsaPrivateProvider(Rsa rsa) ...{
this.rsa = rsa;
}
public int[] Key ...{
get ...{ return this.rsa.PrivateKey; }
}
public byte[] Transform(byte[] input) ...{
int[] input2 = Converter.ConvertBytesToInts(input);
int[] output = rsa.Encrypt(input2);
return Converter.ConvertIntsToBytes(output);
}
public object Clone() ...{
return new RsaPrivateProvider(this.rsa);
}
}
public class RsaPublicProvider : IRsaProvider, ICloneable
... {
private Rsa rsa;
public RsaPublicProvider(Rsa rsa) ...{
this.rsa = rsa;
}
public int[] Key ...{
get ...{ return this.rsa.PublicKey; }
}
public byte[] Transform(byte[] input) ...{
int[] input2 = Converter.ConvertBytesToInts(input);
int[] output = rsa.Decrypt(input2);
return Converter.ConvertIntsToBytes(output);
}
public object Clone() ...{
return new RsaPrivateProvider(this.rsa);
}
}
/**/ /*
* Convert byte array from and to an int array
*/
public static class Converter
... {
public static int[] ConvertBytesToInts(byte[] bytes) ...{
int[] ints = new int[bytes.Length / 4];
for (int i = 0; i < ints.Length; i++) ...{
ints[i] = bytes[i * 4] |
bytes[i * 4 + 1] << 8 |
bytes[i * 4 + 2] << 16 |
bytes[i * 4 + 3] << 24;
}
return ints;
}
public static byte[] ConvertIntsToBytes(int[] ints) ...{
byte[] bytes = new byte[ints.Length * 4];
for (int i = 0; i < ints.Length; i++) ...{
bytes[4 * i] = (byte)ints[i];
bytes[4 * i + 1] = (byte)(ints[i] >> 8);
bytes[4 * i + 2] = (byte)(ints[i] >> 16);
bytes[4 * i + 3] = (byte)(ints[i] >> 24);
}
return bytes;
}
}