/** * 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); }
private static BigInteger GeneratePrivateKey(BigInteger q, SecureRandom random) { // B.1.2 Key Pair Generation by Testing Candidates int minWeight = q.BitLength >> 2; for (;;) { // TODO Prefer this method? (change test cases that used fixed random) // B.1.1 Key Pair Generation Using Extra Random Bits //BigInteger x = new BigInteger(q.BitLength + 64, random).Mod(q.Subtract(One)).Add(One); BigInteger x = BigIntegers.CreateRandomInRange(One, q.Subtract(One), random); if (WNafUtilities.GetNafWeight(x) >= minWeight) { return x; } } }
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; }
// 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); }
//[Fact] //http://bitcoin.stackexchange.com/questions/25814/ecdsa-signature-and-the-z-value //http://www.nilsschneider.net/2013/01/28/recovering-bitcoin-private-keys.html public void PlayingWithSignatures() { var script1 = new Script("30440220d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1022044e1ff2dfd8102cf7a47c21d5c9fd5701610d04953c6836596b4fe9dd2f53e3e01 04dbd0c61532279cf72981c3584fc32216e0127699635c2789f549e0730c059b81ae133016a69c21e23f1859a95f06d52b7bf149a8f2fe4e8535c8a829b449c5ff"); var script2 = new Script("30440220d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad102209a5f1c75e461d7ceb1cf3cab9013eb2dc85b6d0da8c3c6e27e3a5a5b3faa5bab01 04dbd0c61532279cf72981c3584fc32216e0127699635c2789f549e0730c059b81ae133016a69c21e23f1859a95f06d52b7bf149a8f2fe4e8535c8a829b449c5ff"); var sig1 = (PayToPubkeyHashTemplate.Instance.ExtractScriptSigParameters(script1).TransactionSignature.Signature); var sig2 = (PayToPubkeyHashTemplate.Instance.ExtractScriptSigParameters(script2).TransactionSignature.Signature); var n = ECKey.CURVE.N; var z1 = new BigInteger(1, Encoders.Hex.DecodeData("c0e2d0a89a348de88fda08211c70d1d7e52ccef2eb9459911bf977d587784c6e")); var z2 = new BigInteger(1, Encoders.Hex.DecodeData("17b0f41c8c337ac1e18c98759e83a8cccbc368dd9d89e5f03cb633c265fd0ddc")); var z = z1.Subtract(z2); var s = sig1.S.Subtract(sig2.S); var n2 = BigInteger.Two.Pow(256).Subtract(new BigInteger("432420386565659656852420866394968145599")); var expected = new Key(Encoders.Hex.DecodeData("c477f9f65c22cce20657faa5b2d1d8122336f851a508a1ed04e479c34985bf96"), fCompressedIn: false); var expectedBigInt = new NBitcoin.BouncyCastle.Math.BigInteger(1, Encoders.Hex.DecodeData("c477f9f65c22cce20657faa5b2d1d8122336f851a508a1ed04e479c34985bf96")); var priv = (z1.Multiply(sig2.S).Subtract(z2.Multiply(sig1.S)).Mod(n)).Divide(sig1.R.Multiply(sig1.S.Subtract(sig2.S)).Mod(n)); Assert.Equal(expectedBigInt.ToString(), priv.ToString()); }
/// <summary>Choose a random prime value for use with RSA</summary> /// <param name="bitlength">the bit-length of the returned prime</param> /// <param name="e">the RSA public exponent</param> /// <returns>a prime p, with (p-1) relatively prime to e</returns> protected virtual BigInteger ChooseRandomPrime(int bitlength, BigInteger e) { for (;;) { BigInteger p = new BigInteger(bitlength, 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)) continue; return p; } }
/** * 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; } } } }
/* * Select a high order element of the multiplicative group Zp* * * p and q must be s.t. p = 2*q + 1, where p and q are prime (see generateSafePrimes) */ internal static BigInteger SelectGenerator(BigInteger p, BigInteger q, SecureRandom random) { BigInteger pMinusTwo = p.Subtract(BigInteger.Two); BigInteger g; /* * (see: Handbook of Applied Cryptography 4.80) */ // do // { // g = BigIntegers.CreateRandomInRange(BigInteger.Two, pMinusTwo, random); // } // while (g.ModPow(BigInteger.Two, p).Equals(BigInteger.One) // || g.ModPow(q, p).Equals(BigInteger.One)); /* * RFC 2631 2.2.1.2 (and see: Handbook of Applied Cryptography 4.81) */ do { BigInteger h = BigIntegers.CreateRandomInRange(BigInteger.Two, pMinusTwo, random); g = h.ModPow(BigInteger.Two, p); } while (g.Equals(BigInteger.One)); return g; }
public BigInteger Add( BigInteger value) { if (this.sign == 0) return value; if (this.sign != value.sign) { if (value.sign == 0) return this; if (value.sign < 0) return Subtract(value.Negate()); return value.Subtract(Negate()); } return AddToMagnitude(value.magnitude); }
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; }
protected virtual BigInteger CalculateGenerator_FIPS186_3_Verifiable(IDigest d, BigInteger p, BigInteger q, byte[] seed, int index) { // A.2.3 Verifiable Canonical Generation of the Generator g BigInteger e = p.Subtract(BigInteger.One).Divide(q); byte[] ggen = Hex.Decode("6767656E"); // 7. U = domain_parameter_seed || "ggen" || index || count. byte[] U = new byte[seed.Length + ggen.Length + 1 + 2]; Array.Copy(seed, 0, U, 0, seed.Length); Array.Copy(ggen, 0, U, seed.Length, ggen.Length); U[U.Length - 3] = (byte)index; byte[] w = new byte[d.GetDigestSize()]; for (int count = 1; count < (1 << 16); ++count) { Inc(U); Hash(d, U, w); BigInteger W = new BigInteger(1, w); BigInteger g = W.ModPow(e, p); if (g.CompareTo(BigInteger.Two) >= 0) return g; } return null; }
protected virtual BigInteger CalculateGenerator_FIPS186_2(BigInteger p, BigInteger q, SecureRandom r) { BigInteger e = p.Subtract(BigInteger.One).Divide(q); BigInteger pSub2 = p.Subtract(BigInteger.Two); for (;;) { BigInteger h = BigIntegers.CreateRandomInRange(BigInteger.Two, pSub2, r); BigInteger g = h.ModPow(e, p); if (g.BitLength > 1) return g; } }
protected virtual DsaParameters GenerateParameters_FIPS186_2() { byte[] seed = new byte[20]; byte[] part1 = new byte[20]; byte[] part2 = new byte[20]; byte[] u = new byte[20]; int n = (L - 1) / 160; byte[] w = new byte[L / 8]; if (!(digest is Sha1Digest)) throw new InvalidOperationException("can only use SHA-1 for generating FIPS 186-2 parameters"); for (;;) { random.NextBytes(seed); Hash(digest, seed, part1); Array.Copy(seed, 0, part2, 0, seed.Length); Inc(part2); Hash(digest, part2, part2); for (int i = 0; i != u.Length; i++) { u[i] = (byte)(part1[i] ^ part2[i]); } u[0] |= (byte)0x80; u[19] |= (byte)0x01; BigInteger q = new BigInteger(1, u); if (!q.IsProbablePrime(certainty)) continue; byte[] offset = Arrays.Clone(seed); Inc(offset); for (int counter = 0; counter < 4096; ++counter) { for (int k = 0; k < n; k++) { Inc(offset); Hash(digest, offset, part1); Array.Copy(part1, 0, w, w.Length - (k + 1) * part1.Length, part1.Length); } Inc(offset); Hash(digest, offset, part1); 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)); BigInteger p = x.Subtract(c.Subtract(BigInteger.One)); if (p.BitLength != L) continue; if (p.IsProbablePrime(certainty)) { BigInteger g = CalculateGenerator_FIPS186_2(p, q, random); return new DsaParameters(p, q, g, new DsaValidationParameters(seed, counter)); } } } }