Initial Commit

This commit is contained in:
2023-06-21 12:46:23 -04:00
commit c70248a520
1352 changed files with 336780 additions and 0 deletions

View File

@@ -0,0 +1,141 @@
using System;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* Basic KDF generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
* <br/>
* This implementation is based on ISO 18033/P1363a.
*/
public class BaseKdfBytesGenerator
: IDerivationFunction
{
private int counterStart;
private IDigest digest;
private byte[] shared;
private byte[] iv;
/**
* Construct a KDF Parameters generator.
*
* @param counterStart value of counter.
* @param digest the digest to be used as the source of derived keys.
*/
protected BaseKdfBytesGenerator(
int counterStart,
IDigest digest)
{
this.counterStart = counterStart;
this.digest = digest;
}
public void Init(
IDerivationParameters parameters)
{
if (parameters is KdfParameters)
{
KdfParameters p = (KdfParameters)parameters;
shared = p.GetSharedSecret();
iv = p.GetIV();
}
else if (parameters is Iso18033KdfParameters)
{
Iso18033KdfParameters p = (Iso18033KdfParameters)parameters;
shared = p.GetSeed();
iv = null;
}
else
{
throw new ArgumentException("KDF parameters required for KDF Generator");
}
}
/**
* return the underlying digest.
*/
public IDigest Digest
{
get
{
return digest;
}
}
/**
* fill len bytes of the output buffer with bytes generated from
* the derivation function.
*
* @throws ArgumentException if the size of the request will cause an overflow.
* @throws DataLengthException if the out buffer is too small.
*/
public int GenerateBytes(
byte[] output,
int outOff,
int length)
{
if ((output.Length - length) < outOff)
{
throw new DataLengthException("output buffer too small");
}
long oBytes = length;
int outLen = digest.GetDigestSize();
//
// this is at odds with the standard implementation, the
// maximum value should be hBits * (2^32 - 1) where hBits
// is the digest output size in bits. We can't have an
// array with a long index at the moment...
//
if (oBytes > ((2L << 32) - 1))
{
throw new ArgumentException("Output length too large");
}
int cThreshold = (int)((oBytes + outLen - 1) / outLen);
byte[] dig = new byte[digest.GetDigestSize()];
int counter = counterStart;
for (int i = 0; i < cThreshold; i++)
{
digest.BlockUpdate(shared, 0, shared.Length);
digest.Update((byte)(counter >> 24));
digest.Update((byte)(counter >> 16));
digest.Update((byte)(counter >> 8));
digest.Update((byte)counter);
if (iv != null)
{
digest.BlockUpdate(iv, 0, iv.Length);
}
digest.DoFinal(dig, 0);
if (length > outLen)
{
Array.Copy(dig, 0, output, outOff, outLen);
outOff += outLen;
length -= outLen;
}
else
{
Array.Copy(dig, 0, output, outOff, length);
}
counter++;
}
digest.Reset();
return (int)oBytes;
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* a basic Diffie-Helman key pair generator.
*
* This Generates keys consistent for use with the basic algorithm for
* Diffie-Helman.
*/
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 dhParams = param.Parameters;
BigInteger p = dhParams.P;
BigInteger x = helper.CalculatePrivate(p, param.Random, dhParams.L);
BigInteger y = helper.CalculatePublic(p, dhParams.G, x);
return new AsymmetricCipherKeyPair(
new DHPublicKeyParameters(y, dhParams),
new DHPrivateKeyParameters(x, dhParams));
}
}
}

View File

@@ -0,0 +1,78 @@
using System;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Generators
{
class DHKeyGeneratorHelper
{
private const int MAX_ITERATIONS = 1000;
internal static readonly DHKeyGeneratorHelper Instance = new DHKeyGeneratorHelper();
private DHKeyGeneratorHelper()
{
}
internal BigInteger CalculatePrivate(
BigInteger p,
SecureRandom random,
int limit)
{
//
// calculate the private key
//
BigInteger pSub2 = p.Subtract(BigInteger.Two);
BigInteger x;
if (limit == 0)
{
x = createInRange(pSub2, random);
}
else
{
do
{
// TODO Check this (should the generated numbers always be odd,
// and length 'limit'?)
x = new BigInteger(limit, 0, random);
}
while (x.SignValue == 0);
}
return x;
}
private BigInteger createInRange(
BigInteger max,
SecureRandom random)
{
BigInteger x;
int maxLength = max.BitLength;
int count = 0;
do
{
x = new BigInteger(maxLength, random);
count++;
}
while ((x.SignValue == 0 || x.CompareTo(max) > 0) && count != MAX_ITERATIONS);
if (count == MAX_ITERATIONS) // fall back to a faster (restricted) method
{
return new BigInteger(maxLength - 1, random).SetBit(0);
}
return x;
}
internal BigInteger CalculatePublic(
BigInteger p,
BigInteger g,
BigInteger x)
{
return g.ModPow(x, p);
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* a Diffie-Helman 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 dhParams = param.Parameters;
BigInteger p = dhParams.P;
BigInteger x = helper.CalculatePrivate(p, param.Random, dhParams.L);
BigInteger y = helper.CalculatePublic(p, dhParams.G, x);
return new AsymmetricCipherKeyPair(
new DHPublicKeyParameters(y, dhParams),
new DHPrivateKeyParameters(x, dhParams));
}
}
}

View File

@@ -0,0 +1,45 @@
using System;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto.Parameters;
namespace Org.BouncyCastle.Crypto.Generators
{
public class DHParametersGenerator
{
private int size;
private int certainty;
private SecureRandom random;
public virtual void Init(
int size,
int certainty,
SecureRandom random)
{
this.size = size;
this.certainty = certainty;
this.random = random;
}
/**
* which Generates the p and g values from the given parameters,
* returning the DHParameters object.
* <p>
* Note: can take a while...</p>
*/
public virtual DHParameters GenerateParameters()
{
//
// find a safe prime p where p = 2*q + 1, where p and q are prime.
//
BigInteger[] safePrimes = DHParametersHelper.GenerateSafePrimes(size, certainty, random);
BigInteger p = safePrimes[0];
BigInteger q = safePrimes[1];
BigInteger g = DHParametersHelper.SelectGenerator(p, q, random);
return new DHParameters(p, g, q, BigInteger.Two, null);
}
}
}

View File

@@ -0,0 +1,244 @@
using System;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Generators
{
internal class DHParametersHelper
{
// The primes b/w 2 and ~2^10
/*
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 563 569 571 577 587 593 599 601
607 613 617 619 631 641 643 647 653 659
661 673 677 683 691 701 709 719 727 733
739 743 751 757 761 769 773 787 797 809
811 821 823 827 829 839 853 857 859 863
877 881 883 887 907 911 919 929 937 941
947 953 967 971 977 983 991 997
1009 1013 1019 1021 1031
*/
// Each list has a product < 2^31
private static readonly int[][] primeLists = new int[][]
{
new int[]{ 3, 5, 7, 11, 13, 17, 19, 23 },
new int[]{ 29, 31, 37, 41, 43 },
new int[]{ 47, 53, 59, 61, 67 },
new int[]{ 71, 73, 79, 83 },
new int[]{ 89, 97, 101, 103 },
new int[]{ 107, 109, 113, 127 },
new int[]{ 131, 137, 139, 149 },
new int[]{ 151, 157, 163, 167 },
new int[]{ 173, 179, 181, 191 },
new int[]{ 193, 197, 199, 211 },
new int[]{ 223, 227, 229 },
new int[]{ 233, 239, 241 },
new int[]{ 251, 257, 263 },
new int[]{ 269, 271, 277 },
new int[]{ 281, 283, 293 },
new int[]{ 307, 311, 313 },
new int[]{ 317, 331, 337 },
new int[]{ 347, 349, 353 },
new int[]{ 359, 367, 373 },
new int[]{ 379, 383, 389 },
new int[]{ 397, 401, 409 },
new int[]{ 419, 421, 431 },
new int[]{ 433, 439, 443 },
new int[]{ 449, 457, 461 },
new int[]{ 463, 467, 479 },
new int[]{ 487, 491, 499 },
new int[]{ 503, 509, 521 },
new int[]{ 523, 541, 547 },
new int[]{ 557, 563, 569 },
new int[]{ 571, 577, 587 },
new int[]{ 593, 599, 601 },
new int[]{ 607, 613, 617 },
new int[]{ 619, 631, 641 },
new int[]{ 643, 647, 653 },
new int[]{ 659, 661, 673 },
new int[]{ 677, 683, 691 },
new int[]{ 701, 709, 719 },
new int[]{ 727, 733, 739 },
new int[]{ 743, 751, 757 },
new int[]{ 761, 769, 773 },
new int[]{ 787, 797, 809 },
new int[]{ 811, 821, 823 },
new int[]{ 827, 829, 839 },
new int[]{ 853, 857, 859 },
new int[]{ 863, 877, 881 },
new int[]{ 883, 887, 907 },
new int[]{ 911, 919, 929 },
new int[]{ 937, 941, 947 },
new int[]{ 953, 967, 971 },
new int[]{ 977, 983, 991 },
new int[]{ 997, 1009, 1013 },
new int[]{ 1019, 1021, 1031 },
};
private static readonly BigInteger Six = BigInteger.ValueOf(6);
private static readonly int[] primeProducts;
private static readonly BigInteger[] PrimeProducts;
static DHParametersHelper()
{
primeProducts = new int[primeLists.Length];
PrimeProducts = new BigInteger[primeLists.Length];
for (int i = 0; i < primeLists.Length; ++i)
{
int[] primeList = primeLists[i];
int product = 1;
for (int j = 0; j < primeList.Length; ++j)
{
product *= primeList[j];
}
primeProducts[i] = product;
PrimeProducts[i] = BigInteger.ValueOf(product);
}
}
// Finds a pair of prime BigInteger's {p, q: p = 2q + 1}
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(PrimeProducts[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 };
}
// 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
internal static BigInteger SelectGenerator(
BigInteger p,
BigInteger q,
SecureRandom random)
{
BigInteger pMinusTwo = p.Subtract(BigInteger.Two);
BigInteger g;
// Handbook of Applied Cryptography 4.86
do
{
g = CreateInRange(BigInteger.Two, pMinusTwo, random);
}
while (g.ModPow(BigInteger.Two, p).Equals(BigInteger.One)
|| g.ModPow(q, p).Equals(BigInteger.One));
/*
// RFC 2631 2.1.1 (and see Handbook of Applied Cryptography 4.81)
do
{
BigInteger h = CreateInRange(BigInteger.Two, pMinusTwo, random);
g = h.ModPow(BigInteger.Two, p);
}
while (g.Equals(BigInteger.One));
*/
return g;
}
private static BigInteger CreateInRange(
BigInteger min,
BigInteger max,
SecureRandom random)
{
BigInteger x;
do
{
x = new BigInteger(max.BitLength, random);
}
while (x.CompareTo(min) < 0 || x.CompareTo(max) > 0);
return x;
}
}
}

View File

@@ -0,0 +1,66 @@
using System;
using Org.BouncyCastle.Crypto.Parameters;
namespace Org.BouncyCastle.Crypto.Generators
{
public class DesEdeKeyGenerator
: DesKeyGenerator
{
public DesEdeKeyGenerator()
{
}
internal DesEdeKeyGenerator(
int defaultStrength)
: base(defaultStrength)
{
}
/**
* initialise the key generator - if strength is set to zero
* the key Generated will be 192 bits in size, otherwise
* strength can be 128 or 192 (or 112 or 168 if you don't count
* parity bits), depending on whether you wish to do 2-key or 3-key
* triple DES.
*
* @param param the parameters to be used for key generation
*/
protected override void engineInit(
KeyGenerationParameters parameters)
{
base.engineInit(parameters);
if (strength == 0 || strength == (168 / 8))
{
strength = DesEdeParameters.DesEdeKeyLength;
}
else if (strength == (112 / 8))
{
strength = 2 * DesEdeParameters.DesKeyLength;
}
else if (strength != DesEdeParameters.DesEdeKeyLength
&& strength != (2 * DesEdeParameters.DesKeyLength))
{
throw new ArgumentException("DESede key must be "
+ (DesEdeParameters.DesEdeKeyLength * 8) + " or "
+ (2 * 8 * DesEdeParameters.DesKeyLength)
+ " bits long.");
}
}
protected override byte[] engineGenerateKey()
{
byte[] newKey;
do
{
newKey = random.GenerateSeed(strength);
DesEdeParameters.SetOddParity(newKey);
}
while (DesEdeParameters.IsWeakKey(newKey, 0, newKey.Length));
return newKey;
}
}
}

View File

@@ -0,0 +1,34 @@
using System;
using Org.BouncyCastle.Crypto.Parameters;
namespace Org.BouncyCastle.Crypto.Generators
{
public class DesKeyGenerator
: CipherKeyGenerator
{
public DesKeyGenerator()
{
}
internal DesKeyGenerator(
int defaultStrength)
: base(defaultStrength)
{
}
protected override byte[] engineGenerateKey()
{
byte[] newKey;
do
{
newKey = random.GenerateSeed(DesParameters.DesKeyLength);
DesParameters.SetOddParity(newKey);
}
while (DesParameters.IsWeakKey(newKey, 0));
return newKey;
}
}
}

View File

@@ -0,0 +1,56 @@
using System;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* a DSA key pair generator.
*
* This Generates DSA keys in line with the method described
* in FIPS 186-2.
*/
public class DsaKeyPairGenerator
: IAsymmetricCipherKeyPairGenerator
{
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;
SecureRandom random = param.Random;
BigInteger q = dsaParams.Q;
BigInteger x;
do
{
x = new BigInteger(160, random);
}
while (x.SignValue == 0 || x.CompareTo(q) >= 0);
//
// calculate the public key.
//
BigInteger y = dsaParams.G.ModPow(x, dsaParams.P);
return new AsymmetricCipherKeyPair(
new DsaPublicKeyParameters(y, dsaParams),
new DsaPrivateKeyParameters(x, dsaParams));
}
}
}

View File

@@ -0,0 +1,184 @@
using System;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* Generate suitable parameters for DSA, in line with FIPS 186-2.
*/
public class DsaParametersGenerator
{
private int size;
private int certainty;
private SecureRandom random;
/**
* initialise the key generator.
*
* @param size size of the key (range 2^512 -> 2^1024 - 64 bit increments)
* @param certainty measure of robustness of prime (for FIPS 186-2 compliance this should be at least 80).
* @param random random byte source.
*/
public void Init(
int size,
int certainty,
SecureRandom random)
{
if (!IsValidDsaStrength(size))
throw new ArgumentException("size must be from 512 - 1024 and a multiple of 64", "size");
this.size = size;
this.certainty = certainty;
this.random = random;
}
/**
* add value to b, returning the result in a. The a value is treated
* as a BigInteger of length (a.Length * 8) bits. The result is
* modulo 2^a.Length in case of overflow.
*/
private static void Add(
byte[] a,
byte[] b,
int value)
{
int x = (b[b.Length - 1] & 0xff) + value;
a[b.Length - 1] = (byte)x;
x = (int) ((uint) x >>8);
for (int i = b.Length - 2; i >= 0; i--)
{
x += (b[i] & 0xff);
a[i] = (byte)x;
x = (int) ((uint) x >>8);
}
}
/**
* 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));
}
private static bool IsValidDsaStrength(
int strength)
{
return strength >= 512 && strength <= 1024 && strength % 64 == 0;
}
}
}

View File

@@ -0,0 +1,130 @@
using System;
using System.Globalization;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Security;
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 = VerifyAlgorithmName(algorithm);
}
public void Init(
KeyGenerationParameters parameters)
{
if (parameters is ECKeyGenerationParameters)
{
ECKeyGenerationParameters ecP = (ECKeyGenerationParameters) parameters;
if (ecP.PublicKeyParamSet != null)
{
if (algorithm != "ECGOST3410")
throw new ArgumentException("parameters invalid for algorithm: " + algorithm, "parameters");
this.publicKeyParamSet = ecP.PublicKeyParamSet;
}
this.parameters = ecP.DomainParameters;
}
else
{
DerObjectIdentifier oid;
switch (parameters.Strength)
{
case 192:
oid = X9ObjectIdentifiers.Prime192v1;
break;
case 239:
oid = X9ObjectIdentifiers.Prime239v1;
break;
case 256:
oid = X9ObjectIdentifiers.Prime256v1;
break;
default:
throw new InvalidParameterException("unknown key size.");
}
X9ECParameters ecps = X962NamedCurves.GetByOid(oid);
this.parameters = new ECDomainParameters(
ecps.Curve, ecps.G, ecps.N, ecps.H, ecps.GetSeed());
}
this.random = parameters.Random;
}
/**
* 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;
do
{
d = new BigInteger(n.BitLength, random);
}
while (d.SignValue == 0 || (d.CompareTo(n) >= 0));
ECPoint q = parameters.G.Multiply(d);
if (publicKeyParamSet != null)
{
return new AsymmetricCipherKeyPair(
new ECPublicKeyParameters(q, publicKeyParamSet),
new ECPrivateKeyParameters(d, publicKeyParamSet));
}
return new AsymmetricCipherKeyPair(
new ECPublicKeyParameters(algorithm, q, parameters),
new ECPrivateKeyParameters(algorithm, d, parameters));
}
private string VerifyAlgorithmName(
string algorithm)
{
string upper = algorithm.ToUpper(CultureInfo.InvariantCulture);
switch (upper)
{
case "EC":
case "ECDSA":
case "ECGOST3410":
case "ECDH":
case "ECDHC":
break;
default:
throw new ArgumentException("unrecognised algorithm: " + algorithm, "algorithm");
}
return upper;
}
}
}

View File

@@ -0,0 +1,40 @@
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 elParams = param.Parameters;
BigInteger p = elParams.P;
BigInteger x = helper.CalculatePrivate(p, param.Random, elParams.L);
BigInteger y = helper.CalculatePublic(p, elParams.G, x);
return new AsymmetricCipherKeyPair(
new ElGamalPublicKeyParameters(y, elParams),
new ElGamalPrivateKeyParameters(x, elParams));
}
}
}

View File

@@ -0,0 +1,46 @@
using System;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto.Parameters;
namespace Org.BouncyCastle.Crypto.Generators
{
public class ElGamalParametersGenerator
{
private int size;
private int certainty;
private SecureRandom random;
public void Init(
int size,
int certainty,
SecureRandom random)
{
this.size = size;
this.certainty = certainty;
this.random = random;
}
/**
* which Generates the p and g values from the given parameters,
* returning the ElGamalParameters object.
* <p>
* Note: can take a while...
* </p>
*/
public ElGamalParameters GenerateParameters()
{
//
// find a safe prime p where p = 2*q + 1, where p and q are prime.
//
BigInteger[] safePrimes = DHParametersHelper.GenerateSafePrimes(size, certainty, random);
BigInteger p = safePrimes[0];
BigInteger q = safePrimes[1];
BigInteger g = DHParametersHelper.SelectGenerator(p, q, random);
return new ElGamalParameters(p, g);
}
}
}

View File

@@ -0,0 +1,73 @@
using System;
using Org.BouncyCastle.Asn1.CryptoPro;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* a GOST3410 key pair generator.
* This generates GOST3410 keys in line with the method described
* in GOST R 34.10-94.
*/
public class Gost3410KeyPairGenerator
: IAsymmetricCipherKeyPairGenerator
{
private Gost3410KeyGenerationParameters param;
public void Init(
KeyGenerationParameters parameters)
{
if (parameters is Gost3410KeyGenerationParameters)
{
this.param = (Gost3410KeyGenerationParameters) parameters;
}
else
{
Gost3410KeyGenerationParameters kgp = new Gost3410KeyGenerationParameters(
parameters.Random,
CryptoProObjectIdentifiers.GostR3410x94CryptoProA);
if (parameters.Strength != kgp.Parameters.P.BitLength - 1)
{
// TODO Should we complain?
}
this.param = kgp;
}
}
public AsymmetricCipherKeyPair GenerateKeyPair()
{
SecureRandom random = param.Random;
Gost3410Parameters gost3410Params = param.Parameters;
BigInteger q = gost3410Params.Q;
BigInteger x;
do
{
x = new BigInteger(256, random);
}
while (x.SignValue < 1 || x.CompareTo(q) >= 0);
BigInteger p = gost3410Params.P;
BigInteger a = gost3410Params.A;
// calculate the public key.
BigInteger y = a.ModPow(x, p);
if (param.PublicKeyParamSet != null)
{
return new AsymmetricCipherKeyPair(
new Gost3410PublicKeyParameters(y, param.PublicKeyParamSet),
new Gost3410PrivateKeyParameters(x, param.PublicKeyParamSet));
}
return new AsymmetricCipherKeyPair(
new Gost3410PublicKeyParameters(y, gost3410Params),
new Gost3410PrivateKeyParameters(x, gost3410Params));
}
}
}

View File

@@ -0,0 +1,530 @@
using System;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* generate suitable parameters for GOST3410.
*/
public class Gost3410ParametersGenerator
{
private int size;
private int typeproc;
private SecureRandom init_random;
/**
* initialise the key generator.
*
* @param size size of the key
* @param typeProcedure type procedure A,B = 1; A',B' - else
* @param random random byte source.
*/
public void Init(
int size,
int typeProcedure,
SecureRandom random)
{
this.size = size;
this.typeproc = typeProcedure;
this.init_random = random;
}
//Procedure A
private int procedure_A(int x0, int c, BigInteger[] pq, int size)
{
//Verify and perform condition: 0<x<2^16; 0<c<2^16; c - odd.
while(x0<0 || x0>65536)
{
x0 = init_random.NextInt()/32768;
}
while((c<0 || c>65536) || (c/2==0))
{
c = init_random.NextInt()/32768 + 1;
}
BigInteger C = BigInteger.ValueOf(c);
BigInteger constA16 = BigInteger.ValueOf(19381);
//step1
BigInteger[] y = new BigInteger[1]; // begin length = 1
y[0] = BigInteger.ValueOf(x0);
//step 2
int[] t = new int[1]; // t - orders; begin length = 1
t[0] = size;
int s = 0;
for (int i=0; t[i]>=17; i++)
{
// extension array t
int[] tmp_t = new int[t.Length + 1]; ///////////////
Array.Copy(t,0,tmp_t,0,t.Length); // extension
t = new int[tmp_t.Length]; // array t
Array.Copy(tmp_t, 0, t, 0, tmp_t.Length); ///////////////
t[i+1] = t[i]/2;
s = i+1;
}
//step3
BigInteger[] p = new BigInteger[s+1];
p[s] = new BigInteger("8003",16); //set min prime number length 16 bit
int m = s-1; //step4
for (int i=0; i<s; i++)
{
int rm = t[m]/16; //step5
step6: for(;;)
{
//step 6
BigInteger[] tmp_y = new BigInteger[y.Length]; ////////////////
Array.Copy(y,0,tmp_y,0,y.Length); // extension
y = new BigInteger[rm+1]; // array y
Array.Copy(tmp_y,0,y,0,tmp_y.Length); ////////////////
for (int j=0; j<rm; j++)
{
y[j+1] = (y[j].Multiply(constA16).Add(C)).Mod(BigInteger.Two.Pow(16));
}
//step 7
BigInteger Ym = BigInteger.Zero;
for (int j=0; j<rm; j++)
{
Ym = Ym.Add(y[j].ShiftLeft(16*j));
}
y[0] = y[rm]; //step 8
//step 9
BigInteger N = BigInteger.One.ShiftLeft(t[m]-1).Divide(p[m+1]).Add(
Ym.ShiftLeft(t[m]-1).Divide(p[m+1].ShiftLeft(16*rm)));
if (N.TestBit(0))
{
N = N.Add(BigInteger.One);
}
//step 10
for(;;)
{
//step 11
BigInteger NByLastP = N.Multiply(p[m+1]);
if (NByLastP.BitLength > t[m])
{
goto step6; //step 12
}
p[m] = NByLastP.Add(BigInteger.One);
//step13
if (BigInteger.Two.ModPow(NByLastP, p[m]).CompareTo(BigInteger.One) == 0
&& BigInteger.Two.ModPow(N, p[m]).CompareTo(BigInteger.One) != 0)
{
break;
}
N = N.Add(BigInteger.Two);
}
if (--m < 0)
{
pq[0] = p[0];
pq[1] = p[1];
return y[0].IntValue; //return for procedure B step 2
}
break; //step 14
}
}
return y[0].IntValue;
}
//Procedure A'
private long procedure_Aa(long x0, long c, BigInteger[] pq, int size)
{
//Verify and perform condition: 0<x<2^32; 0<c<2^32; c - odd.
while(x0<0 || x0>4294967296L)
{
x0 = init_random.NextInt()*2;
}
while((c<0 || c>4294967296L) || (c/2==0))
{
c = init_random.NextInt()*2+1;
}
BigInteger C = BigInteger.ValueOf(c);
BigInteger constA32 = BigInteger.ValueOf(97781173);
//step1
BigInteger[] y = new BigInteger[1]; // begin length = 1
y[0] = BigInteger.ValueOf(x0);
//step 2
int[] t = new int[1]; // t - orders; begin length = 1
t[0] = size;
int s = 0;
for (int i=0; t[i]>=33; i++)
{
// extension array t
int[] tmp_t = new int[t.Length + 1]; ///////////////
Array.Copy(t,0,tmp_t,0,t.Length); // extension
t = new int[tmp_t.Length]; // array t
Array.Copy(tmp_t, 0, t, 0, tmp_t.Length); ///////////////
t[i+1] = t[i]/2;
s = i+1;
}
//step3
BigInteger[] p = new BigInteger[s+1];
p[s] = new BigInteger("8000000B",16); //set min prime number length 32 bit
int m = s-1; //step4
for (int i=0; i<s; i++)
{
int rm = t[m]/32; //step5
step6: for(;;)
{
//step 6
BigInteger[] tmp_y = new BigInteger[y.Length]; ////////////////
Array.Copy(y,0,tmp_y,0,y.Length); // extension
y = new BigInteger[rm+1]; // array y
Array.Copy(tmp_y,0,y,0,tmp_y.Length); ////////////////
for (int j=0; j<rm; j++)
{
y[j+1] = (y[j].Multiply(constA32).Add(C)).Mod(BigInteger.Two.Pow(32));
}
//step 7
BigInteger Ym = BigInteger.Zero;
for (int j=0; j<rm; j++)
{
Ym = Ym.Add(y[j].ShiftLeft(32*j));
}
y[0] = y[rm]; //step 8
//step 9
BigInteger N = BigInteger.One.ShiftLeft(t[m]-1).Divide(p[m+1]).Add(
Ym.ShiftLeft(t[m]-1).Divide(p[m+1].ShiftLeft(32*rm)));
if (N.TestBit(0))
{
N = N.Add(BigInteger.One);
}
//step 10
for(;;)
{
//step 11
BigInteger NByLastP = N.Multiply(p[m+1]);
if (NByLastP.BitLength > t[m])
{
goto step6; //step 12
}
p[m] = NByLastP.Add(BigInteger.One);
//step13
if (BigInteger.Two.ModPow(NByLastP, p[m]).CompareTo(BigInteger.One) == 0
&& BigInteger.Two.ModPow(N, p[m]).CompareTo(BigInteger.One) != 0)
{
break;
}
N = N.Add(BigInteger.Two);
}
if (--m < 0)
{
pq[0] = p[0];
pq[1] = p[1];
return y[0].LongValue; //return for procedure B' step 2
}
break; //step 14
}
}
return y[0].LongValue;
}
//Procedure B
private void procedure_B(int x0, int c, BigInteger[] pq)
{
//Verify and perform condition: 0<x<2^16; 0<c<2^16; c - odd.
while(x0<0 || x0>65536)
{
x0 = init_random.NextInt()/32768;
}
while((c<0 || c>65536) || (c/2==0))
{
c = init_random.NextInt()/32768 + 1;
}
BigInteger [] qp = new BigInteger[2];
BigInteger q = null, Q = null, p = null;
BigInteger C = BigInteger.ValueOf(c);
BigInteger constA16 = BigInteger.ValueOf(19381);
//step1
x0 = procedure_A(x0, c, qp, 256);
q = qp[0];
//step2
x0 = procedure_A(x0, c, qp, 512);
Q = qp[0];
BigInteger[] y = new BigInteger[65];
y[0] = BigInteger.ValueOf(x0);
const int tp = 1024;
BigInteger qQ = q.Multiply(Q);
step3:
for(;;)
{
//step 3
for (int j=0; j<64; j++)
{
y[j+1] = (y[j].Multiply(constA16).Add(C)).Mod(BigInteger.Two.Pow(16));
}
//step 4
BigInteger Y = BigInteger.Zero;
for (int j=0; j<64; j++)
{
Y = Y.Add(y[j].ShiftLeft(16*j));
}
y[0] = y[64]; //step 5
//step 6
BigInteger N = BigInteger.One.ShiftLeft(tp-1).Divide(qQ).Add(
Y.ShiftLeft(tp-1).Divide(qQ.ShiftLeft(1024)));
if (N.TestBit(0))
{
N = N.Add(BigInteger.One);
}
//step 7
for(;;)
{
//step 11
BigInteger qQN = qQ.Multiply(N);
if (qQN.BitLength > tp)
{
goto step3; //step 9
}
p = qQN.Add(BigInteger.One);
//step10
if (BigInteger.Two.ModPow(qQN, p).CompareTo(BigInteger.One) == 0
&& BigInteger.Two.ModPow(q.Multiply(N), p).CompareTo(BigInteger.One) != 0)
{
pq[0] = p;
pq[1] = q;
return;
}
N = N.Add(BigInteger.Two);
}
}
}
//Procedure B'
private void procedure_Bb(long x0, long c, BigInteger[] pq)
{
//Verify and perform condition: 0<x<2^32; 0<c<2^32; c - odd.
while(x0<0 || x0>4294967296L)
{
x0 = init_random.NextInt()*2;
}
while((c<0 || c>4294967296L) || (c/2==0))
{
c = init_random.NextInt()*2+1;
}
BigInteger [] qp = new BigInteger[2];
BigInteger q = null, Q = null, p = null;
BigInteger C = BigInteger.ValueOf(c);
BigInteger constA32 = BigInteger.ValueOf(97781173);
//step1
x0 = procedure_Aa(x0, c, qp, 256);
q = qp[0];
//step2
x0 = procedure_Aa(x0, c, qp, 512);
Q = qp[0];
BigInteger[] y = new BigInteger[33];
y[0] = BigInteger.ValueOf(x0);
const int tp = 1024;
BigInteger qQ = q.Multiply(Q);
step3:
for(;;)
{
//step 3
for (int j=0; j<32; j++)
{
y[j+1] = (y[j].Multiply(constA32).Add(C)).Mod(BigInteger.Two.Pow(32));
}
//step 4
BigInteger Y = BigInteger.Zero;
for (int j=0; j<32; j++)
{
Y = Y.Add(y[j].ShiftLeft(32*j));
}
y[0] = y[32]; //step 5
//step 6
BigInteger N = BigInteger.One.ShiftLeft(tp-1).Divide(qQ).Add(
Y.ShiftLeft(tp-1).Divide(qQ.ShiftLeft(1024)));
if (N.TestBit(0))
{
N = N.Add(BigInteger.One);
}
//step 7
for(;;)
{
//step 11
BigInteger qQN = qQ.Multiply(N);
if (qQN.BitLength > tp)
{
goto step3; //step 9
}
p = qQN.Add(BigInteger.One);
//step10
if (BigInteger.Two.ModPow(qQN, p).CompareTo(BigInteger.One) == 0
&& BigInteger.Two.ModPow(q.Multiply(N), p).CompareTo(BigInteger.One) != 0)
{
pq[0] = p;
pq[1] = q;
return;
}
N = N.Add(BigInteger.Two);
}
}
}
/**
* Procedure C
* procedure generates the a value from the given p,q,
* returning the a value.
*/
private BigInteger procedure_C(BigInteger p, BigInteger q)
{
BigInteger pSub1 = p.Subtract(BigInteger.One);
BigInteger pSub1Divq = pSub1.Divide(q);
for(;;)
{
BigInteger d = new BigInteger(p.BitLength, init_random);
// 1 < d < p-1
if (d.CompareTo(BigInteger.One) > 0 && d.CompareTo(pSub1) < 0)
{
BigInteger a = d.ModPow(pSub1Divq, p);
if (a.CompareTo(BigInteger.One) != 0)
{
return a;
}
}
}
}
/**
* which generates the p , q and a values from the given parameters,
* returning the Gost3410Parameters object.
*/
public Gost3410Parameters GenerateParameters()
{
BigInteger [] pq = new BigInteger[2];
BigInteger q = null, p = null, a = null;
int x0, c;
long x0L, cL;
if (typeproc==1)
{
x0 = init_random.NextInt();
c = init_random.NextInt();
switch(size)
{
case 512:
procedure_A(x0, c, pq, 512);
break;
case 1024:
procedure_B(x0, c, pq);
break;
default:
throw new ArgumentException("Ooops! key size 512 or 1024 bit.");
}
p = pq[0]; q = pq[1];
a = procedure_C(p, q);
//System.out.println("p:"+p.toString(16)+"\n"+"q:"+q.toString(16)+"\n"+"a:"+a.toString(16));
//System.out.println("p:"+p+"\n"+"q:"+q+"\n"+"a:"+a);
return new Gost3410Parameters(p, q, a, new Gost3410ValidationParameters(x0, c));
}
else
{
x0L = init_random.NextLong();
cL = init_random.NextLong();
switch(size)
{
case 512:
procedure_Aa(x0L, cL, pq, 512);
break;
case 1024:
procedure_Bb(x0L, cL, pq);
break;
default:
throw new InvalidOperationException("Ooops! key size 512 or 1024 bit.");
}
p = pq[0]; q = pq[1];
a = procedure_C(p, q);
//System.out.println("p:"+p.toString(16)+"\n"+"q:"+q.toString(16)+"\n"+"a:"+a.toString(16));
//System.out.println("p:"+p+"\n"+"q:"+q+"\n"+"a:"+a);
return new Gost3410Parameters(p, q, a, new Gost3410ValidationParameters(x0L, cL));
}
}
}
}

View File

@@ -0,0 +1,27 @@
using System;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* KFD2 generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
* <br/>
* This implementation is based on IEEE P1363/ISO 18033.
*/
public class Kdf1BytesGenerator
: BaseKdfBytesGenerator
{
/**
* Construct a KDF1 byte generator.
*
* @param digest the digest to be used as the source of derived keys.
*/
public Kdf1BytesGenerator(
IDigest digest)
: base(0, digest)
{
}
}
}

View File

@@ -0,0 +1,28 @@
using System;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* KFD2 generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
* <br/>
* This implementation is based on IEEE P1363/ISO 18033.
*/
public class Kdf2BytesGenerator
: BaseKdfBytesGenerator
{
/**
* Construct a KDF2 bytes generator. Generates key material
* according to IEEE P1363 or ISO 18033 depending on the initialisation.
*
* @param digest the digest to be used as the source of derived keys.
*/
public Kdf2BytesGenerator(
IDigest digest)
: base(1, digest)
{
}
}
}

View File

@@ -0,0 +1,117 @@
using System;
//using Org.BouncyCastle.Math;
//using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* Generator for MGF1 as defined in Pkcs 1v2
*/
public class Mgf1BytesGenerator : IDerivationFunction
{
private IDigest digest;
private byte[] seed;
private int hLen;
/**
* @param digest the digest to be used as the source of Generated bytes
*/
public Mgf1BytesGenerator(
IDigest digest)
{
this.digest = digest;
this.hLen = digest.GetDigestSize();
}
public void Init(
IDerivationParameters parameters)
{
if (!(typeof(MgfParameters).IsInstanceOfType(parameters)))
{
throw new ArgumentException("MGF parameters required for MGF1Generator");
}
MgfParameters p = (MgfParameters)parameters;
seed = p.GetSeed();
}
/**
* return the underlying digest.
*/
public IDigest Digest
{
get
{
return digest;
}
}
/**
* int to octet string.
*/
private void ItoOSP(
int i,
byte[] sp)
{
sp[0] = (byte)((uint) i >> 24);
sp[1] = (byte)((uint) i >> 16);
sp[2] = (byte)((uint) i >> 8);
sp[3] = (byte)((uint) i >> 0);
}
/**
* fill len bytes of the output buffer with bytes Generated from
* the derivation function.
*
* @throws DataLengthException if the out buffer is too small.
*/
public int GenerateBytes(
byte[] output,
int outOff,
int length)
{
if ((output.Length - length) < outOff)
{
throw new DataLengthException("output buffer too small");
}
byte[] hashBuf = new byte[hLen];
byte[] C = new byte[4];
int counter = 0;
digest.Reset();
if (length > hLen)
{
do
{
ItoOSP(counter, C);
digest.BlockUpdate(seed, 0, seed.Length);
digest.BlockUpdate(C, 0, C.Length);
digest.DoFinal(hashBuf, 0);
Array.Copy(hashBuf, 0, output, outOff + counter * hLen, hLen);
}
while (++counter < (length / hLen));
}
if ((counter * hLen) < length)
{
ItoOSP(counter, C);
digest.BlockUpdate(seed, 0, seed.Length);
digest.BlockUpdate(C, 0, C.Length);
digest.DoFinal(hashBuf, 0);
Array.Copy(hashBuf, 0, output, outOff + counter * hLen, length - (counter * hLen));
}
return length;
}
}
}

View File

@@ -0,0 +1,330 @@
using System;
using System.Collections;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
namespace 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;
bool debug = param.IsDebug;
if (debug)
{
Console.WriteLine("Fetching first " + param.CountSmallPrimes + " primes.");
}
ArrayList 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;
if (debug)
{
Console.WriteLine("generating p and q");
}
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))
continue;
for (;;)
{
q_ = generatePrime(24, certainty, rand);
if (p_.Equals(q_))
continue;
q = q_.Multiply(_2bv).Add(BigInteger.One);
if (q.IsProbablePrime(certainty))
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)
{
if (debug)
{
Console.WriteLine("key size too small. Should be " + strength + " but is actually "
+ p.Multiply(q).BitLength);
}
continue;
}
break;
}
if (debug)
{
Console.WriteLine("needed " + tries + " tries to generate p and q.");
}
BigInteger n = p.Multiply(q);
BigInteger phi_n = p.Subtract(BigInteger.One).Multiply(q.Subtract(BigInteger.One));
BigInteger g;
tries = 0;
if (debug)
{
Console.WriteLine("generating g");
}
for (;;)
{
// TODO After the first loop, just regenerate one randomly-selected gPart each time?
ArrayList gParts = new ArrayList();
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))
{
if (debug)
{
Console.WriteLine("g has order phi(n)/" + smallPrimes[i] + "\n g: " + g);
}
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))
{
if (debug)
{
Console.WriteLine("g has order phi(n)/4\n g:" + g);
}
continue;
}
if (g.ModPow(phi_n.Divide(p_), n).Equals(BigInteger.One))
{
if (debug)
{
Console.WriteLine("g has order phi(n)/p'\n g: " + g);
}
continue;
}
if (g.ModPow(phi_n.Divide(q_), n).Equals(BigInteger.One))
{
if (debug)
{
Console.WriteLine("g has order phi(n)/q'\n g: " + g);
}
continue;
}
if (g.ModPow(phi_n.Divide(a), n).Equals(BigInteger.One))
{
if (debug)
{
Console.WriteLine("g has order phi(n)/a\n g: " + g);
}
continue;
}
if (g.ModPow(phi_n.Divide(b), n).Equals(BigInteger.One))
{
if (debug)
{
Console.WriteLine("g has order phi(n)/b\n g: " + g);
}
continue;
}
break;
}
if (debug)
{
Console.WriteLine("needed " + tries + " tries to generate g");
Console.WriteLine();
Console.WriteLine("found new NaccacheStern cipher variables:");
Console.WriteLine("smallPrimes: " + Arrays.ToString(smallPrimes.ToArray()));
Console.WriteLine("sigma:...... " + sigma + " (" + sigma.BitLength + " bits)");
Console.WriteLine("a:.......... " + a);
Console.WriteLine("b:.......... " + b);
Console.WriteLine("p':......... " + p_);
Console.WriteLine("q':......... " + q_);
Console.WriteLine("p:.......... " + p);
Console.WriteLine("q:.......... " + q);
Console.WriteLine("n:.......... " + n);
Console.WriteLine("phi(n):..... " + phi_n);
Console.WriteLine("g:.......... " + g);
Console.WriteLine();
}
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 ArrayList with the permuted elements.
*/
private static ArrayList permuteList(
ArrayList arr,
SecureRandom rand)
{
ArrayList retval = new ArrayList(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 ArrayList findFirstPrimes(
int count)
{
ArrayList primes = new ArrayList(count);
for (int i = 0; i != count; i++)
{
primes.Add(BigInteger.ValueOf(smallPrimes[i]));
}
return primes;
}
}
}

View File

@@ -0,0 +1,167 @@
using System;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* Generator for PBE derived keys and ivs as usd by OpenSSL.
* <p>
* The scheme is a simple extension of PKCS 5 V2.0 Scheme 1 using MD5 with an
* iteration count of 1.
* </p>
*/
public class OpenSslPbeParametersGenerator
: PbeParametersGenerator
{
private readonly IDigest digest = new MD5Digest();
/**
* Construct a OpenSSL Parameters generator.
*/
public OpenSslPbeParametersGenerator()
{
}
public override void Init(
byte[] password,
byte[] salt,
int iterationCount)
{
// Ignore the provided iterationCount
base.Init(password, salt, 1);
}
/**
* Initialise - note the iteration count for this algorithm is fixed at 1.
*
* @param password password to use.
* @param salt salt to use.
*/
public virtual void Init(
byte[] password,
byte[] salt)
{
base.Init(password, salt, 1);
}
/**
* the derived key function, the ith hash of the password and the salt.
*/
private byte[] GenerateDerivedKey(
int bytesNeeded)
{
byte[] buf = new byte[digest.GetDigestSize()];
byte[] key = new byte[bytesNeeded];
int offset = 0;
for (;;)
{
digest.BlockUpdate(mPassword, 0, mPassword.Length);
digest.BlockUpdate(mSalt, 0, mSalt.Length);
digest.DoFinal(buf, 0);
int len = (bytesNeeded > buf.Length) ? buf.Length : bytesNeeded;
Array.Copy(buf, 0, key, offset, len);
offset += len;
// check if we need any more
bytesNeeded -= len;
if (bytesNeeded == 0)
{
break;
}
// do another round
digest.Reset();
digest.BlockUpdate(buf, 0, buf.Length);
}
return key;
}
/**
* Generate a key parameter derived from the password, salt, and iteration
* count we are currently initialised with.
*
* @param keySize the size of the key we want (in bits)
* @return a KeyParameter object.
* @exception ArgumentException if the key length larger than the base hash size.
*/
[Obsolete("Use version with 'algorithm' parameter")]
public override ICipherParameters GenerateDerivedParameters(
int keySize)
{
return GenerateDerivedMacParameters(keySize);
}
public override ICipherParameters GenerateDerivedParameters(
string algorithm,
int keySize)
{
keySize /= 8;
byte[] dKey = GenerateDerivedKey(keySize);
return ParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize);
}
/**
* Generate a key with initialisation vector parameter derived from
* the password, salt, and iteration count we are currently initialised
* with.
*
* @param keySize the size of the key we want (in bits)
* @param ivSize the size of the iv we want (in bits)
* @return a ParametersWithIV object.
* @exception ArgumentException if keySize + ivSize is larger than the base hash size.
*/
[Obsolete("Use version with 'algorithm' parameter")]
public override ICipherParameters GenerateDerivedParameters(
int keySize,
int ivSize)
{
keySize = keySize / 8;
ivSize = ivSize / 8;
byte[] dKey = GenerateDerivedKey(keySize + ivSize);
return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
}
public override ICipherParameters GenerateDerivedParameters(
string algorithm,
int keySize,
int ivSize)
{
keySize /= 8;
ivSize /= 8;
byte[] dKey = GenerateDerivedKey(keySize + ivSize);
KeyParameter key = ParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize);
return new ParametersWithIV(key, dKey, keySize, ivSize);
}
/**
* Generate a key parameter for use with a MAC derived from the password,
* salt, and iteration count we are currently initialised with.
*
* @param keySize the size of the key we want (in bits)
* @return a KeyParameter object.
* @exception ArgumentException if the key length larger than the base hash size.
*/
public override ICipherParameters GenerateDerivedMacParameters(
int keySize)
{
keySize = keySize / 8;
byte[] dKey = GenerateDerivedKey(keySize);
return new KeyParameter(dKey, 0, keySize);
}
}
}

View File

@@ -0,0 +1,245 @@
using System;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* Generator for Pbe derived keys and ivs as defined by Pkcs 12 V1.0.
* <p>
* The document this implementation is based on can be found at
* <a href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-12/index.html">
* RSA's Pkcs12 Page</a>
* </p>
*/
public class Pkcs12ParametersGenerator
: PbeParametersGenerator
{
public const int KeyMaterial = 1;
public const int IVMaterial = 2;
public const int MacMaterial = 3;
private readonly IDigest digest;
private readonly int u;
private readonly int v;
/**
* Construct a Pkcs 12 Parameters generator.
*
* @param digest the digest to be used as the source of derived keys.
* @exception ArgumentException if an unknown digest is passed in.
*/
public Pkcs12ParametersGenerator(
IDigest digest)
{
this.digest = digest;
u = digest.GetDigestSize();
v = digest.GetByteLength();
}
/**
* add a + b + 1, returning the result in a. The a value is treated
* as a BigInteger of length (b.Length * 8) bits. The result is
* modulo 2^b.Length in case of overflow.
*/
private void Adjust(
byte[] a,
int aOff,
byte[] b)
{
int x = (b[b.Length - 1] & 0xff) + (a[aOff + b.Length - 1] & 0xff) + 1;
a[aOff + b.Length - 1] = (byte)x;
x = (int) ((uint) x >> 8);
for (int i = b.Length - 2; i >= 0; i--)
{
x += (b[i] & 0xff) + (a[aOff + i] & 0xff);
a[aOff + i] = (byte)x;
x = (int) ((uint) x >> 8);
}
}
/**
* generation of a derived key ala Pkcs12 V1.0.
*/
private byte[] GenerateDerivedKey(
int idByte,
int n)
{
byte[] D = new byte[v];
byte[] dKey = new byte[n];
for (int i = 0; i != D.Length; i++)
{
D[i] = (byte)idByte;
}
byte[] S;
if ((mSalt != null) && (mSalt.Length != 0))
{
S = new byte[v * ((mSalt.Length + v - 1) / v)];
for (int i = 0; i != S.Length; i++)
{
S[i] = mSalt[i % mSalt.Length];
}
}
else
{
S = new byte[0];
}
byte[] P;
if ((mPassword != null) && (mPassword.Length != 0))
{
P = new byte[v * ((mPassword.Length + v - 1) / v)];
for (int i = 0; i != P.Length; i++)
{
P[i] = mPassword[i % mPassword.Length];
}
}
else
{
P = new byte[0];
}
byte[] I = new byte[S.Length + P.Length];
Array.Copy(S, 0, I, 0, S.Length);
Array.Copy(P, 0, I, S.Length, P.Length);
byte[] B = new byte[v];
int c = (n + u - 1) / u;
for (int i = 1; i <= c; i++)
{
byte[] A = new byte[u];
digest.BlockUpdate(D, 0, D.Length);
digest.BlockUpdate(I, 0, I.Length);
digest.DoFinal(A, 0);
for (int j = 1; j != mIterationCount; j++)
{
digest.BlockUpdate(A, 0, A.Length);
digest.DoFinal(A, 0);
}
for (int j = 0; j != B.Length; j++)
{
B[j] = A[j % A.Length];
}
for (int j = 0; j != I.Length / v; j++)
{
Adjust(I, j * v, B);
}
if (i == c)
{
Array.Copy(A, 0, dKey, (i - 1) * u, dKey.Length - ((i - 1) * u));
}
else
{
Array.Copy(A, 0, dKey, (i - 1) * u, A.Length);
}
}
return dKey;
}
/**
* Generate a key parameter derived from the password, salt, and iteration
* count we are currently initialised with.
*
* @param keySize the size of the key we want (in bits)
* @return a KeyParameter object.
*/
[Obsolete("Use version with 'algorithm' parameter")]
public override ICipherParameters GenerateDerivedParameters(
int keySize)
{
keySize /= 8;
byte[] dKey = GenerateDerivedKey(KeyMaterial, keySize);
return new KeyParameter(dKey, 0, keySize);
}
public override ICipherParameters GenerateDerivedParameters(
string algorithm,
int keySize)
{
keySize /= 8;
byte[] dKey = GenerateDerivedKey(KeyMaterial, keySize);
return ParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize);
}
/**
* Generate a key with initialisation vector parameter derived from
* the password, salt, and iteration count we are currently initialised
* with.
*
* @param keySize the size of the key we want (in bits)
* @param ivSize the size of the iv we want (in bits)
* @return a ParametersWithIV object.
*/
[Obsolete("Use version with 'algorithm' parameter")]
public override ICipherParameters GenerateDerivedParameters(
int keySize,
int ivSize)
{
keySize /= 8;
ivSize /= 8;
byte[] dKey = GenerateDerivedKey(KeyMaterial, keySize);
byte[] iv = GenerateDerivedKey(IVMaterial, ivSize);
return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), iv, 0, ivSize);
}
public override ICipherParameters GenerateDerivedParameters(
string algorithm,
int keySize,
int ivSize)
{
keySize /= 8;
ivSize /= 8;
byte[] dKey = GenerateDerivedKey(KeyMaterial, keySize);
KeyParameter key = ParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize);
byte[] iv = GenerateDerivedKey(IVMaterial, ivSize);
return new ParametersWithIV(key, iv, 0, ivSize);
}
/**
* Generate a key parameter for use with a MAC derived from the password,
* salt, and iteration count we are currently initialised with.
*
* @param keySize the size of the key we want (in bits)
* @return a KeyParameter object.
*/
public override ICipherParameters GenerateDerivedMacParameters(
int keySize)
{
keySize /= 8;
byte[] dKey = GenerateDerivedKey(MacMaterial, keySize);
return new KeyParameter(dKey, 0, keySize);
}
}
}

View File

@@ -0,0 +1,162 @@
using System;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* Generator for Pbe derived keys and ivs as defined by Pkcs 5 V2.0 Scheme 1.
* Note this generator is limited to the size of the hash produced by the
* digest used to drive it.
* <p>
* The document this implementation is based on can be found at
* <a href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html">
* RSA's Pkcs5 Page</a>
* </p>
*/
public class Pkcs5S1ParametersGenerator
: PbeParametersGenerator
{
private readonly IDigest digest;
/**
* Construct a Pkcs 5 Scheme 1 Parameters generator.
*
* @param digest the digest to be used as the source of derived keys.
*/
public Pkcs5S1ParametersGenerator(
IDigest digest)
{
this.digest = digest;
}
/**
* the derived key function, the ith hash of the mPassword and the mSalt.
*/
private byte[] GenerateDerivedKey()
{
byte[] digestBytes = new byte[digest.GetDigestSize()];
digest.BlockUpdate(mPassword, 0, mPassword.Length);
digest.BlockUpdate(mSalt, 0, mSalt.Length);
digest.DoFinal(digestBytes, 0);
for (int i = 1; i < mIterationCount; i++)
{
digest.BlockUpdate(digestBytes, 0, digestBytes.Length);
digest.DoFinal(digestBytes, 0);
}
return digestBytes;
}
/**
* Generate a key parameter derived from the mPassword, mSalt, and iteration
* count we are currently initialised with.
*
* @param keySize the size of the key we want (in bits)
* @return a KeyParameter object.
* @exception ArgumentException if the key length larger than the base hash size.
*/
[Obsolete("Use version with 'algorithm' parameter")]
public override ICipherParameters GenerateDerivedParameters(
int keySize)
{
return GenerateDerivedMacParameters(keySize);
}
public override ICipherParameters GenerateDerivedParameters(
string algorithm,
int keySize)
{
keySize /= 8;
if (keySize > digest.GetDigestSize())
{
throw new ArgumentException(
"Can't Generate a derived key " + keySize + " bytes long.");
}
byte[] dKey = GenerateDerivedKey();
return ParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize);
}
/**
* Generate a key with initialisation vector parameter derived from
* the mPassword, mSalt, and iteration count we are currently initialised
* with.
*
* @param keySize the size of the key we want (in bits)
* @param ivSize the size of the iv we want (in bits)
* @return a ParametersWithIV object.
* @exception ArgumentException if keySize + ivSize is larger than the base hash size.
*/
[Obsolete("Use version with 'algorithm' parameter")]
public override ICipherParameters GenerateDerivedParameters(
int keySize,
int ivSize)
{
keySize /= 8;
ivSize /= 8;
if ((keySize + ivSize) > digest.GetDigestSize())
{
throw new ArgumentException(
"Can't Generate a derived key " + (keySize + ivSize) + " bytes long.");
}
byte[] dKey = GenerateDerivedKey();
return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
}
public override ICipherParameters GenerateDerivedParameters(
string algorithm,
int keySize,
int ivSize)
{
keySize /= 8;
ivSize /= 8;
if ((keySize + ivSize) > digest.GetDigestSize())
{
throw new ArgumentException(
"Can't Generate a derived key " + (keySize + ivSize) + " bytes long.");
}
byte[] dKey = GenerateDerivedKey();
KeyParameter key = ParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize);
return new ParametersWithIV(key, dKey, keySize, ivSize);
}
/**
* Generate a key parameter for use with a MAC derived from the mPassword,
* mSalt, and iteration count we are currently initialised with.
*
* @param keySize the size of the key we want (in bits)
* @return a KeyParameter object.
* @exception ArgumentException if the key length larger than the base hash size.
*/
public override ICipherParameters GenerateDerivedMacParameters(
int keySize)
{
keySize /= 8;
if (keySize > digest.GetDigestSize())
{
throw new ArgumentException(
"Can't Generate a derived key " + keySize + " bytes long.");
}
byte[] dKey = GenerateDerivedKey();
return new KeyParameter(dKey, 0, keySize);
}
}
}

View File

@@ -0,0 +1,175 @@
using System;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Macs;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* Generator for Pbe derived keys and ivs as defined by Pkcs 5 V2.0 Scheme 2.
* This generator uses a SHA-1 HMac as the calculation function.
* <p>
* The document this implementation is based on can be found at
* <a href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html">
* RSA's Pkcs5 Page</a></p>
*/
public class Pkcs5S2ParametersGenerator
: PbeParametersGenerator
{
private readonly IMac hMac = new HMac(new Sha1Digest());
/**
* construct a Pkcs5 Scheme 2 Parameters generator.
*/
public Pkcs5S2ParametersGenerator()
{
}
private void F(
byte[] P,
byte[] S,
int c,
byte[] iBuf,
byte[] outBytes,
int outOff)
{
byte[] state = new byte[hMac.GetMacSize()];
ICipherParameters param = new KeyParameter(P);
hMac.Init(param);
if (S != null)
{
hMac.BlockUpdate(S, 0, S.Length);
}
hMac.BlockUpdate(iBuf, 0, iBuf.Length);
hMac.DoFinal(state, 0);
Array.Copy(state, 0, outBytes, outOff, state.Length);
for (int count = 1; count != c; count++)
{
hMac.Init(param);
hMac.BlockUpdate(state, 0, state.Length);
hMac.DoFinal(state, 0);
for (int j = 0; j != state.Length; j++)
{
outBytes[outOff + j] ^= state[j];
}
}
}
private void IntToOctet(
byte[] Buffer,
int i)
{
Buffer[0] = (byte)((uint) i >> 24);
Buffer[1] = (byte)((uint) i >> 16);
Buffer[2] = (byte)((uint) i >> 8);
Buffer[3] = (byte)i;
}
private byte[] GenerateDerivedKey(
int dkLen)
{
int hLen = hMac.GetMacSize();
int l = (dkLen + hLen - 1) / hLen;
byte[] iBuf = new byte[4];
byte[] outBytes = new byte[l * hLen];
for (int i = 1; i <= l; i++)
{
IntToOctet(iBuf, i);
F(mPassword, mSalt, mIterationCount, iBuf, outBytes, (i - 1) * hLen);
}
return outBytes;
}
/**
* Generate a key parameter derived from the password, salt, and iteration
* count we are currently initialised with.
*
* @param keySize the size of the key we want (in bits)
* @return a KeyParameter object.
*/
[Obsolete("Use version with 'algorithm' parameter")]
public override ICipherParameters GenerateDerivedParameters(
int keySize)
{
return GenerateDerivedMacParameters(keySize);
}
public override ICipherParameters GenerateDerivedParameters(
string algorithm,
int keySize)
{
keySize /= 8;
byte[] dKey = GenerateDerivedKey(keySize);
return ParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize);
}
/**
* Generate a key with initialisation vector parameter derived from
* the password, salt, and iteration count we are currently initialised
* with.
*
* @param keySize the size of the key we want (in bits)
* @param ivSize the size of the iv we want (in bits)
* @return a ParametersWithIV object.
*/
[Obsolete("Use version with 'algorithm' parameter")]
public override ICipherParameters GenerateDerivedParameters(
int keySize,
int ivSize)
{
keySize /= 8;
ivSize /= 8;
byte[] dKey = GenerateDerivedKey(keySize + ivSize);
return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
}
public override ICipherParameters GenerateDerivedParameters(
string algorithm,
int keySize,
int ivSize)
{
keySize /= 8;
ivSize /= 8;
byte[] dKey = GenerateDerivedKey(keySize + ivSize);
KeyParameter key = ParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize);
return new ParametersWithIV(key, dKey, keySize, ivSize);
}
/**
* Generate a key parameter for use with a MAC derived from the password,
* salt, and iteration count we are currently initialised with.
*
* @param keySize the size of the key we want (in bits)
* @return a KeyParameter object.
*/
public override ICipherParameters GenerateDerivedMacParameters(
int keySize)
{
keySize /= 8;
byte[] dKey = GenerateDerivedKey(keySize);
return new KeyParameter(dKey, 0, keySize);
}
}
}

View File

@@ -0,0 +1,69 @@
using System;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* Generate a random factor suitable for use with RSA blind signatures
* as outlined in Chaum's blinding and unblinding as outlined in
* "Handbook of Applied Cryptography", page 475.
*/
public class RsaBlindingFactorGenerator
{
private RsaKeyParameters key;
private SecureRandom random;
/**
* Initialise the factor generator
*
* @param param the necessary RSA key parameters.
*/
public void Init(
ICipherParameters param)
{
if (param is ParametersWithRandom)
{
ParametersWithRandom rParam = (ParametersWithRandom)param;
key = (RsaKeyParameters)rParam.Parameters;
random = rParam.Random;
}
else
{
key = (RsaKeyParameters)param;
random = new SecureRandom();
}
if (key.IsPrivate)
throw new ArgumentException("generator requires RSA public key");
}
/**
* Generate a suitable blind factor for the public key the generator was initialised with.
*
* @return a random blind factor
*/
public BigInteger GenerateBlindingFactor()
{
if (key == null)
throw new InvalidOperationException("generator not initialised");
BigInteger m = key.Modulus;
int length = m.BitLength - 1; // must be less than m.BitLength
BigInteger factor;
BigInteger gcd;
do
{
factor = new BigInteger(length, random);
gcd = factor.Gcd(m);
}
while (factor.SignValue == 0 || factor.Equals(BigInteger.One) || !gcd.Equals(BigInteger.One));
return factor;
}
}
}

View File

@@ -0,0 +1,139 @@
using System;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Crypto.Generators
{
/**
* an RSA key pair generator.
*/
public class RsaKeyPairGenerator
: IAsymmetricCipherKeyPairGenerator
{
private static readonly BigInteger DefaultPublicExponent = BigInteger.ValueOf(0x10001);
private const int DefaultTests = 12;
private RsaKeyGenerationParameters param;
public void Init(
KeyGenerationParameters parameters)
{
if (parameters is RsaKeyGenerationParameters)
{
this.param = (RsaKeyGenerationParameters)parameters;
}
else
{
this.param = new RsaKeyGenerationParameters(
DefaultPublicExponent, parameters.Random, parameters.Strength, DefaultTests);
}
}
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));
}
}
}