123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
- #pragma warning disable
- using System;
- using System.Collections;
- using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
- using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
- using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
- using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
- using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
- using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Collections;
- namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Generators
- {
- /**
- * Key generation parameters for NaccacheStern cipher. For details on this cipher, please see
- *
- * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
- */
- public class NaccacheSternKeyPairGenerator
- : IAsymmetricCipherKeyPairGenerator
- {
- private static readonly int[] smallPrimes =
- {
- 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67,
- 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149,
- 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
- 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331,
- 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431,
- 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523,
- 541, 547, 557
- };
- private NaccacheSternKeyGenerationParameters param;
- /*
- * (non-Javadoc)
- *
- * @see org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator#init(org.bouncycastle.crypto.KeyGenerationParameters)
- */
- public void Init(KeyGenerationParameters parameters)
- {
- this.param = (NaccacheSternKeyGenerationParameters)parameters;
- }
- /*
- * (non-Javadoc)
- *
- * @see org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator#generateKeyPair()
- */
- public AsymmetricCipherKeyPair GenerateKeyPair()
- {
- int strength = param.Strength;
- SecureRandom rand = param.Random;
- int certainty = param.Certainty;
- IList smallPrimes = findFirstPrimes(param.CountSmallPrimes);
- smallPrimes = permuteList(smallPrimes, rand);
- BigInteger u = BigInteger.One;
- BigInteger v = BigInteger.One;
- for (int i = 0; i < smallPrimes.Count / 2; i++)
- {
- u = u.Multiply((BigInteger)smallPrimes[i]);
- }
- for (int i = smallPrimes.Count / 2; i < smallPrimes.Count; i++)
- {
- v = v.Multiply((BigInteger)smallPrimes[i]);
- }
- BigInteger sigma = u.Multiply(v);
- // n = (2 a u _p + 1 ) ( 2 b v _q + 1)
- // -> |n| = strength
- // |2| = 1 in bits
- // -> |a| * |b| = |n| - |u| - |v| - |_p| - |_q| - |2| -|2|
- // remainingStrength = strength - sigma.bitLength() - _p.bitLength() -
- // _q.bitLength() - 1 -1
- int remainingStrength = strength - sigma.BitLength - 48;
- BigInteger a = generatePrime(remainingStrength / 2 + 1, certainty, rand);
- BigInteger b = generatePrime(remainingStrength / 2 + 1, certainty, rand);
- BigInteger _p;
- BigInteger _q;
- BigInteger p;
- BigInteger q;
- long tries = 0;
- BigInteger _2au = a.Multiply(u).ShiftLeft(1);
- BigInteger _2bv = b.Multiply(v).ShiftLeft(1);
- for (;;)
- {
- tries++;
- _p = generatePrime(24, certainty, rand);
- p = _p.Multiply(_2au).Add(BigInteger.One);
- if (!p.IsProbablePrime(certainty, true))
- continue;
- for (;;)
- {
- _q = generatePrime(24, certainty, rand);
- if (_p.Equals(_q))
- continue;
- q = _q.Multiply(_2bv).Add(BigInteger.One);
- if (q.IsProbablePrime(certainty, true))
- break;
- }
- if (!sigma.Gcd(_p.Multiply(_q)).Equals(BigInteger.One))
- {
- //Console.WriteLine("sigma.gcd(_p.mult(_q)) != 1!\n _p: " + _p +"\n _q: "+ _q );
- continue;
- }
- if (p.Multiply(q).BitLength < strength)
- {
- continue;
- }
- break;
- }
- BigInteger n = p.Multiply(q);
- BigInteger phi_n = p.Subtract(BigInteger.One).Multiply(q.Subtract(BigInteger.One));
- BigInteger g;
- tries = 0;
- for (;;)
- {
- // TODO After the first loop, just regenerate one randomly-selected gPart each time?
- IList gParts = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateArrayList();
- for (int ind = 0; ind != smallPrimes.Count; ind++)
- {
- BigInteger i = (BigInteger)smallPrimes[ind];
- BigInteger e = phi_n.Divide(i);
- for (;;)
- {
- tries++;
- g = generatePrime(strength, certainty, rand);
- if (!g.ModPow(e, n).Equals(BigInteger.One))
- {
- gParts.Add(g);
- break;
- }
- }
- }
- g = BigInteger.One;
- for (int i = 0; i < smallPrimes.Count; i++)
- {
- BigInteger gPart = (BigInteger) gParts[i];
- BigInteger smallPrime = (BigInteger) smallPrimes[i];
- g = g.Multiply(gPart.ModPow(sigma.Divide(smallPrime), n)).Mod(n);
- }
- // make sure that g is not divisible by p_i or q_i
- bool divisible = false;
- for (int i = 0; i < smallPrimes.Count; i++)
- {
- if (g.ModPow(phi_n.Divide((BigInteger)smallPrimes[i]), n).Equals(BigInteger.One))
- {
- divisible = true;
- break;
- }
- }
- if (divisible)
- {
- continue;
- }
- // make sure that g has order > phi_n/4
- //if (g.ModPow(phi_n.Divide(BigInteger.ValueOf(4)), n).Equals(BigInteger.One))
- if (g.ModPow(phi_n.ShiftRight(2), n).Equals(BigInteger.One))
- {
- continue;
- }
- if (g.ModPow(phi_n.Divide(_p), n).Equals(BigInteger.One))
- {
- continue;
- }
- if (g.ModPow(phi_n.Divide(_q), n).Equals(BigInteger.One))
- {
- continue;
- }
- if (g.ModPow(phi_n.Divide(a), n).Equals(BigInteger.One))
- {
- continue;
- }
- if (g.ModPow(phi_n.Divide(b), n).Equals(BigInteger.One))
- {
- continue;
- }
- break;
- }
- return new AsymmetricCipherKeyPair(new NaccacheSternKeyParameters(false, g, n, sigma.BitLength),
- new NaccacheSternPrivateKeyParameters(g, n, sigma.BitLength, smallPrimes, phi_n));
- }
- private static BigInteger generatePrime(
- int bitLength,
- int certainty,
- SecureRandom rand)
- {
- return new BigInteger(bitLength, certainty, rand);
- }
- /**
- * Generates a permuted ArrayList from the original one. The original List
- * is not modified
- *
- * @param arr
- * the ArrayList to be permuted
- * @param rand
- * the source of Randomness for permutation
- * @return a new IList with the permuted elements.
- */
- private static IList permuteList(
- IList arr,
- SecureRandom rand)
- {
- // TODO Create a utility method for generating permutation of first 'n' integers
- IList retval = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateArrayList(arr.Count);
- foreach (object element in arr)
- {
- int index = rand.Next(retval.Count + 1);
- retval.Insert(index, element);
- }
- return retval;
- }
- /**
- * Finds the first 'count' primes starting with 3
- *
- * @param count
- * the number of primes to find
- * @return a vector containing the found primes as Integer
- */
- private static IList findFirstPrimes(
- int count)
- {
- IList primes = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateArrayList(count);
- for (int i = 0; i != count; i++)
- {
- primes.Add(BigInteger.ValueOf(smallPrimes[i]));
- }
- return primes;
- }
- }
- }
- #pragma warning restore
- #endif
|