/// <summary>Choose a random prime value for use with RSA</summary> /// <param name="bitlength">the bit-length of the returned prime</param> /// <param name="e">the RSA public exponent</param> /// <returns>a prime p, with (p-1) relatively prime to e</returns> protected virtual BigInteger ChooseRandomPrime(int bitlength, BigInteger e) { for (;;) { BigInteger p = new BigInteger(bitlength, 1, param.Random); if (p.Mod(e).Equals(BigInteger.One)) continue; if (!p.IsProbablePrime(param.Certainty)) continue; if (!e.Gcd(p.Subtract(BigInteger.One)).Equals(BigInteger.One)) continue; return p; } }
public AsymmetricCipherKeyPair GenerateKeyPair() { BigInteger p, q, n, d, e, pSub1, qSub1, phi; // // p and q values should have a length of half the strength in bits // int strength = param.Strength; int pbitlength = (strength + 1) / 2; int qbitlength = (strength - pbitlength); int mindiffbits = strength / 3; e = param.PublicExponent; // TODO Consider generating safe primes for p, q (see DHParametersHelper.generateSafePrimes) // (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm") // // Generate p, prime and (p-1) relatively prime to e // for (;;) { p = new BigInteger(pbitlength, 1, param.Random); if (p.Mod(e).Equals(BigInteger.One)) continue; if (!p.IsProbablePrime(param.Certainty)) continue; if (e.Gcd(p.Subtract(BigInteger.One)).Equals(BigInteger.One)) 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 = new BigInteger(qbitlength, 1, param.Random); if (q.Subtract(p).Abs().BitLength < mindiffbits) continue; if (q.Mod(e).Equals(BigInteger.One)) continue; if (!q.IsProbablePrime(param.Certainty)) continue; if (e.Gcd(q.Subtract(BigInteger.One)).Equals(BigInteger.One)) break; } // // calculate the modulus // n = p.Multiply(q); if (n.BitLength == param.Strength) break; // // if we Get here our primes aren't big enough, make the largest // of the two p and try again // p = p.Max(q); } if (p.CompareTo(q) < 0) { phi = p; p = q; q = phi; } pSub1 = p.Subtract(BigInteger.One); qSub1 = q.Subtract(BigInteger.One); phi = pSub1.Multiply(qSub1); // // calculate the private exponent // d = e.ModInverse(phi); // // calculate the CRT factors // BigInteger dP, dQ, qInv; dP = d.Remainder(pSub1); dQ = d.Remainder(qSub1); qInv = q.ModInverse(p); return new AsymmetricCipherKeyPair( new RsaKeyParameters(false, n, e), new RsaPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv)); }
/// <summary> /// Constructor used by the pre-approved groups in JPakePrimeOrderGroups. /// These pre-approved groups can avoid the expensive checks. /// User-specified groups should not use this constructor. /// </summary> public JPakePrimeOrderGroup(BigInteger p, BigInteger q, BigInteger g, bool skipChecks) { JPakeUtilities.ValidateNotNull(p, "p"); JPakeUtilities.ValidateNotNull(q, "q"); JPakeUtilities.ValidateNotNull(g, "g"); if (!skipChecks) { if (!p.Subtract(JPakeUtilities.One).Mod(q).Equals(JPakeUtilities.Zero)) throw new ArgumentException("p-1 must be evenly divisible by q"); if (g.CompareTo(BigInteger.Two) == -1 || g.CompareTo(p.Subtract(JPakeUtilities.One)) == 1) throw new ArgumentException("g must be in [2, p-1]"); if (!g.ModPow(q, p).Equals(JPakeUtilities.One)) throw new ArgumentException("g^q mod p must equal 1"); // Note these checks do not guarantee that p and q are prime. // We just have reasonable certainty that they are prime. if (!p.IsProbablePrime(20)) throw new ArgumentException("p must be prime"); if (!q.IsProbablePrime(20)) throw new ArgumentException("q must be prime"); } this.p = p; this.q = q; this.g = g; }
private DsaParameters GenerateParameters_FIPS186_2() { byte[] seed = new byte[20]; byte[] part1 = new byte[20]; byte[] part2 = new byte[20]; byte[] u = new byte[20]; Sha1Digest sha1 = new Sha1Digest(); int n = (L - 1) / 160; byte[] w = new byte[L / 8]; for (;;) { random.NextBytes(seed); Hash(sha1, seed, part1); Array.Copy(seed, 0, part2, 0, seed.Length); Inc(part2); Hash(sha1, part2, part2); for (int i = 0; i != u.Length; i++) { u[i] = (byte)(part1[i] ^ part2[i]); } u[0] |= (byte)0x80; u[19] |= (byte)0x01; BigInteger q = new BigInteger(1, u); if (!q.IsProbablePrime(certainty)) continue; byte[] offset = Arrays.Clone(seed); Inc(offset); for (int counter = 0; counter < 4096; ++counter) { for (int k = 0; k < n; k++) { Inc(offset); Hash(sha1, offset, part1); Array.Copy(part1, 0, w, w.Length - (k + 1) * part1.Length, part1.Length); } Inc(offset); Hash(sha1, offset, part1); Array.Copy(part1, part1.Length - ((w.Length - (n) * part1.Length)), w, 0, w.Length - n * part1.Length); w[0] |= (byte)0x80; BigInteger x = new BigInteger(1, w); BigInteger c = x.Mod(q.ShiftLeft(1)); BigInteger p = x.Subtract(c.Subtract(BigInteger.One)); if (p.BitLength != L) continue; if (p.IsProbablePrime(certainty)) { BigInteger g = CalculateGenerator_FIPS186_2(p, q, random); return new DsaParameters(p, q, g, new DsaValidationParameters(seed, counter)); } } } }
/* * Finds a pair of prime BigInteger's {p, q: p = 2q + 1} * * (see: Handbook of Applied Cryptography 4.86) */ internal static BigInteger[] GenerateSafePrimes(int size, int certainty, SecureRandom random) { BigInteger p, q; int qLength = size - 1; int minWeight = size >> 2; if (size <= 32) { for (;;) { q = new BigInteger(qLength, 2, random); p = q.ShiftLeft(1).Add(BigInteger.One); if (!p.IsProbablePrime(certainty)) continue; if (certainty > 2 && !q.IsProbablePrime(certainty - 2)) continue; break; } } else { // Note: Modified from Java version for speed for (;;) { q = new BigInteger(qLength, 0, random); retry: for (int i = 0; i < primeLists.Length; ++i) { int test = q.Remainder(BigPrimeProducts[i]).IntValue; if (i == 0) { int rem3 = test % 3; if (rem3 != 2) { int diff = 2 * rem3 + 2; q = q.Add(BigInteger.ValueOf(diff)); test = (test + diff) % primeProducts[i]; } } int[] primeList = primeLists[i]; for (int j = 0; j < primeList.Length; ++j) { int prime = primeList[j]; int qRem = test % prime; if (qRem == 0 || qRem == (prime >> 1)) { q = q.Add(Six); goto retry; } } } if (q.BitLength != qLength) continue; if (!q.RabinMillerTest(2, random)) continue; p = q.ShiftLeft(1).Add(BigInteger.One); if (!p.RabinMillerTest(certainty, random)) continue; if (certainty > 2 && !q.RabinMillerTest(certainty - 2, random)) continue; /* * Require a minimum weight of the NAF representation, since low-weight primes may be * weak against a version of the number-field-sieve for the discrete-logarithm-problem. * * See "The number field sieve for integers of low weight", Oliver Schirokauer. */ if (WNafUtilities.GetNafWeight(p) < minWeight) continue; break; } } return new BigInteger[] { p, q }; }
/** * which Generates the p and g values from the given parameters, * returning the DsaParameters object. * <p> * Note: can take a while...</p> */ public DsaParameters GenerateParameters() { byte[] seed = new byte[20]; byte[] part1 = new byte[20]; byte[] part2 = new byte[20]; byte[] u = new byte[20]; Sha1Digest sha1 = new Sha1Digest(); int n = (size - 1) / 160; byte[] w = new byte[size / 8]; BigInteger q = null, p = null, g = null; int counter = 0; bool primesFound = false; while (!primesFound) { do { random.NextBytes(seed); sha1.BlockUpdate(seed, 0, seed.Length); sha1.DoFinal(part1, 0); Array.Copy(seed, 0, part2, 0, seed.Length); Add(part2, seed, 1); sha1.BlockUpdate(part2, 0, part2.Length); sha1.DoFinal(part2, 0); for (int i = 0; i != u.Length; i++) { u[i] = (byte)(part1[i] ^ part2[i]); } u[0] |= (byte)0x80; u[19] |= (byte)0x01; q = new BigInteger(1, u); } while (!q.IsProbablePrime(certainty)); counter = 0; int offset = 2; while (counter < 4096) { for (int k = 0; k < n; k++) { Add(part1, seed, offset + k); sha1.BlockUpdate(part1, 0, part1.Length); sha1.DoFinal(part1, 0); Array.Copy(part1, 0, w, w.Length - (k + 1) * part1.Length, part1.Length); } Add(part1, seed, offset + n); sha1.BlockUpdate(part1, 0, part1.Length); sha1.DoFinal(part1, 0); Array.Copy(part1, part1.Length - ((w.Length - (n) * part1.Length)), w, 0, w.Length - n * part1.Length); w[0] |= (byte)0x80; BigInteger x = new BigInteger(1, w); BigInteger c = x.Mod(q.ShiftLeft(1)); p = x.Subtract(c.Subtract(BigInteger.One)); if (p.TestBit(size - 1)) { if (p.IsProbablePrime(certainty)) { primesFound = true; break; } } counter += 1; offset += n + 1; } } // // calculate the generator g // BigInteger pMinusOneOverQ = p.Subtract(BigInteger.One).Divide(q); for (;;) { BigInteger h = new BigInteger(size, random); if (h.CompareTo(BigInteger.One) <= 0 || h.CompareTo(p.Subtract(BigInteger.One)) >= 0) { continue; } g = h.ModPow(pMinusOneOverQ, p); if (g.CompareTo(BigInteger.One) <= 0) { continue; } break; } return new DsaParameters(p, q, g, new DsaValidationParameters(seed, counter)); }
/* * Finds a pair of prime BigInteger's {p, q: p = 2q + 1} * * (see: Handbook of Applied Cryptography 4.86) */ internal static BigInteger[] GenerateSafePrimes(int size, int certainty, SecureRandom random) { BigInteger p, q; int qLength = size - 1; if (size <= 32) { for (;;) { q = new BigInteger(qLength, 2, random); p = q.ShiftLeft(1).Add(BigInteger.One); if (p.IsProbablePrime(certainty) && (certainty <= 2 || q.IsProbablePrime(certainty))) break; } } else { // Note: Modified from Java version for speed for (;;) { q = new BigInteger(qLength, 0, random); retry: for (int i = 0; i < primeLists.Length; ++i) { int test = q.Remainder(BigPrimeProducts[i]).IntValue; if (i == 0) { int rem3 = test % 3; if (rem3 != 2) { int diff = 2 * rem3 + 2; q = q.Add(BigInteger.ValueOf(diff)); test = (test + diff) % primeProducts[i]; } } int[] primeList = primeLists[i]; for (int j = 0; j < primeList.Length; ++j) { int prime = primeList[j]; int qRem = test % prime; if (qRem == 0 || qRem == (prime >> 1)) { q = q.Add(Six); goto retry; } } } if (q.BitLength != qLength) continue; if (!q.RabinMillerTest(2, random)) continue; p = q.ShiftLeft(1).Add(BigInteger.One); if (p.RabinMillerTest(certainty, random) && (certainty <= 2 || q.RabinMillerTest(certainty - 2, random))) break; } } return new BigInteger[] { p, q }; }
/// <summary>Choose a random prime value for use with RSA</summary> /// <param name="bitlength">the bit-length of the returned prime</param> /// <param name="e">the RSA public exponent</param> /// <returns>a prime p, with (p-1) relatively prime to e</returns> protected virtual BigInteger ChooseRandomPrime(int bitlength, BigInteger e) { bool eIsKnownOddPrime = (e.BitLength <= SPECIAL_E_BITS) && Arrays.Contains(SPECIAL_E_VALUES, e.IntValue); for (;;) { BigInteger p = new BigInteger(bitlength, 1, parameters.Random); if (p.Mod(e).Equals(One)) continue; if (!p.IsProbablePrime(parameters.Certainty, true)) continue; if (!eIsKnownOddPrime && !e.Gcd(p.Subtract(One)).Equals(One)) continue; return p; } }
private void processDHEKeyExchange( MemoryStream inStr, ISigner signer) { Stream sigIn = inStr; if (signer != null) { signer.Init(false, this.serverPublicKey); signer.BlockUpdate(this.clientRandom, 0, this.clientRandom.Length); signer.BlockUpdate(this.serverRandom, 0, this.serverRandom.Length); sigIn = new SignerStream(inStr, signer, null); } /* * Parse the Structure */ byte[] pByte = TlsUtilities.ReadOpaque16(sigIn); byte[] gByte = TlsUtilities.ReadOpaque16(sigIn); byte[] YsByte = TlsUtilities.ReadOpaque16(sigIn); if (signer != null) { byte[] sigByte = TlsUtilities.ReadOpaque16(sigIn); /* * Verify the Signature. */ if (!signer.VerifySignature(sigByte)) { this.FailWithError(AL_fatal, AP_bad_certificate); } } this.AssertEmpty(inStr); /* * Do the DH calculation. */ BigInteger p = new BigInteger(1, pByte); BigInteger g = new BigInteger(1, gByte); BigInteger Ys = new BigInteger(1, YsByte); /* * Check the DH parameter values */ if (!p.IsProbablePrime(10)) { this.FailWithError(AL_fatal, AP_illegal_parameter); } if (g.CompareTo(BigInteger.Two) < 0 || g.CompareTo(p.Subtract(BigInteger.Two)) > 0) { this.FailWithError(AL_fatal, AP_illegal_parameter); } // TODO For static DH public values, see additional checks in RFC 2631 2.1.5 if (Ys.CompareTo(BigInteger.Two) < 0 || Ys.CompareTo(p.Subtract(BigInteger.One)) > 0) { this.FailWithError(AL_fatal, AP_illegal_parameter); } /* * Diffie-Hellman basic key agreement */ DHParameters dhParams = new DHParameters(p, g); // Generate a keypair DHBasicKeyPairGenerator dhGen = new DHBasicKeyPairGenerator(); dhGen.Init(new DHKeyGenerationParameters(random, dhParams)); AsymmetricCipherKeyPair dhPair = dhGen.GenerateKeyPair(); // Store the public value to send to server this.Yc = ((DHPublicKeyParameters)dhPair.Public).Y; // Calculate the shared secret DHBasicAgreement dhAgree = new DHBasicAgreement(); dhAgree.Init(dhPair.Private); BigInteger agreement = dhAgree.CalculateAgreement(new DHPublicKeyParameters(Ys, dhParams)); this.pms = BigIntegers.AsUnsignedByteArray(agreement); }
/** * <summary>Tests whether a given string number is a prime number.</summary> * <param name="value">The string number to test if it is prime.</param> * <returns>Returns true if the string given value is prime else returns false.</returns> */ public static bool IsPrime(string value, BackgroundWorker bw) { BigInteger b = new BigInteger(value); return b.IsProbablePrime(64); }
/// <summary> /// Finds a pair of prime BigInteger's {p, q: p = 2q + 1} /// /// (see: Handbook of Applied Cryptography 4.86) /// </summary> /// <param name="size">The size.</param> /// <param name="certainty">The certainty.</param> /// <param name="random">The random.</param> /// <returns></returns> internal static IBigInteger[] GenerateSafePrimes(int size, int certainty, ISecureRandom random) { IBigInteger p, q; var qLength = size - 1; if (size <= 32) { for (; ; ) { q = new BigInteger(qLength, 2, random); p = q.ShiftLeft(1).Add(BigInteger.One); if (p.IsProbablePrime(certainty) && (certainty <= 2 || q.IsProbablePrime(certainty))) break; } } else { // Note: Modified from Java version for speed for (; ; ) { q = new BigInteger(qLength, 0, random); retry: for (var i = 0; i < _primeLists.Length; ++i) { var test = q.Remainder(_primeProductsBigs[i]).IntValue; if (i == 0) { var rem3 = test % 3; if (rem3 != 2) { var diff = 2 * rem3 + 2; q = q.Add(BigInteger.ValueOf(diff)); test = (test + diff) % _primeProductsInts[i]; } } var primeList = _primeLists[i]; foreach (var prime in primeList) { var qRem = test % prime; if (qRem != 0 && qRem != (prime >> 1)) continue; q = q.Add(_six); goto retry; } } if (q.BitLength != qLength) continue; if (!((BigInteger)q).RabinMillerTest(2, random)) continue; p = q.ShiftLeft(1).Add(BigInteger.One); if (((BigInteger)p).RabinMillerTest(certainty, random) && (certainty <= 2 || ((BigInteger)q).RabinMillerTest(certainty - 2, random))) break; } } return new[] { p, q }; }