/// <summary> /// Default constructor /// </summary> /// <param name="p">First prime number</param> /// <param name="q">Second prime number</param> /// <param name="privateKey">Private key d</param> /// <param name="hashFunction">hashfunction to use in algorithm</param> /// <param name="ChecksNeeded">check if data is right </param> public RsaSignature(BigInteger p, BigInteger q, BigInteger privateKey, HashFunction hashFunction, bool ChecksNeeded) { if (ChecksNeeded) { if ((!p.CheckIfPrime()) || (!q.CheckIfPrime())) { throw new ArgumentException("p and q must be prime numbers!"); } //if privatekey = 1 then signature == h //if privateKey == phi(n) - 1; then s == 1 //if privateKey > phi(n) then there'll problem with multipl. inversion in equation d*e = 1 mod phi(n) if ((privateKey < 2) || (privateKey > (p - 1) * (q - 1) - 1)) { throw new ArgumentException("Private key should be 2 < < (p - 1) * (q - 1) - 1)!"); } //We need private key to be prime with phi(n) to find open key later if (!NumericAlgorithms.GCD(privateKey, (p - 1) * (q - 1)).Equals(1)) { throw new ArgumentException("D should be mutually prime with (p - 1) * (q - 1)"); } } Modulus = p * q; PublicExp = NumericAlgorithms.ExtendedGCD((p - 1) * (q - 1), privateKey); PrivateExp = privateKey; HashFunc = (hashFunction == HashFunction.MD5) ? null : new HashFunctionFactory().NewHashFunction(Modulus, hashFunction); }
private BigInteger[] Decrypt(BigInteger FirstPrime, BigInteger SecondPrime, BigInteger cipherText) { var publicKey = CalculatePublicKey(FirstPrime, SecondPrime); if (cipherText > publicKey) { throw new ArgumentException("c", "Ciphertext is larger than public key"); } BigInteger r = NumericAlgorithms.FastExp(cipherText, (FirstPrime + 1) / 4, FirstPrime); BigInteger s = NumericAlgorithms.FastExp(cipherText, (SecondPrime + 1) / 4, SecondPrime); BigInteger a, b; NumericAlgorithms.ExtendedGCD(FirstPrime, SecondPrime, out a, out b); //(a*p*r + b*q*s) % n BigInteger m1 = (a * FirstPrime * s + b * SecondPrime * r) % publicKey; if (m1 < 0) { m1 += publicKey; } BigInteger m2 = publicKey - m1; BigInteger m3 = (a * FirstPrime * s - b * SecondPrime * r) % publicKey; if (m3 < 0) { m3 += publicKey; } BigInteger m4 = publicKey - m3; return(new BigInteger[] { m1, m2, m3, m4 }); }
/// <summary> /// Hash "image" used in RSA digital signature algorithm /// </summary> /// <param name="message"></param> /// <param name="key"></param> /// <returns></returns> protected virtual BigInteger HashImage(BigInteger message, BigInteger key) { if (((message > 0) ? message : -message) >= Modulus) { throw new ArgumentException("Modulus p * q was too small."); } return(NumericAlgorithms.FastExp(message, key, Modulus)); }
private BigInteger GenerateHash(byte[] message) { var returnValue = startHashValue; for (int i = 0; i < message.Length; ++i) { returnValue = NumericAlgorithms.FastExp(returnValue + (BigInteger)message[i], 2, modulus); var x = returnValue.ToString(); } return(returnValue); }
private int[] Decrypt(int FirstPrime, int SecondPrime, int b, int cipherText) { var publicKey = CalculatePublicKey(FirstPrime, SecondPrime); if (cipherText > publicKey) { throw new ArgumentException("cipherText", "Ciphertext is larger then public key"); } var D = (b * b + (4 * cipherText)) % publicKey; int mp = NumericAlgorithms.FastExp(D, (FirstPrime + 1) / 4, FirstPrime); int mq = NumericAlgorithms.FastExp(D, (SecondPrime + 1) / 4, SecondPrime); NumericAlgorithms.ExtendedGCD(FirstPrime, SecondPrime, out int yp, out int yq); int d1, d2, d3, d4; d1 = (yp * FirstPrime * mq + yq * SecondPrime * mp) % publicKey; d1 = (d1 >= 0) ? d1 : NumericAlgorithms.NegativeMod(yp * FirstPrime * mq + yq * SecondPrime * mp, publicKey); // do { d1 += publicKey; } while (d1 <= 0); d2 = publicKey - d1; d3 = (yp * FirstPrime * mq - yq * SecondPrime * mp) % publicKey; d3 = (d3 >= 0) ? d3 : NumericAlgorithms.NegativeMod(yp * FirstPrime * mq - yq * SecondPrime * mp, publicKey); //do { d3 += publicKey; } while (d3 <= 0); d4 = publicKey - d3; d1 = Math.Abs(CalculateRoot(b, d1, publicKey)); d2 = Math.Abs(CalculateRoot(b, d2, publicKey)); d3 = Math.Abs(CalculateRoot(b, d3, publicKey)); d4 = Math.Abs(CalculateRoot(b, d4, publicKey)); return(new int[] { d1, d2, d3, d4 }); }
/// <summary> /// Encrypts a message /// </summary> /// <param name="FirstPrime"> First prime (part of secret key)</param> /// <param name="SecondPrime">Second prime (part of secret key)</param> /// <param name="Message">Message to encrypt</param> /// <returns></returns> private byte[] Encrypt(BigInteger FirstPrime, BigInteger SecondPrime, byte[] plainText) { return(NumericAlgorithms.FastExp(new BigInteger(plainText), 2, CalculatePublicKey(FirstPrime, SecondPrime)).ToByteArray()); }