This commit is contained in:
2020-07-09 08:50:24 +08:00
parent 13d25f4707
commit c523462b82
1818 changed files with 174940 additions and 582 deletions

View File

@@ -0,0 +1,42 @@
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
using System;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* a basic Diffie-Hellman key pair generator.
*
* This generates keys consistent for use with the basic algorithm for
* Diffie-Hellman.
*/
public class DHBasicKeyPairGenerator
: IAsymmetricCipherKeyPairGenerator
{
private DHKeyGenerationParameters param;
public virtual void Init(
KeyGenerationParameters parameters)
{
this.param = (DHKeyGenerationParameters)parameters;
}
public virtual AsymmetricCipherKeyPair GenerateKeyPair()
{
DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.Instance;
DHParameters dhp = param.Parameters;
BigInteger x = helper.CalculatePrivate(dhp, param.Random);
BigInteger y = helper.CalculatePublic(dhp, x);
return new AsymmetricCipherKeyPair(
new DHPublicKeyParameters(y, dhp),
new DHPrivateKeyParameters(x, dhp));
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 71cb7cb8ef1934ee7a27b181ca570a5d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,76 @@
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
using System;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC.Multiplier;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Generators
{
class DHKeyGeneratorHelper
{
internal static readonly DHKeyGeneratorHelper Instance = new DHKeyGeneratorHelper();
private DHKeyGeneratorHelper()
{
}
internal BigInteger CalculatePrivate(
DHParameters dhParams,
SecureRandom random)
{
int limit = dhParams.L;
if (limit != 0)
{
int minWeight = limit >> 2;
for (;;)
{
BigInteger x = new BigInteger(limit, random).SetBit(limit - 1);
if (WNafUtilities.GetNafWeight(x) >= minWeight)
{
return x;
}
}
}
BigInteger min = BigInteger.Two;
int m = dhParams.M;
if (m != 0)
{
min = BigInteger.One.ShiftLeft(m - 1);
}
BigInteger q = dhParams.Q;
if (q == null)
{
q = dhParams.P;
}
BigInteger max = q.Subtract(BigInteger.Two);
{
int minWeight = max.BitLength >> 2;
for (;;)
{
BigInteger x = BigIntegers.CreateRandomInRange(min, max, random);
if (WNafUtilities.GetNafWeight(x) >= minWeight)
{
return x;
}
}
}
}
internal BigInteger CalculatePublic(
DHParameters dhParams,
BigInteger x)
{
return dhParams.G.ModPow(x, dhParams.P);
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 621a4ba407aff4c559a86a866918db75
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,42 @@
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
using System;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* a Diffie-Hellman key pair generator.
*
* This generates keys consistent for use in the MTI/A0 key agreement protocol
* as described in "Handbook of Applied Cryptography", Pages 516-519.
*/
public class DHKeyPairGenerator
: IAsymmetricCipherKeyPairGenerator
{
private DHKeyGenerationParameters param;
public virtual void Init(
KeyGenerationParameters parameters)
{
this.param = (DHKeyGenerationParameters)parameters;
}
public virtual AsymmetricCipherKeyPair GenerateKeyPair()
{
DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.Instance;
DHParameters dhp = param.Parameters;
BigInteger x = helper.CalculatePrivate(dhp, param.Random);
BigInteger y = helper.CalculatePublic(dhp, x);
return new AsymmetricCipherKeyPair(
new DHPublicKeyParameters(y, dhp),
new DHPrivateKeyParameters(x, dhp));
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8c5290a0dc35d4e6dbab129c8a548ede
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,160 @@
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
using System;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC.Multiplier;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Generators
{
internal class DHParametersHelper
{
private static readonly BigInteger Six = BigInteger.ValueOf(6);
private static readonly int[][] primeLists = BigInteger.primeLists;
private static readonly int[] primeProducts = BigInteger.primeProducts;
private static readonly BigInteger[] BigPrimeProducts = ConstructBigPrimeProducts(primeProducts);
private static BigInteger[] ConstructBigPrimeProducts(int[] primeProducts)
{
BigInteger[] bpp = new BigInteger[primeProducts.Length];
for (int i = 0; i < bpp.Length; ++i)
{
bpp[i] = BigInteger.ValueOf(primeProducts[i]);
}
return bpp;
}
/*
* 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, true))
continue;
if (certainty > 2 && !q.IsProbablePrime(certainty, true))
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, true))
continue;
p = q.ShiftLeft(1).Add(BigInteger.One);
if (!p.RabinMillerTest(certainty, random, true))
continue;
if (certainty > 2 && !q.RabinMillerTest(certainty - 2, random, true))
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 };
}
/*
* Select a high order element of the multiplicative group Zp*
*
* p and q must be s.t. p = 2*q + 1, where p and q are prime (see generateSafePrimes)
*/
internal static BigInteger SelectGenerator(BigInteger p, BigInteger q, SecureRandom random)
{
BigInteger pMinusTwo = p.Subtract(BigInteger.Two);
BigInteger g;
/*
* (see: Handbook of Applied Cryptography 4.80)
*/
// do
// {
// g = BigIntegers.CreateRandomInRange(BigInteger.Two, pMinusTwo, random);
// }
// while (g.ModPow(BigInteger.Two, p).Equals(BigInteger.One)
// || g.ModPow(q, p).Equals(BigInteger.One));
/*
* RFC 2631 2.2.1.2 (and see: Handbook of Applied Cryptography 4.81)
*/
do
{
BigInteger h = BigIntegers.CreateRandomInRange(BigInteger.Two, pMinusTwo, random);
g = h.ModPow(BigInteger.Two, p);
}
while (g.Equals(BigInteger.One));
return g;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eb44cdefd0a904566ba1ddd8d6ef874e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,76 @@
#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.Security;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* a DSA key pair generator.
*
* This Generates DSA keys in line with the method described
* in <i>FIPS 186-3 B.1 FFC Key Pair Generation</i>.
*/
public class DsaKeyPairGenerator
: IAsymmetricCipherKeyPairGenerator
{
private static readonly BigInteger One = BigInteger.One;
private DsaKeyGenerationParameters param;
public void Init(
KeyGenerationParameters parameters)
{
if (parameters == null)
throw new ArgumentNullException("parameters");
// Note: If we start accepting instances of KeyGenerationParameters,
// must apply constraint checking on strength (see DsaParametersGenerator.Init)
this.param = (DsaKeyGenerationParameters) parameters;
}
public AsymmetricCipherKeyPair GenerateKeyPair()
{
DsaParameters dsaParams = param.Parameters;
BigInteger x = GeneratePrivateKey(dsaParams.Q, param.Random);
BigInteger y = CalculatePublicKey(dsaParams.P, dsaParams.G, x);
return new AsymmetricCipherKeyPair(
new DsaPublicKeyParameters(y, dsaParams),
new DsaPrivateKeyParameters(x, dsaParams));
}
private static BigInteger GeneratePrivateKey(BigInteger q, SecureRandom random)
{
// B.1.2 Key Pair Generation by Testing Candidates
int minWeight = q.BitLength >> 2;
for (;;)
{
// TODO Prefer this method? (change test cases that used fixed random)
// B.1.1 Key Pair Generation Using Extra Random Bits
//BigInteger x = new BigInteger(q.BitLength + 64, random).Mod(q.Subtract(One)).Add(One);
BigInteger x = BigIntegers.CreateRandomInRange(One, q.Subtract(One), random);
if (WNafUtilities.GetNafWeight(x) >= minWeight)
{
return x;
}
}
}
private static BigInteger CalculatePublicKey(BigInteger p, BigInteger g, BigInteger x)
{
return g.ModPow(x, p);
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d627570e9412c418eab0464ecdaad363
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,166 @@
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
using System;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Nist;
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.TeleTrust;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.EC;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Math.EC.Multiplier;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Generators
{
public class ECKeyPairGenerator
: IAsymmetricCipherKeyPairGenerator
{
private readonly string algorithm;
private ECDomainParameters parameters;
private DerObjectIdentifier publicKeyParamSet;
private SecureRandom random;
public ECKeyPairGenerator()
: this("EC")
{
}
public ECKeyPairGenerator(
string algorithm)
{
if (algorithm == null)
throw new ArgumentNullException("algorithm");
this.algorithm = ECKeyParameters.VerifyAlgorithmName(algorithm);
}
public void Init(
KeyGenerationParameters parameters)
{
if (parameters is ECKeyGenerationParameters)
{
ECKeyGenerationParameters ecP = (ECKeyGenerationParameters) parameters;
this.publicKeyParamSet = ecP.PublicKeyParamSet;
this.parameters = ecP.DomainParameters;
}
else
{
DerObjectIdentifier oid;
switch (parameters.Strength)
{
case 192:
oid = X9ObjectIdentifiers.Prime192v1;
break;
case 224:
oid = SecObjectIdentifiers.SecP224r1;
break;
case 239:
oid = X9ObjectIdentifiers.Prime239v1;
break;
case 256:
oid = X9ObjectIdentifiers.Prime256v1;
break;
case 384:
oid = SecObjectIdentifiers.SecP384r1;
break;
case 521:
oid = SecObjectIdentifiers.SecP521r1;
break;
default:
throw new InvalidParameterException("unknown key size.");
}
X9ECParameters ecps = FindECCurveByOid(oid);
this.publicKeyParamSet = oid;
this.parameters = new ECDomainParameters(
ecps.Curve, ecps.G, ecps.N, ecps.H, ecps.GetSeed());
}
this.random = parameters.Random;
if (this.random == null)
{
this.random = new SecureRandom();
}
}
/**
* Given the domain parameters this routine generates an EC key
* pair in accordance with X9.62 section 5.2.1 pages 26, 27.
*/
public AsymmetricCipherKeyPair GenerateKeyPair()
{
BigInteger n = parameters.N;
BigInteger d;
int minWeight = n.BitLength >> 2;
for (;;)
{
d = new BigInteger(n.BitLength, random);
if (d.CompareTo(BigInteger.Two) < 0 || d.CompareTo(n) >= 0)
continue;
if (WNafUtilities.GetNafWeight(d) < minWeight)
continue;
break;
}
ECPoint q = CreateBasePointMultiplier().Multiply(parameters.G, d);
if (publicKeyParamSet != null)
{
return new AsymmetricCipherKeyPair(
new ECPublicKeyParameters(algorithm, q, publicKeyParamSet),
new ECPrivateKeyParameters(algorithm, d, publicKeyParamSet));
}
return new AsymmetricCipherKeyPair(
new ECPublicKeyParameters(algorithm, q, parameters),
new ECPrivateKeyParameters(algorithm, d, parameters));
}
protected virtual ECMultiplier CreateBasePointMultiplier()
{
return new FixedPointCombMultiplier();
}
internal static X9ECParameters FindECCurveByOid(DerObjectIdentifier oid)
{
// TODO ECGost3410NamedCurves support (returns ECDomainParameters though)
X9ECParameters ecP = CustomNamedCurves.GetByOid(oid);
if (ecP == null)
{
ecP = ECNamedCurveTable.GetByOid(oid);
}
return ecP;
}
internal static ECPublicKeyParameters GetCorrespondingPublicKey(
ECPrivateKeyParameters privKey)
{
ECDomainParameters ec = privKey.Parameters;
ECPoint q = new FixedPointCombMultiplier().Multiply(ec.G, privKey.D);
if (privKey.PublicKeyParamSet != null)
{
return new ECPublicKeyParameters(privKey.AlgorithmName, q, privKey.PublicKeyParamSet);
}
return new ECPublicKeyParameters(privKey.AlgorithmName, q, ec);
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e9f024be2dc124ffe9894d886c0c5730
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,44 @@
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
using System;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* a ElGamal key pair generator.
* <p>
* This Generates keys consistent for use with ElGamal as described in
* page 164 of "Handbook of Applied Cryptography".</p>
*/
public class ElGamalKeyPairGenerator
: IAsymmetricCipherKeyPairGenerator
{
private ElGamalKeyGenerationParameters param;
public void Init(
KeyGenerationParameters parameters)
{
this.param = (ElGamalKeyGenerationParameters) parameters;
}
public AsymmetricCipherKeyPair GenerateKeyPair()
{
DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.Instance;
ElGamalParameters egp = param.Parameters;
DHParameters dhp = new DHParameters(egp.P, egp.G, null, 0, egp.L);
BigInteger x = helper.CalculatePrivate(dhp, param.Random);
BigInteger y = helper.CalculatePublic(dhp, x);
return new AsymmetricCipherKeyPair(
new ElGamalPublicKeyParameters(y, egp),
new ElGamalPrivateKeyParameters(x, egp));
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 39c3fd5183e42433581ec0eb8fcf19df
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,120 @@
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
using System;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Macs;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Crypto.Generators
{
/// <summary>
/// Generates keys for the Poly1305 MAC.
/// </summary>
/// <remarks>
/// Poly1305 keys are 256 bit keys consisting of a 128 bit secret key used for the underlying block
/// cipher followed by a 128 bit {@code r} value used for the polynomial portion of the Mac. <br/>
/// The {@code r} value has a specific format with some bits required to be cleared, resulting in an
/// effective 106 bit key. <br/>
/// A separately generated 256 bit key can be modified to fit the Poly1305 key format by using the
/// {@link #clamp(byte[])} method to clear the required bits.
/// </remarks>
/// <seealso cref="Poly1305"/>
public class Poly1305KeyGenerator
: CipherKeyGenerator
{
private const byte R_MASK_LOW_2 = (byte)0xFC;
private const byte R_MASK_HIGH_4 = (byte)0x0F;
/// <summary>
/// Initialises the key generator.
/// </summary>
/// <remarks>
/// Poly1305 keys are always 256 bits, so the key length in the provided parameters is ignored.
/// </remarks>
protected override void engineInit(KeyGenerationParameters param)
{
// Poly1305 keys are always 256 bits
this.random = param.Random;
this.strength = 32;
}
/// <summary>
/// Generates a 256 bit key in the format required for Poly1305 - e.g.
/// <code>k[0] ... k[15], r[0] ... r[15]</code> with the required bits in <code>r</code> cleared
/// as per <see cref="Clamp(byte[])"/>.
/// </summary>
protected override byte[] engineGenerateKey()
{
byte[] key = base.engineGenerateKey();
Clamp(key);
return key;
}
/// <summary>
/// Modifies an existing 32 byte key value to comply with the requirements of the Poly1305 key by
/// clearing required bits in the <code>r</code> (second 16 bytes) portion of the key.<br/>
/// Specifically:
/// <ul>
/// <li>r[3], r[7], r[11], r[15] have top four bits clear (i.e., are {0, 1, . . . , 15})</li>
/// <li>r[4], r[8], r[12] have bottom two bits clear (i.e., are in {0, 4, 8, . . . , 252})</li>
/// </ul>
/// </summary>
/// <param name="key">a 32 byte key value <code>k[0] ... k[15], r[0] ... r[15]</code></param>
public static void Clamp(byte[] key)
{
/*
* Key is k[0] ... k[15], r[0] ... r[15] as per poly1305_aes_clamp in ref impl.
*/
if (key.Length != 32)
throw new ArgumentException("Poly1305 key must be 256 bits.");
/*
* r[3], r[7], r[11], r[15] have top four bits clear (i.e., are {0, 1, . . . , 15})
*/
key[3] &= R_MASK_HIGH_4;
key[7] &= R_MASK_HIGH_4;
key[11] &= R_MASK_HIGH_4;
key[15] &= R_MASK_HIGH_4;
/*
* r[4], r[8], r[12] have bottom two bits clear (i.e., are in {0, 4, 8, . . . , 252}).
*/
key[4] &= R_MASK_LOW_2;
key[8] &= R_MASK_LOW_2;
key[12] &= R_MASK_LOW_2;
}
/// <summary>
/// Checks a 32 byte key for compliance with the Poly1305 key requirements, e.g.
/// <code>k[0] ... k[15], r[0] ... r[15]</code> with the required bits in <code>r</code> cleared
/// as per <see cref="Clamp(byte[])"/>.
/// </summary>
/// <param name="key">Key.</param>
/// <exception cref="System.ArgumentException">if the key is of the wrong length, or has invalid bits set
/// in the <code>r</code> portion of the key.</exception>
public static void CheckKey(byte[] key)
{
if (key.Length != 32)
throw new ArgumentException("Poly1305 key must be 256 bits.");
CheckMask(key[3], R_MASK_HIGH_4);
CheckMask(key[7], R_MASK_HIGH_4);
CheckMask(key[11], R_MASK_HIGH_4);
CheckMask(key[15], R_MASK_HIGH_4);
CheckMask(key[4], R_MASK_LOW_2);
CheckMask(key[8], R_MASK_LOW_2);
CheckMask(key[12], R_MASK_LOW_2);
}
private static void CheckMask(byte b, byte mask)
{
if ((b & (~mask)) != 0)
throw new ArgumentException("Invalid format for r portion of Poly1305 key.");
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8249664920ec44707b2e157acc7aea74
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 74fcbd849e4ed4de2b91b5fd2622bb3e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: