/** * 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); }
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) { 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; }
/** * Given the domain parameters this routine generates an EC key * pair in accordance with X9.62 section 5.2.1 pages 26, 27. */ public AsymmetricCipherKeyPair GenerateKeyPair() { BigInteger n = parameters.N; BigInteger d; int minWeight = n.BitLength >> 2; for (;;) { d = new BigInteger(n.BitLength, random); if (d.CompareTo(BigInteger.Two) < 0 || d.CompareTo(n) >= 0) continue; /* * 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(d) < minWeight) continue; break; } ECPoint q = CreateBasePointMultiplier().Multiply(parameters.G, d); if (publicKeyParamSet != null) { return new AsymmetricCipherKeyPair( new ECPublicKeyParameters(algorithm, q, publicKeyParamSet), new ECPrivateKeyParameters(algorithm, d, publicKeyParamSet)); } return new AsymmetricCipherKeyPair( new ECPublicKeyParameters(algorithm, q, parameters), new ECPrivateKeyParameters(algorithm, d, parameters)); }
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."); BigInteger input = new BigInteger(1, inBuf, inOff, inLen); if (input.CompareTo(key.Modulus) >= 0) throw new DataLengthException("input too large for RSA cipher."); return input; }
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)); }
/** * 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; } } } }
internal static PublicKey Derivate(this PublicKey publicKey, byte[] cc, uint nChild, Network network, out byte[] ccChild) { byte[] lr = null; byte[] l = new byte[32]; byte[] r = new byte[32]; if ((nChild >> 31) == 0) { var pubKey = publicKey.ToBytes(); lr = Hashes.BIP32Hash(cc, nChild, pubKey[0], pubKey.Skip(1).ToArray()); } else { throw new InvalidOperationException("A public key can't derivate an hardened child"); } Array.Copy(lr, l, 32); Array.Copy(lr, 32, r, 0, 32); ccChild = r; BigInteger N = ECHelper.CURVE.N; BigInteger parse256LL = new BigInteger(1, l); if (parse256LL.CompareTo(N) >= 0) throw new InvalidOperationException("You won a prize ! this should happen very rarely. Take a screenshot, and roll the dice again."); var eq = ECHelper.Secp256k1.Curve.DecodePoint(publicKey.ToBytes()); var publicKeyParameters = new ECPublicKeyParameters("EC", eq, ECHelper.DomainParameter); var q = ECHelper.CURVE.G.Multiply(parse256LL).Add(publicKeyParameters.Q); if (q.IsInfinity) throw new InvalidOperationException("You won the big prize ! this would happen only 1 in 2^127. Take a screenshot, and roll the dice again."); var p = new BitcoinKit.BouncyCastle.Math.EC.FpPoint(ECHelper.CURVE.Curve, q.X, q.Y, true); return new PublicKey(p.GetEncoded(), network); }
private static BigInteger ReduceBarrett(BigInteger x, BigInteger m, BigInteger mr, BigInteger yu) { int xLen = x.BitLength, mLen = m.BitLength; if (xLen < mLen) return x; if (xLen - mLen > 1) { int k = m.magnitude.Length; BigInteger q1 = x.DivideWords(k - 1); BigInteger q2 = q1.Multiply(yu); // TODO Only need partial multiplication here BigInteger q3 = q2.DivideWords(k + 1); BigInteger r1 = x.RemainderWords(k + 1); BigInteger r2 = q3.Multiply(m); // TODO Only need partial multiplication here BigInteger r3 = r2.RemainderWords(k + 1); x = r1.Subtract(r3); if (x.sign < 0) { x = x.Add(mr); } } while (x.CompareTo(m) >= 0) { x = x.Subtract(m); } return x; }
// 5.4 pg 29 /** * return true if the value r and s represent a DSA signature for * the passed in message (for standard DSA the message should be * a SHA-1 hash of the real message to be verified). */ public virtual bool VerifySignature(byte[] message, BigInteger r, BigInteger s) { BigInteger n = key.Parameters.N; // r and s should both in the range [1,n-1] if (r.SignValue < 1 || s.SignValue < 1 || r.CompareTo(n) >= 0 || s.CompareTo(n) >= 0) { return false; } BigInteger e = CalculateE(n, message); BigInteger c = s.ModInverse(n); BigInteger u1 = e.Multiply(c).Mod(n); BigInteger u2 = r.Multiply(c).Mod(n); ECPoint G = key.Parameters.G; ECPoint Q = ((ECPublicKeyParameters) key).Q; ECPoint point = ECAlgorithms.SumOfTwoMultiplies(G, u1, Q, u2).Normalize(); if (point.IsInfinity) return false; BigInteger v = point.AffineXCoord.ToBigInteger().Mod(n); return v.Equals(r); }
/** * Set the private key. * * @param p key parameter: field modulus * @param q key parameter: subgroup order * @param g key parameter: generator * @param x private key */ public void setPrivateKey(BigInteger p, BigInteger q, BigInteger g, BigInteger x) { /* * Perform some basic sanity checks. We do not * check primality of p or q because that would * be too expensive. * * We reject keys where q is longer than 999 bits, * because it would complicate signature encoding. * Normal DSA keys do not have a q longer than 256 * bits anyway. */ if(p == null || q == null || g == null || x == null || p.SignValue <= 0 || q.SignValue <= 0 || g.SignValue <= 0 || x.SignValue <= 0 || x.CompareTo(q) >= 0 || q.CompareTo(p) >= 0 || q.BitLength > 999 || g.CompareTo(p) >= 0 || g.BitLength == 1 || g.ModPow(q, p).BitLength != 1) { throw new InvalidOperationException( "invalid DSA private key"); } this.p = p; this.q = q; this.g = g; this.x = x; qlen = q.BitLength; if(q.SignValue <= 0 || qlen < 8) { throw new InvalidOperationException( "bad group order: " + q); } rolen = (qlen + 7) >> 3; rlen = rolen * 8; /* * Convert the private exponent (x) into a sequence * of octets. */ bx = int2octets(x); }
/** * return true if the value r and s represent a GOST3410 signature for * the passed in message (for standard GOST3410 the message should be * a GOST3411 hash of the real message to be verified). */ public bool VerifySignature( byte[] message, BigInteger r, BigInteger s) { 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 e = new BigInteger(1, mRev); BigInteger n = key.Parameters.N; // r in the range [1,n-1] if (r.CompareTo(BigInteger.One) < 0 || r.CompareTo(n) >= 0) { return false; } // s in the range [1,n-1] if (s.CompareTo(BigInteger.One) < 0 || s.CompareTo(n) >= 0) { return false; } BigInteger v = e.ModInverse(n); BigInteger z1 = s.Multiply(v).Mod(n); BigInteger z2 = (n.Subtract(r)).Multiply(v).Mod(n); ECPoint G = key.Parameters.G; // P ECPoint Q = ((ECPublicKeyParameters)key).Q; ECPoint point = ECAlgorithms.SumOfTwoMultiplies(G, z1, Q, z2).Normalize(); if (point.IsInfinity) return false; BigInteger R = point.AffineXCoord.ToBigInteger().Mod(n); return R.Equals(r); }
internal static PrivateKey Derivate(this PrivateKey privateKey, byte[] cc, uint nChild, Network network, out byte[] ccChild) { byte[] l = null; if((nChild >> 31) == 0) { var pubKey = privateKey.GetPublicKey().ToBytes(); l = Hashes.BIP32Hash(cc, nChild, pubKey[0], pubKey.Skip(1).ToArray()); } else { l = Hashes.BIP32Hash(cc, nChild, 0, privateKey.ToBytes()); } var ll = l.Take(32).ToArray(); var lr = l.Skip(32).Take(32).ToArray(); ccChild = lr; var parse256LL = new BigInteger(1, ll); var kPar = new BigInteger(1, privateKey.ToBytes()); var N = ECHelper.CURVE.N; if(parse256LL.CompareTo(N) >= 0) throw new InvalidOperationException("You won a prize ! this should happen very rarely. Take a screenshot, and roll the dice again."); var key = parse256LL.Add(kPar).Mod(N); if(key == BigInteger.Zero) throw new InvalidOperationException("You won the big prize ! this would happen only 1 in 2^127. Take a screenshot, and roll the dice again."); var keyBytes = key.ToByteArrayUnsigned(); if(keyBytes.Length < 32) keyBytes = new byte[32 - keyBytes.Length].Concat(keyBytes).ToArray(); return new PrivateKey(keyBytes, network); }
// 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; } // 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).Normalize(); if (P.IsInfinity) return false; BigInteger x = P.AffineXCoord.ToBigInteger(); BigInteger t = r.Subtract(x).Mod(n); return t.Equals(e); }
/** * Process a single block using the basic ElGamal algorithm. * * @param in the input array. * @param inOff the offset into the input buffer where the data starts. * @param length the length of the data to be processed. * @return the result of the ElGamal process. * @exception DataLengthException the input block is too large. */ public byte[] ProcessBlock( byte[] input, int inOff, int length) { if (key == null) throw new InvalidOperationException("ElGamal engine not initialised"); int maxLength = forEncryption ? (bitSize - 1 + 7) / 8 : GetInputBlockSize(); if (length > maxLength) throw new DataLengthException("input too large for ElGamal cipher.\n"); BigInteger p = key.Parameters.P; byte[] output; if (key is ElGamalPrivateKeyParameters) // decryption { int halfLength = length / 2; BigInteger gamma = new BigInteger(1, input, inOff, halfLength); BigInteger phi = new BigInteger(1, input, inOff + halfLength, halfLength); ElGamalPrivateKeyParameters priv = (ElGamalPrivateKeyParameters) key; // a shortcut, which generally relies on p being prime amongst other things. // if a problem with this shows up, check the p and g values! BigInteger m = gamma.ModPow(p.Subtract(BigInteger.One).Subtract(priv.X), p).Multiply(phi).Mod(p); output = m.ToByteArrayUnsigned(); } else // encryption { BigInteger tmp = new BigInteger(1, input, inOff, length); if (tmp.BitLength >= p.BitLength) throw new DataLengthException("input too large for ElGamal cipher.\n"); ElGamalPublicKeyParameters pub = (ElGamalPublicKeyParameters) key; BigInteger pSub2 = p.Subtract(BigInteger.Two); // TODO In theory, a series of 'k', 'g.ModPow(k, p)' and 'y.ModPow(k, p)' can be pre-calculated BigInteger k; do { k = new BigInteger(p.BitLength, random); } while (k.SignValue == 0 || k.CompareTo(pSub2) > 0); BigInteger g = key.Parameters.G; BigInteger gamma = g.ModPow(k, p); BigInteger phi = tmp.Multiply(pub.Y.ModPow(k, p)).Mod(p); output = new byte[this.GetOutputBlockSize()]; // TODO Add methods to allow writing BigInteger to existing byte array? byte[] out1 = gamma.ToByteArrayUnsigned(); byte[] out2 = phi.ToByteArrayUnsigned(); out1.CopyTo(output, output.Length / 2 - out1.Length); out2.CopyTo(output, output.Length - out2.Length); } return output; }
public 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; int s = n.GetLowestSetBitMaskFirst(-1 << 1); Debug.Assert(s >= 1); BigInteger r = n.ShiftRight(s); // NOTE: Avoid conversion to/from Montgomery form and check for R/-R as result instead BigInteger montRadix = One.ShiftLeft(32 * n.magnitude.Length).Remainder(n); BigInteger minusMontRadix = n.Subtract(montRadix); do { BigInteger a; do { a = new BigInteger(n.BitLength, random); } while (a.sign == 0 || a.CompareTo(n) >= 0 || a.IsEqualMagnitude(montRadix) || a.IsEqualMagnitude(minusMontRadix)); BigInteger y = ModPowMonty(a, r, n, false); if (!y.Equals(montRadix)) { int j = 0; while (!y.Equals(minusMontRadix)) { if (++j == s) return false; y = ModPowMonty(y, Two, n, false); if (y.Equals(montRadix)) return false; } } certainty -= 2; // composites pass for only 1/4 possible 'a' } while (certainty > 0); return true; }