up
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
|
||||
using System;
|
||||
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Math.EC.Multiplier;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Generators
|
||||
{
|
||||
/**
|
||||
* an RSA key pair generator.
|
||||
*/
|
||||
public class RsaKeyPairGenerator
|
||||
: IAsymmetricCipherKeyPairGenerator
|
||||
{
|
||||
private static readonly int[] SPECIAL_E_VALUES = new int[]{ 3, 5, 17, 257, 65537 };
|
||||
private static readonly int SPECIAL_E_HIGHEST = SPECIAL_E_VALUES[SPECIAL_E_VALUES.Length - 1];
|
||||
private static readonly int SPECIAL_E_BITS = BigInteger.ValueOf(SPECIAL_E_HIGHEST).BitLength;
|
||||
|
||||
protected static readonly BigInteger One = BigInteger.One;
|
||||
protected static readonly BigInteger DefaultPublicExponent = BigInteger.ValueOf(0x10001);
|
||||
protected const int DefaultTests = 100;
|
||||
|
||||
protected RsaKeyGenerationParameters parameters;
|
||||
|
||||
public virtual void Init(
|
||||
KeyGenerationParameters parameters)
|
||||
{
|
||||
if (parameters is RsaKeyGenerationParameters)
|
||||
{
|
||||
this.parameters = (RsaKeyGenerationParameters)parameters;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.parameters = new RsaKeyGenerationParameters(
|
||||
DefaultPublicExponent, parameters.Random, parameters.Strength, DefaultTests);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual AsymmetricCipherKeyPair GenerateKeyPair()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
//
|
||||
// p and q values should have a length of half the strength in bits
|
||||
//
|
||||
int strength = parameters.Strength;
|
||||
int pBitlength = (strength + 1) / 2;
|
||||
int qBitlength = strength - pBitlength;
|
||||
int mindiffbits = strength / 3;
|
||||
int minWeight = strength >> 2;
|
||||
|
||||
BigInteger e = parameters.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")
|
||||
|
||||
BigInteger p = ChooseRandomPrime(pBitlength, e);
|
||||
BigInteger q, n;
|
||||
|
||||
//
|
||||
// generate a modulus of the required length
|
||||
//
|
||||
for (;;)
|
||||
{
|
||||
q = ChooseRandomPrime(qBitlength, e);
|
||||
|
||||
// p and q should not be too close together (or equal!)
|
||||
BigInteger diff = q.Subtract(p).Abs();
|
||||
if (diff.BitLength < mindiffbits)
|
||||
continue;
|
||||
|
||||
//
|
||||
// calculate the modulus
|
||||
//
|
||||
n = p.Multiply(q);
|
||||
|
||||
if (n.BitLength != strength)
|
||||
{
|
||||
//
|
||||
// if we get here our primes aren't big enough, make the largest
|
||||
// of the two p and try again
|
||||
//
|
||||
p = p.Max(q);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Require a minimum weight of the NAF representation, since low-weight composites may
|
||||
* be weak against a version of the number-field-sieve for factoring.
|
||||
*
|
||||
* See "The number field sieve for integers of low weight", Oliver Schirokauer.
|
||||
*/
|
||||
if (WNafUtilities.GetNafWeight(n) < minWeight)
|
||||
{
|
||||
p = ChooseRandomPrime(pBitlength, e);
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (p.CompareTo(q) < 0)
|
||||
{
|
||||
BigInteger tmp = p;
|
||||
p = q;
|
||||
q = tmp;
|
||||
}
|
||||
|
||||
BigInteger pSub1 = p.Subtract(One);
|
||||
BigInteger qSub1 = q.Subtract(One);
|
||||
//BigInteger phi = pSub1.Multiply(qSub1);
|
||||
BigInteger gcd = pSub1.Gcd(qSub1);
|
||||
BigInteger lcm = pSub1.Divide(gcd).Multiply(qSub1);
|
||||
|
||||
//
|
||||
// calculate the private exponent
|
||||
//
|
||||
BigInteger d = e.ModInverse(lcm);
|
||||
|
||||
if (d.BitLength <= qBitlength)
|
||||
continue;
|
||||
|
||||
//
|
||||
// calculate the CRT factors
|
||||
//
|
||||
BigInteger dP = d.Remainder(pSub1);
|
||||
BigInteger dQ = d.Remainder(qSub1);
|
||||
BigInteger qInv = q.ModInverse(p);
|
||||
|
||||
return new AsymmetricCipherKeyPair(
|
||||
new RsaKeyParameters(false, n, e),
|
||||
new RsaPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv));
|
||||
}
|
||||
}
|
||||
|
||||
/// <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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user