/// <summary> /// Probabilistic prime test based on Rabin-Miller's test /// </summary> /// <param name="n" type="BigInteger.BigInteger"> /// <para> /// The number to test. /// </para> /// </param> /// <param name="confidence" type="int"> /// <para> /// The number of chosen bases. The test has at least a /// 1/4^confidence chance of falsely returning True. /// </para> /// </param> /// <returns> /// <para> /// True if "this" is a strong pseudoprime to randomly chosen bases. /// </para> /// <para> /// False if "this" is definitely NOT prime. /// </para> /// </returns> public static bool RabinMillerTest(BigInteger n, ConfidenceFactor confidence) { int bits = n.BitCount (); int t = GetSPPRounds (bits, confidence); // n - 1 == 2^s * r, r is odd BigInteger n_minus_1 = n - 1; int s = n_minus_1.LowestSetBit (); BigInteger r = n_minus_1 >> s; BigInteger.ModulusRing mr = new BigInteger.ModulusRing (n); // Applying optimization from HAC section 4.50 (base == 2) // not a really random base but an interesting (and speedy) one BigInteger y = null; // FIXME - optimization disable for small primes due to bug #81857 if (n.BitCount () > 100) y = mr.Pow (2, r); // still here ? start at round 1 (round 0 was a == 2) for (int round = 0; round < t; round++) { if ((round > 0) || (y == null)) { BigInteger a = null; // check for 2 <= a <= n - 2 // ...but we already did a == 2 previously as an optimization do { a = BigInteger.GenerateRandom (bits); } while ((a <= 2) && (a >= n_minus_1)); y = mr.Pow (a, r); } if (y == 1) continue; for (int j = 0; ((j < s) && (y != n_minus_1)); j++) { y = mr.Pow (y, 2); if (y == 1) return false; } if (y != n_minus_1) return false; } return true; }
private static int GetSPPRounds(BigInteger bi, ConfidenceFactor confidence) { int bc = bi.BitCount(); int Rounds; // Data from HAC, 4.49 if (bc <= 100) Rounds = 27; else if (bc <= 150) Rounds = 18; else if (bc <= 200) Rounds = 15; else if (bc <= 250) Rounds = 12; else if (bc <= 300) Rounds = 9; else if (bc <= 350) Rounds = 8; else if (bc <= 400) Rounds = 7; else if (bc <= 500) Rounds = 6; else if (bc <= 600) Rounds = 5; else if (bc <= 800) Rounds = 4; else if (bc <= 1250) Rounds = 3; else Rounds = 2; switch (confidence) { case ConfidenceFactor.ExtraLow: Rounds >>= 2; return Rounds != 0 ? Rounds : 1; case ConfidenceFactor.Low: Rounds >>= 1; return Rounds != 0 ? Rounds : 1; case ConfidenceFactor.Medium: return Rounds; case ConfidenceFactor.High: return Rounds << 1; case ConfidenceFactor.ExtraHigh: return Rounds << 2; case ConfidenceFactor.Provable: throw new Exception("The Rabin-Miller test can not be executed in a way such that its results are provable"); default: throw new ArgumentOutOfRangeException("confidence"); } }
public static bool Test (BigInteger n, ConfidenceFactor confidence) { // Rabin-Miller fails with smaller primes (at least with our BigInteger code) if (n.BitCount () < 33) return SmallPrimeSppTest (n, confidence); else return RabinMillerTest (n, confidence); }
/// <summary> /// Probabilistic prime test based on Rabin-Miller's test /// </summary> /// <param name="bi" type="BigInteger.BigInteger"> /// <para> /// The number to test. /// </para> /// </param> /// <param name="confidence" type="int"> /// <para> /// The number of chosen bases. The test has at least a /// 1/4^confidence chance of falsely returning True. /// </para> /// </param> /// <returns> /// <para> /// True if "this" is a strong pseudoprime to randomly chosen bases. /// </para> /// <para> /// False if "this" is definitely NOT prime. /// </para> /// </returns> public static bool RabinMillerTest (BigInteger bi, ConfidenceFactor confidence) { int Rounds = GetSPPRounds (bi, confidence); // calculate values of s and t BigInteger p_sub1 = bi - 1; int s = p_sub1.LowestSetBit (); BigInteger t = p_sub1 >> s; int bits = bi.BitCount (); BigInteger a = null; BigInteger.ModulusRing mr = new BigInteger.ModulusRing (bi); // Applying optimization from HAC section 4.50 (base == 2) // not a really random base but an interesting (and speedy) one BigInteger b = mr.Pow (2, t); if (b != 1) { bool result = false; for (int j=0; j < s; j++) { if (b == p_sub1) { // a^((2^j)*t) mod p = p-1 for some 0 <= j <= s-1 result = true; break; } b = (b * b) % bi; } if (!result) return false; } // still here ? start at round 1 (round 0 was a == 2) for (int round = 1; round < Rounds; round++) { while (true) { // generate a < n a = BigInteger.GenerateRandom (bits); // make sure "a" is not 0 (and not 2 as we have already tested that) if (a > 2 && a < bi) break; } if (a.GCD (bi) != 1) return false; b = mr.Pow (a, t); if (b == 1) continue; // a^t mod p = 1 bool result = false; for (int j = 0; j < s; j++) { if (b == p_sub1) { // a^((2^j)*t) mod p = p-1 for some 0 <= j <= s-1 result = true; break; } b = (b * b) % bi; } if (!result) return false; } return true; }
public override byte[] DecryptValue(byte[] rgb) { if (m_disposed) { throw new ObjectDisposedException("private key"); } // decrypt operation is used for signature if (!keypairGenerated) { GenerateKeyPair(); } BigInteger input = new BigInteger(rgb); BigInteger r = null; // we use key blinding (by default) against timing attacks if (keyBlinding) { // x = (r^e * g) mod n // *new* random number (so it's timing is also random) r = BigInteger.GenerateRandom(n.BitCount()); input = r.ModPow(e, n) * input % n; } BigInteger output; // decrypt (which uses the private key) can be // optimized by using CRT (Chinese Remainder Theorem) if (isCRTpossible) { // m1 = c^dp mod p BigInteger m1 = input.ModPow(dp, p); // m2 = c^dq mod q BigInteger m2 = input.ModPow(dq, q); BigInteger h; if (m2 > m1) { // thanks to benm! h = p - ((m2 - m1) * qInv % p); output = m2 + q * h; } else { // h = (m1 - m2) * qInv mod p h = (m1 - m2) * qInv % p; // m = m2 + q * h; output = m2 + q * h; } } else { // m = c^d mod n output = input.ModPow(d, n); } if (keyBlinding) { // Complete blinding // x^e / r mod n output = output * r.ModInverse(n) % n; r.Clear(); } byte[] result = output.GetBytes(); // zeroize values input.Clear(); output.Clear(); return(result); }
void setStatusBar() { // create status line string string s = textOutputPresentation.textBox.Text; string label = ""; if (Input is string) { var value = Input as string; if (Regex.IsMatch(value, @"^-?\d+$")) { try { input = BigInteger.Parse(value); } catch (Exception) { //wtf ? } } } if (Input is Int16) { input = (BigInteger)(int)(Int16)Input; } else if (Input is Int32) { input = (BigInteger)(int)(Int32)Input; } if (Input is BigInteger) { int digits = 0; int bits; try { BigInteger number = (BigInteger)input; bits = number.BitCount(); digits = BigInteger.Abs(number).ToString().Length; } catch (Exception) { digits = 0; bits = 0; } string digitText = (digits == 1) ? Properties.Resources.Digit : Properties.Resources.Digits; string bitText = (bits == 1) ? Properties.Resources.Bit : Properties.Resources.Bits; label = string.Format(" {0:#,0} {1}, {2} {3}", digits, digitText, bits, bitText); textOutputPresentation.labelBytes.Content = label; return; } if (settings.ShowChars) { int chars = (s == null) ? 0 : s.Length; //int bytes = Encoding.UTF8.GetBytes(textOutputPresentation.textBox.Text).Length; string entity = (chars == 1) ? Properties.Resources.Char : Properties.Resources.Chars; label += string.Format(" {0:#,0} " + entity, chars); } if (settings.ShowLines) { int lines = 0; if (s != null && s.Length > 0) { lines = new Regex("\n", RegexOptions.Multiline).Matches(s).Count; if (s[s.Length - 1] != '\n') { lines++; } } string entity = (lines == 1) ? Properties.Resources.Line : Properties.Resources.Lines; if (label != "") { label += ", "; } label += string.Format(" {0:#,0} " + entity, lines); } textOutputPresentation.labelBytes.Content = label; }
private static int GetSPPRounds(BigInteger bi, ConfidenceFactor confidence) { int bc = bi.BitCount(); int Rounds; // Data from HAC, 4.49 if (bc <= 100) { Rounds = 27; } else if (bc <= 150) { Rounds = 18; } else if (bc <= 200) { Rounds = 15; } else if (bc <= 250) { Rounds = 12; } else if (bc <= 300) { Rounds = 9; } else if (bc <= 350) { Rounds = 8; } else if (bc <= 400) { Rounds = 7; } else if (bc <= 500) { Rounds = 6; } else if (bc <= 600) { Rounds = 5; } else if (bc <= 800) { Rounds = 4; } else if (bc <= 1250) { Rounds = 3; } else { Rounds = 2; } switch (confidence) { case ConfidenceFactor.ExtraLow: Rounds >>= 2; return(Rounds != 0 ? Rounds : 1); case ConfidenceFactor.Low: Rounds >>= 1; return(Rounds != 0 ? Rounds : 1); case ConfidenceFactor.Medium: return(Rounds); case ConfidenceFactor.High: return(Rounds << 1); case ConfidenceFactor.ExtraHigh: return(Rounds << 2); case ConfidenceFactor.Provable: throw new Exception("The Rabin-Miller test can not be executed in a way such that its results are provable"); default: throw new ArgumentOutOfRangeException("confidence"); } }
public void WriteBigIntWithBits(BigInteger bi) { WriteInt32(bi.BitCount()); Write(bi.GetBytes()); }
// Modified from http://www.codeproject.com/Articles/2728/C-BigInteger-Class for use with the BigInteger public static bool RabinMillerTest(this BigInteger thisVal, int confidence) { byte[] bytes = thisVal.ToUnsignedByteArray(); if (bytes.Length == 1) { // test small numbers if (bytes[0] == 0 || bytes[0] == 1) { return(false); } if (bytes[0] == 2 || bytes[0] == 3) { return(true); } } if ((bytes[0] & 0x1) == 0) // even numbers { return(false); } // calculate values of s and t BigInteger pSub1 = thisVal - (new BigInteger(1)); byte[] pSub1Bytes = pSub1.ToUnsignedByteArray(); int s = 0; for (var index = 0; index < pSub1Bytes.Length; index++) { uint mask = 0x01; for (var i = 0; i < 32; i++) { if ((pSub1Bytes[index] & mask) != 0) { index = pSub1Bytes.Length; // to break the outer loop break; } mask <<= 1; s++; } } BigInteger t = pSub1 >> s; int bits = thisVal.BitCount(); BigInteger a = new BigInteger().MakePositive(); var rand = new Random(); for (var round = 0; round < confidence; round++) { var done = false; while (!done) // generate a < n { int testBits = 0; // make sure "a" has at least 2 bits while (testBits < 2) { testBits = (int)(rand.NextDouble() * bits); } a = CreateBigInteger(testBits, rand); byte[] aBytes = a.ToUnsignedByteArray(); // make sure "a" is not 0 if (aBytes.Length > 1 || (aBytes.Length == 1 && aBytes[0] != 1)) { done = true; } } // check whether a factor exists(fix for version 1.03) BigInteger gcdTest = a.Gcd(thisVal); byte[] gcdBytes = gcdTest.ToUnsignedByteArray(); if (gcdBytes.Length == 1 && gcdBytes[0] != 1) { return(false); } BigInteger b = a.ModPow(t, thisVal); byte[] bBytes = b.ToUnsignedByteArray(); var result = bBytes.Length == 1 && bBytes[0] == 1; for (var j = 0; result == false && j < s; j++) { if (b == pSub1) // a^((2^j)*t) mod p = p-1 for some 0 <= j <= s-1 { result = true; break; } b = (b * b) % thisVal; } if (result == false) { return(false); } } return(true); }
protected void GenerateKeyPair() { // p and q values should have a length of half the strength in bits int pbitlength = ((KeySize + 1) >> 1); int qbitlength = (KeySize - pbitlength); const uint uint_e = 65537; //duff before 17 now e = uint_e; // fixed // generate p, prime and (p-1) relatively prime to e for (;;) { p = BigInteger.GeneratePseudoPrime(pbitlength); if (p % uint_e != 1) { break; } } // generate a modulus of the required length for (;;) { // generate q, prime and (q-1) relatively prime to e, // and not equal to p for (;;) { q = BigInteger.GeneratePseudoPrime(qbitlength); if ((q % uint_e != 1) && (p != q)) { break; } } // calculate the modulus n = p * q; if (n.BitCount() == KeySize) { break; } // if we get here our primes aren't big enough, make the largest // of the two p and try again if (p < q) { p = q; } } BigInteger pSub1 = (p - 1); BigInteger qSub1 = (q - 1); BigInteger phi = pSub1 * qSub1; // calculate the private exponent d = e.ModInverse(phi); // calculate the CRT factors dp = d % pSub1; dq = d % qSub1; qInv = q.ModInverse(p); //duff add qP = q.ModInverse(p); pQ = p.ModInverse(q); keypairGenerated = true; isCRTpossible = true; if (KeyGenerated != null) { KeyGenerated(this, null); } }
/// <summary> /// Probabilistic prime test based on Rabin-Miller's test /// </summary> /// <param name="bi" type="BigInteger.BigInteger"> /// <para> /// The number to test. /// </para> /// </param> /// <param name="confidence" type="int"> /// <para> /// The number of chosen bases. The test has at least a /// 1/4^confidence chance of falsely returning True. /// </para> /// </param> /// <returns> /// <para> /// True if "this" is a strong pseudoprime to randomly chosen bases. /// </para> /// <para> /// False if "this" is definitely NOT prime. /// </para> /// </returns> public static bool RabinMillerTest(BigInteger bi, ConfidenceFactor confidence) { int Rounds = GetSPPRounds(bi, confidence); // calculate values of s and t BigInteger p_sub1 = bi - 1; int s = p_sub1.LowestSetBit(); BigInteger t = p_sub1 >> s; int bits = bi.BitCount(); BigInteger a = null; BigInteger.ModulusRing mr = new BigInteger.ModulusRing(bi); // Applying optimization from HAC section 4.50 (base == 2) // not a really random base but an interesting (and speedy) one BigInteger b = mr.Pow(2, t); if (b != 1) { bool result = false; for (int j = 0; j < s; j++) { if (b == p_sub1) // a^((2^j)*t) mod p = p-1 for some 0 <= j <= s-1 { result = true; break; } b = (b * b) % bi; } if (!result) { return(false); } } // still here ? start at round 1 (round 0 was a == 2) for (int round = 1; round < Rounds; round++) { while (true) // generate a < n { a = BigInteger.GenerateRandom(bits); // make sure "a" is not 0 (and not 2 as we have already tested that) if (a > 2 && a < bi) { break; } } if (a.GCD(bi) != 1) { return(false); } b = mr.Pow(a, t); if (b == 1) { continue; // a^t mod p = 1 } bool result = false; for (int j = 0; j < s; j++) { if (b == p_sub1) // a^((2^j)*t) mod p = p-1 for some 0 <= j <= s-1 { result = true; break; } b = (b * b) % bi; } if (!result) { return(false); } } return(true); }
public override byte[] DecryptValue(byte[] rgb) { if (m_disposed) { throw new ObjectDisposedException("private key"); } // decrypt operation is used for signature if (!keypairGenerated) { GenerateKeyPair(); } BigInteger input = new BigInteger(rgb); BigInteger r = null; // we use key blinding (by default) against timing attacks if (keyBlinding) { // x = (r^e * g) mod n // *new* random number (so it's timing is also random) r = BigInteger.GenerateRandom(n.BitCount()); input = r.ModPow(e, n) * input % n; } BigInteger output; // decrypt (which uses the private key) can be // optimized by using CRT (Chinese Remainder Theorem) if (isCRTpossible) { // m1 = c^dp mod p BigInteger m1 = input.ModPow(dp, p); // m2 = c^dq mod q BigInteger m2 = input.ModPow(dq, q); BigInteger h; if (m2 > m1) { // thanks to benm! h = p - ((m2 - m1) * qInv % p); output = m2 + q * h; } else { // h = (m1 - m2) * qInv mod p h = (m1 - m2) * qInv % p; // m = m2 + q * h; output = m2 + q * h; } } else if (!PublicOnly) { // m = c^d mod n output = input.ModPow(d, n); } else { throw new CryptographicException(Locale.GetText("Missing private key to decrypt value.")); } if (keyBlinding) { // Complete blinding // x^e / r mod n output = output * r.ModInverse(n) % n; r.Clear(); } // it's sometimes possible for the results to be a byte short // and this can break some software (see #79502) so we 0x00 pad the result byte[] result = GetPaddedValue(output, (KeySize >> 3)); // zeroize values input.Clear(); output.Clear(); return(result); }