/// <summary> /// Generates a KeyPair using a BigInteger as a private key. /// BigInteger is checked for appropriate range. /// </summary> public KeyPair(BigInteger bi, bool compressed = false, byte addressType = 0) { this.IsCompressedPoint = compressed; this.AddressType = addressType; var ps = Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByName("secp256k1"); if (bi.CompareTo(ps.N) >= 0 || bi.SignValue <= 0) { throw new ArgumentException("BigInteger is out of range of valid private keys"); } byte[] bb = Util.Force32Bytes(bi.ToByteArrayUnsigned()); PrivateKeyBytes = bb; }
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)); }
/** * Return a random BigInteger not less than 'min' and not greater than 'max' * * @param min the least value that may be generated * @param max the greatest value that may be generated * @param random the source of randomness * @return a random BigInteger value in the range [min,max] */ public static BigInteger CreateRandomInRange( BigInteger min, BigInteger max, // TODO Should have been just Random class SecureRandom random) { int cmp = min.CompareTo(max); if (cmp >= 0) { if (cmp > 0) throw new ArgumentException("'min' may not be greater than 'max'"); return min; } if (min.BitLength > max.BitLength / 2) { return CreateRandomInRange(BigInteger.Zero, max.Subtract(min), random).Add(min); } for (int i = 0; i < MaxIterations; ++i) { BigInteger x = new BigInteger(max.BitLength, random); if (x.CompareTo(min) >= 0 && x.CompareTo(max) <= 0) { return x; } } // fall back to a faster (restricted) method return new BigInteger(max.Subtract(min).BitLength - 1, random).Add(min); }
/// <summary> /// Constructor used by the pre-approved groups in JPakePrimeOrderGroups. /// These pre-approved groups can avoid the expensive checks. /// User-specified groups should not use this constructor. /// </summary> public JPakePrimeOrderGroup(BigInteger p, BigInteger q, BigInteger g, bool skipChecks) { JPakeUtilities.ValidateNotNull(p, "p"); JPakeUtilities.ValidateNotNull(q, "q"); JPakeUtilities.ValidateNotNull(g, "g"); if (!skipChecks) { if (!p.Subtract(JPakeUtilities.One).Mod(q).Equals(JPakeUtilities.Zero)) throw new ArgumentException("p-1 must be evenly divisible by q"); if (g.CompareTo(BigInteger.Two) == -1 || g.CompareTo(p.Subtract(JPakeUtilities.One)) == 1) throw new ArgumentException("g must be in [2, p-1]"); if (!g.ModPow(q, p).Equals(JPakeUtilities.One)) throw new ArgumentException("g^q mod p must equal 1"); // Note these checks do not guarantee that p and q are prime. // We just have reasonable certainty that they are prime. if (!p.IsProbablePrime(20)) throw new ArgumentException("p must be prime"); if (!q.IsProbablePrime(20)) throw new ArgumentException("q must be prime"); } this.p = p; this.q = q; this.g = g; }
public Org.BouncyCastle.Math.BigInteger getGCD(Org.BouncyCastle.Math.BigInteger bd1, Org.BouncyCastle.Math.BigInteger bd2) { Org.BouncyCastle.Math.BigInteger bigger = (bd1.CompareTo(bd2) > 0) ? bd1 : bd2; Org.BouncyCastle.Math.BigInteger smaller = (bd1.CompareTo(bd2) < 0) ? bd1 : bd2; Org.BouncyCastle.Math.BigInteger gcd = smaller; while (!Org.BouncyCastle.Math.BigInteger.Zero.Equals(smaller)) { gcd = smaller; smaller = bigger.Mod(smaller); bigger = gcd; } return(gcd); }
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)); }
/** * Given the domain parameters this routine Generates an EC key * pair in accordance with X9.62 section 5.2.1 pages 26, 27. */ public IAsymmetricCipherKeyPair GenerateKeyPair() { var n = _parameters.N; IBigInteger d; do { d = new BigInteger(n.BitLength, _random); } while (d.SignValue == 0 || (d.CompareTo(n) >= 0)); var isEcdh = _algorithm == "ECDH"; var q = _parameters.G.Multiply(d); if (_publicKeyParamSet != null) { return new AsymmetricCipherKeyPair( isEcdh ? new ECDHPublicKeyParameters(q, _publicKeyParamSet, _hashAlgorithm, _symmetricKeyAlgorithm) : new ECPublicKeyParameters(_algorithm, q, _publicKeyParamSet), new ECPrivateKeyParameters(_algorithm, d, _publicKeyParamSet)); } return new AsymmetricCipherKeyPair( isEcdh ? new ECDHPublicKeyParameters(q, _parameters, _hashAlgorithm, _symmetricKeyAlgorithm) : new ECPublicKeyParameters(_algorithm, q, _parameters), new ECPrivateKeyParameters(_algorithm, d, _parameters)); }
public BigInteger ConvertInput( byte[] inBuf, int inOff, int inLen) { int maxLength = (bitSize + 7) / 8; if (inLen > maxLength) throw new DataLengthException("input too large for RSA cipher."); byte[] block; if (inOff != 0 || inLen != inBuf.Length) { block = new byte[inLen]; Array.Copy(inBuf, inOff, block, 0, inLen); } else { block = inBuf; } BigInteger input = new BigInteger(1, block); if (input.CompareTo(key.Modulus) >= 0) throw new DataLengthException("input too large for RSA cipher."); return input; }
/** * generate a signature for the given message using the key we were * initialised with. For conventional Gost3410 the message should be a Gost3411 * hash of the message of interest. * * @param message the message that will be verified later. */ public BigInteger[] GenerateSignature( byte[] message) { byte[] mRev = new byte[message.Length]; // conversion is little-endian for (int i = 0; i != mRev.Length; i++) { mRev[i] = message[mRev.Length - 1 - i]; } BigInteger m = new BigInteger(1, mRev); Gost3410Parameters parameters = key.Parameters; BigInteger k; do { k = new BigInteger(parameters.Q.BitLength, random); } while (k.CompareTo(parameters.Q) >= 0); BigInteger r = parameters.A.ModPow(k, parameters.P).Mod(parameters.Q); BigInteger s = k.Multiply(m). Add(((Gost3410PrivateKeyParameters)key).X.Multiply(r)). Mod(parameters.Q); return new BigInteger[]{ r, s }; }
public static string ByteArrayToBase58(byte[] ba) { Org.BouncyCastle.Math.BigInteger addrremain = new Org.BouncyCastle.Math.BigInteger(1, ba); Org.BouncyCastle.Math.BigInteger big0 = new Org.BouncyCastle.Math.BigInteger("0"); Org.BouncyCastle.Math.BigInteger big58 = new Org.BouncyCastle.Math.BigInteger("58"); string b58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; string rv = ""; while (addrremain.CompareTo(big0) > 0) { int d = Convert.ToInt32(addrremain.Mod(big58).ToString()); addrremain = addrremain.Divide(big58); rv = b58.Substring(d, 1) + rv; } // handle leading zeroes foreach (byte b in ba) { if (b != 0) { break; } rv = "1" + rv; } return(rv); }
public RsaSecretBcpgKey( BigInteger d, BigInteger p, BigInteger q) { // PGP requires (p < q) int cmp = p.CompareTo(q); if (cmp >= 0) { if (cmp == 0) throw new ArgumentException("p and q cannot be equal"); BigInteger tmp = p; p = q; q = tmp; } this.d = new MPInteger(d); this.p = new MPInteger(p); this.q = new MPInteger(q); this.u = new MPInteger(p.ModInverse(q)); this.expP = d.Remainder(p.Subtract(BigInteger.One)); this.expQ = d.Remainder(q.Subtract(BigInteger.One)); this.crt = q.ModInverse(p); }
public Gost3410PublicKeyParameters( BigInteger y, DerObjectIdentifier publicKeyParamSet) : base(false, publicKeyParamSet) { if (y.SignValue < 1 || y.CompareTo(Parameters.P) >= 0) throw new ArgumentException("Invalid y for GOST3410 public key", "y"); this.y = y; }
public Gost3410PrivateKeyParameters( BigInteger x, DerObjectIdentifier publicKeyParamSet) : base(true, publicKeyParamSet) { if (x.SignValue < 1 || x.BitLength > 256 || x.CompareTo(Parameters.Q) >= 0) throw new ArgumentException("Invalid x for GOST3410 private key", "x"); this.x = x; }
public DHParameters( BigInteger p, BigInteger g, BigInteger q, int m, int l, BigInteger j, DHValidationParameters validation) { if (p == null) throw new ArgumentNullException("p"); if (g == null) throw new ArgumentNullException("g"); if (!p.TestBit(0)) throw new ArgumentException("field must be an odd prime", "p"); if (g.CompareTo(BigInteger.Two) < 0 || g.CompareTo(p.Subtract(BigInteger.Two)) > 0) throw new ArgumentException("generator must in the range [2, p - 2]", "g"); if (q != null && q.BitLength >= p.BitLength) throw new ArgumentException("q too big to be a factor of (p-1)", "q"); if (m >= p.BitLength) throw new ArgumentException("m value must be < bitlength of p", "m"); if (l != 0) { // TODO Check this against the Java version, which has 'l > p.BitLength' here if (l >= p.BitLength) throw new ArgumentException("when l value specified, it must be less than bitlength(p)", "l"); if (l < m) throw new ArgumentException("when l value specified, it may not be less than m value", "l"); } if (j != null && j.CompareTo(BigInteger.Two) < 0) throw new ArgumentException("subgroup factor must be >= 2", "j"); // TODO If q, j both provided, validate p = jq + 1 ? this.p = p; this.g = g; this.q = q; this.m = m; this.l = l; this.j = j; this.validation = validation; }
/// <summary> /// Returns error message in a string if private key is not within the valid range (2 ... N-1) /// </summary> private string validateRange() { Org.BouncyCastle.Math.BigInteger Db = new Org.BouncyCastle.Math.BigInteger(1, _privKey); BigInteger N = Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByName("secp256k1").N; if (Db == BigInteger.Zero || Db.CompareTo(N) >= 0) { return("Not a valid private key"); } return(null); }
public String decipher(List <Org.BouncyCastle.Math.BigInteger> cipher, MHPrivateKey key) { String decrypted = ""; Org.BouncyCastle.Math.BigInteger temp = Org.BouncyCastle.Math.BigInteger.ValueOf(0); int tmp = 0; Org.BouncyCastle.Math.BigInteger bits = Org.BouncyCastle.Math.BigInteger.ValueOf(0); for (int i = 0; i < cipher.Count; i++) { temp = cipher.ElementAt(i); int bitlen = temp.BitLength; int ff = 0; while (bitlen < (int)Math.Pow(2, ff)) { ff++; } if (ff > bitlen) { bitlen = ff; } for (int j = 0; j < bitlen; j++) { if (temp.Mod(Org.BouncyCastle.Math.BigInteger.ValueOf(2)).CompareTo(Org.BouncyCastle.Math.BigInteger.ValueOf(1)) == 0) { bits = bits.Add(key.w1.Multiply(Org.BouncyCastle.Math.BigInteger.ValueOf((long)Math.Pow(2, j)))); } temp = temp.ShiftRight(1); } bits = bits.Mod(key.n); List <Org.BouncyCastle.Math.BigInteger> list = key.a; Org.BouncyCastle.Math.BigInteger temper; int k = key.a.Count - 1; while (k >= 0) { temper = list.ElementAt(k); if (bits.CompareTo(temper) > -1) { tmp += (int)Math.Pow(2, k); bits = bits.Subtract(temper); } k--; } decrypted += (binaryToChar(Convert.ToString(tmp, 2))).ToString(); bits = Org.BouncyCastle.Math.BigInteger.ValueOf(0); tmp = 0; } return(decrypted); }
public virtual BigInteger NextK() { int qBitLength = q.BitLength; BigInteger k; do { k = new BigInteger(qBitLength, random); } while (k.SignValue < 1 || k.CompareTo(q) >= 0); return k; }
public IBigInteger ConvertInput( byte[] inBuf, int inOff, int inLen) { int maxLength = (bitSize + 7) / 8; if (inLen > maxLength) throw new DataLengthException("input too large for RSA cipher."); IBigInteger input = new BigInteger(1, inBuf, inOff, inLen); if (input.CompareTo(key.Modulus) >= 0) throw new DataLengthException("input too large for RSA cipher."); return input; }
/// <summary> /// MPI encoded numbers are produced by the OpenSSL BN_bn2mpi function. /// They consist of a 4 byte big endian length field, followed by the stated number of bytes representing the number in big endian format (with a sign bit). /// </summary> /// <param name="value"></param> /// <param name="includeLength">Indicates whether the 4 byte length field should be included</param> /// <returns></returns> public static byte[] Encode(BigInteger value,bool includeLength=true) { if(value.Equals(BigInteger.Zero)) { if(!includeLength) { return new byte[0]; } return new byte[] { 0x00,0x00,0x00,0x00 }; } bool isNegative=value.CompareTo(BigInteger.Zero)<0; if(isNegative) { value=value.Negate(); } byte[] array=value.ToByteArray(); int length=array.Length; if((array[0] & 0x80)==0x80) { length++; } if(includeLength) { byte[] result=new byte[length+4]; Array.Copy(array,0,result,length-array.Length+3,array.Length); ((uint)length).ToByteArrayBe(result); if(isNegative) { result[4]|=0x80; } return result; } else { byte[] result; if(length!=array.Length) { result=new byte[length]; Array.Copy(array,0,result,1,array.Length); } else { result=array; } if(isNegative) { result[0]|=0x80; } return result; } }
public AsymmetricCipherKeyPair GenerateKeyPair() { SecureRandom random = param.Random; Gost3410Parameters gost3410Params = param.Parameters; BigInteger q = gost3410Params.Q, x; int minWeight = 64; for (;;) { x = new BigInteger(256, random); if (x.SignValue < 1 || x.CompareTo(q) >= 0) 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(x) < minWeight) continue; break; } 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)); }
/** * Generate a signature for the given message using the key we were * initialised with. For conventional DSA the message should be a SHA-1 * hash of the message of interest. * * @param message the message that will be verified later. */ public IBigInteger[] GenerateSignature(byte[] message) { var parameters = _key.Parameters; var q = parameters.Q; var m = CalculateE(q, message); IBigInteger k; do { k = new BigInteger(q.BitLength, _random); } while (k.CompareTo(q) >= 0); var r = parameters.G.ModPow(k, parameters.P).Mod(q); k = k.ModInverse(q).Multiply(m.Add(((DsaPrivateKeyParameters)_key).X.Multiply(r))); var s = k.Mod(q); return new[] { r, s }; }
public ECDsaBouncyCastle() { var secp256k1 = SecP256k1; var privateKey = new byte[secp256k1.N.BitLength]; BigInteger d; using (var cryptoRng = RandomNumberGenerator.Create()) { do { cryptoRng.GetBytes(privateKey); d = new BigInteger(1, privateKey); } while (d.SignValue == 0 || (d.CompareTo(secp256k1.N) >= 0)); } _publicKey = new ECPublicKeyParameters(secp256k1.G.Multiply(d), secp256k1); _privateKey = new ECPrivateKeyParameters(d, secp256k1); }
public static string Encode(byte[] input) { var bi = new BigInteger(1, input); var s = new StringBuilder(); while (bi.CompareTo(Base) >= 0) { var mod = bi.Mod(Base); s.Insert(0, new[] {Alphabet[mod.IntValue]}); bi = bi.Subtract(mod).Divide(Base); } s.Insert(0, new[] {Alphabet[bi.IntValue]}); // Convert leading zeros too. foreach (var anInput in input) { if (anInput == 0) s.Insert(0, new[] {Alphabet[0]}); else break; } return s.ToString(); }
public RsaSecretBcpgKey( BigInteger d, BigInteger p, BigInteger q) { // pgp requires (p < q) if (p.CompareTo(q) > 0) { BigInteger tmp = p; p = q; q = tmp; } this.d = new MPInteger(d); this.p = new MPInteger(p); this.q = new MPInteger(q); this.u = new MPInteger(p.ModInverse(q)); this.expP = d.Remainder(p.Subtract(BigInteger.One)); this.expQ = d.Remainder(q.Subtract(BigInteger.One)); this.crt = q.ModInverse(p); }
// 5.3 pg 28 /** * Generate a signature for the given message using the key we were * initialised with. For conventional DSA the message should be a SHA-1 * hash of the message of interest. * * @param message the message that will be verified later. */ public BigInteger[] GenerateSignature( byte[] message) { BigInteger n = key.Parameters.N; BigInteger e = calculateE(n, message); BigInteger r = null; BigInteger s = null; // 5.3.2 do // Generate s { BigInteger k = null; do // Generate r { do { k = new BigInteger(n.BitLength, random); } while (k.SignValue == 0 || k.CompareTo(n) >= 0); ECPoint p = key.Parameters.G.Multiply(k); // 5.3.3 BigInteger x = p.X.ToBigInteger(); r = x.Mod(n); } while (r.SignValue == 0); BigInteger d = ((ECPrivateKeyParameters)key).D; s = k.ModInverse(n).Multiply(e.Add(d.Multiply(r).Mod(n))).Mod(n); } while (s.SignValue == 0); return new BigInteger[]{ r, s }; }
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; }
/// <summary> /// Encode a byte sequence as a base58-encoded string /// </summary> /// <param name="bytes">Byte sequence</param> /// <returns>Encoding result</returns> public static string Base58Encode(byte[] input) { // TODO: This could be a lot more efficient. var bi = new BigInteger(1, input); var s = new StringBuilder(); while (bi.CompareTo(_base) >= 0) { var mod = bi.Mod(_base); s.Insert(0, new[] { strDigits[mod.IntValue] }); bi = bi.Subtract(mod).Divide(_base); } s.Insert(0, new[] { strDigits[bi.IntValue] }); // Convert leading zeros too. foreach (var anInput in input) { if (anInput == 0) s.Insert(0, new[] { strDigits[0] }); else break; } return s.ToString(); }
public AsymmetricCipherKeyPair GenerateKeyPair() { SecureRandom random = param.Random; Gost3410Parameters gost3410Params = param.Parameters; BigInteger q = gost3410Params.Q, x; int minWeight = 64; for (;;) { x = new BigInteger(256, random); if (x.SignValue < 1 || x.CompareTo(q) >= 0) continue; if (WNafUtilities.GetNafWeight(x) < minWeight) continue; break; } 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)); }
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)); }
// 5.3 pg 28 /** * Generate a signature for the given message using the key we were * initialised with. For conventional DSA the message should be a SHA-1 * hash of the message of interest. * * @param message the message that will be verified later. */ public IBigInteger[] GenerateSignature(byte[] message) { var n = _key.Parameters.N; var e = CalculateE(n, message); IBigInteger r; IBigInteger s; // 5.3.2 do // Generate s { IBigInteger k; do // Generate r { do { k = new BigInteger(n.BitLength, _random); } while (k.SignValue == 0 || k.CompareTo(n) >= 0); var p = _key.Parameters.G.Multiply(k); // 5.3.3 var x = p.X.ToBigInteger(); r = x.Mod(n); } while (r.SignValue == 0); var d = ((ECPrivateKeyParameters)_key).D; s = k.ModInverse(n).Multiply(e.Add(d.Multiply(r))).Mod(n); } while (s.SignValue == 0); return new[] { r, s }; }
/** * 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(algorithm, q, publicKeyParamSet), new ECPrivateKeyParameters(algorithm, d, publicKeyParamSet)); } return new AsymmetricCipherKeyPair( new ECPublicKeyParameters(algorithm, q, parameters), new ECPrivateKeyParameters(algorithm, d, parameters)); }
// 5.3 pg 28 /** * Generate a signature for the given message using the key we were * initialised with. For conventional DSA the message should be a SHA-1 * hash of the message of interest. * * @param message the message that will be verified later. */ public virtual BigInteger[] GenerateSignature(byte[] message) { ECDomainParameters ec = key.Parameters; BigInteger n = ec.N; BigInteger e = CalculateE(n, message); BigInteger d = ((ECPrivateKeyParameters)key).D; BigInteger r, s; ECMultiplier basePointMultiplier = CreateBasePointMultiplier(); // 5.3.2 do // Generate s { BigInteger k; do // Generate r { do { k = new BigInteger(n.BitLength, random); } while (k.SignValue == 0 || k.CompareTo(n) >= 0); ECPoint p = basePointMultiplier.Multiply(ec.G, k).Normalize(); // 5.3.3 r = p.AffineXCoord.ToBigInteger().Mod(n); } while (r.SignValue == 0); s = k.ModInverse(n).Multiply(e.Add(d.Multiply(r))).Mod(n); } while (s.SignValue == 0); return new BigInteger[]{ r, s }; }
internal bool RabinMillerTest( int certainty, Random random) { Debug.Assert(certainty > 0); Debug.Assert(BitLength > 2); Debug.Assert(TestBit(0)); // let n = 1 + d . 2^s BigInteger n = this; BigInteger nMinusOne = n.Subtract(One); int s = nMinusOne.GetLowestSetBit(); BigInteger r = nMinusOne.ShiftRight(s); Debug.Assert(s >= 1); do { // TODO Make a method for random BigIntegers in range 0 < x < n) // - Method can be optimized by only replacing examined bits at each trial BigInteger a; do { a = new BigInteger(n.BitLength, random); } while (a.CompareTo(One) <= 0 || a.CompareTo(nMinusOne) >= 0); BigInteger y = a.ModPow(r, n); if (!y.Equals(One)) { int j = 0; while (!y.Equals(nMinusOne)) { if (++j == s) return false; y = y.ModPow(Two, n); if (y.Equals(One)) return false; } } certainty -= 2; // composites pass for only 1/4 possible 'a' } while (certainty > 0); return true; }
// Section 7.2.6 ECVP-NR, pg 35 /** * return true if the value r and s represent a signature for the * message passed in. Generally, the order of the curve should be at * least as long as the hash of the message of interest, and with * ECNR, it *must* be at least as long. But just in case the signer * applied mod(n) to the longer digest, this implementation will * apply mod(n) during verification. * * @param digest the digest to be verified. * @param r the r value of the signature. * @param s the s value of the signature. * @exception DataLengthException if the digest is longer than the key allows */ public bool VerifySignature( byte[] message, BigInteger r, BigInteger s) { if (this.forSigning) { // not properly initilaized... deal with it throw new InvalidOperationException("not initialised for verifying"); } ECPublicKeyParameters pubKey = (ECPublicKeyParameters)key; BigInteger n = pubKey.Parameters.N; int nBitLength = n.BitLength; BigInteger e = new BigInteger(1, message); int eBitLength = e.BitLength; if (eBitLength > nBitLength) { throw new DataLengthException("input too large for ECNR key."); } // r in the range [1,n-1] if (r.CompareTo(BigInteger.One) < 0 || r.CompareTo(n) >= 0) { return false; } // TODO So why is this different from the spec? // s in the range [0,n-1] NB: ECNR spec says 0 if (s.CompareTo(BigInteger.Zero) < 0 || s.CompareTo(n) >= 0) { return false; } // compute P = sG + rW ECPoint G = pubKey.Parameters.G; ECPoint W = pubKey.Q; // calculate P using Bouncy math ECPoint P = ECAlgorithms.SumOfTwoMultiplies(G, s, W, r); if (P.IsInfinity) return false; BigInteger x = P.X.ToBigInteger(); BigInteger t = r.Subtract(x).Mod(n); return t.Equals(e); }