public ECDomainParameters( ECCurve curve, ECPoint g, BigInteger n) : this(curve, g, n, BigInteger.One) { }
private static ECPoint ImplShamirsTrick(ECPoint P, BigInteger k, ECPoint Q, BigInteger l) { int m = System.Math.Max(k.BitLength, l.BitLength); ECPoint Z = P.Add(Q); ECPoint R = P.Curve.Infinity; for (int i = m - 1; i >= 0; --i) { R = R.Twice(); if (k.TestBit(i)) { if (l.TestBit(i)) { R = R.Add(Z); } else { R = R.Add(P); } } else { if (l.TestBit(i)) { R = R.Add(Q); } } } return R; }
/** * Computes the Window NAF (non-adjacent Form) of an integer. * @param width The width <code>w</code> of the Window NAF. The width is * defined as the minimal number <code>w</code>, such that for any * <code>w</code> consecutive digits in the resulting representation, at * most one is non-zero. * @param k The integer of which the Window NAF is computed. * @return The Window NAF of the given width, such that the following holds: * <code>k = −<sub>i=0</sub><sup>l-1</sup> k<sub>i</sub>2<sup>i</sup> * </code>, where the <code>k<sub>i</sub></code> denote the elements of the * returned <code>sbyte[]</code>. */ public sbyte[] WindowNaf(sbyte width, BigInteger k) { // The window NAF is at most 1 element longer than the binary // representation of the integer k. sbyte can be used instead of short or // int unless the window width is larger than 8. For larger width use // short or int. However, a width of more than 8 is not efficient for // m = log2(q) smaller than 2305 Bits. Note: Values for m larger than // 1000 Bits are currently not used in practice. sbyte[] wnaf = new sbyte[k.BitLength + 1]; // 2^width as short and BigInteger short pow2wB = (short)(1 << width); BigInteger pow2wBI = BigInteger.ValueOf(pow2wB); int i = 0; // The actual length of the WNAF int length = 0; // while k >= 1 while (k.SignValue > 0) { // if k is odd if (k.TestBit(0)) { // k Mod 2^width BigInteger remainder = k.Mod(pow2wBI); // if remainder > 2^(width - 1) - 1 if (remainder.TestBit(width - 1)) { wnaf[i] = (sbyte)(remainder.IntValue - pow2wB); } else { wnaf[i] = (sbyte)remainder.IntValue; } // wnaf[i] is now in [-2^(width-1), 2^(width-1)-1] k = k.Subtract(BigInteger.ValueOf(wnaf[i])); length = i; } else { wnaf[i] = 0; } // k = k/2 k = k.ShiftRight(1); i++; } length++; // Reduce the WNAF array to its actual length sbyte[] wnafShort = new sbyte[length]; Array.Copy(wnaf, 0, wnafShort, 0, length); return wnafShort; }
public ECDomainParameters( ECCurve curve, ECPoint g, BigInteger n, BigInteger h) : this(curve, g, n, h, null) { }
public FpFieldElement( BigInteger q, BigInteger x) { if (x.CompareTo(q) >= 0) throw new ArgumentException("x value too large in field element"); this.q = q; this.x = x; }
/* * "Shamir's Trick", originally due to E. G. Straus * (Addition chains of vectors. American Mathematical Monthly, * 71(7):806-808, Aug./Sept. 1964) * * Input: The points P, Q, scalar k = (km?, ... , k1, k0) * and scalar l = (lm?, ... , l1, l0). * Output: R = k * P + l * Q. * 1: Z <- P + Q * 2: R <- O * 3: for i from m-1 down to 0 do * 4: R <- R + R {point doubling} * 5: if (ki = 1) and (li = 0) then R <- R + P end if * 6: if (ki = 0) and (li = 1) then R <- R + Q end if * 7: if (ki = 1) and (li = 1) then R <- R + Z end if * 8: end for * 9: return R */ public static ECPoint ShamirsTrick( ECPoint P, BigInteger k, ECPoint Q, BigInteger l) { if (!P.Curve.Equals(Q.Curve)) throw new ArgumentException("P and Q must be on same curve"); return ImplShamirsTrick(P, k, Q, l); }
/// <summary> /// BigInteger inverse with respect to addition. /// </summary> /// <param name="n">The BigInteger whose opposite is to be computed</param> /// <returns>The BigInteger inverse with respect to addition</returns> public static BigInteger Opposite(BigInteger n) { BigInteger result = n; if (result != Zero) { if (result.sign == -1) result.sign = 1; else result.sign = 1; } result.SetEven(); return result; }
public static ECPoint SumOfTwoMultiplies(ECPoint P, BigInteger a, ECPoint Q, BigInteger b) { ECCurve c = P.Curve; if (!c.Equals(Q.Curve)) throw new ArgumentException("P and Q must be on same curve"); /* // Point multiplication for Koblitz curves (using WTNAF) beats Shamir's trick if (c is F2mCurve) { F2mCurve f2mCurve = (F2mCurve) c; if (f2mCurve.IsKoblitz) { return P.Multiply(a).Add(Q.Multiply(b)); } } */ return ImplShamirsTrick(P, a, Q, b); }
public static byte[] IntegerToBytes( BigInteger s, int qLength) { byte[] bytes = s.ToByteArrayUnsigned(); if (qLength < bytes.Length) { byte[] tmp = new byte[qLength]; Array.Copy(bytes, bytes.Length - tmp.Length, tmp, 0, tmp.Length); return tmp; } else if (qLength > bytes.Length) { byte[] tmp = new byte[qLength]; Array.Copy(bytes, 0, tmp, tmp.Length - bytes.Length, bytes.Length); return tmp; } return bytes; }
public ECDomainParameters( ECCurve curve, ECPoint g, BigInteger n, BigInteger h, byte[] seed) { if (curve == null) throw new ArgumentNullException("curve"); if (g == null) throw new ArgumentNullException("g"); if (n == null) throw new ArgumentNullException("n"); if (h == null) throw new ArgumentNullException("h"); this.curve = curve; this.g = g; this.n = n; this.h = h; this.seed = (seed == null ? null : (byte[])seed.Clone()); }
// D.1.4 91 /** * return a sqrt root - the routine verifies that the calculation * returns the right value - if none exists it returns null. */ public override ECFieldElement Sqrt() { if (!q.TestBit(0)) throw new NotImplementedException("even value of q"); // p mod 4 == 3 if (q.TestBit(1)) { // TODO Can this be optimised (inline the Square?) // z = g^(u+1) + p, p = 4u + 3 ECFieldElement z = new FpFieldElement(q, x.ModPow(q.ShiftRight(2).Add(BigInteger.One), q)); return z.Square().Equals(this) ? z : null; } // p mod 4 == 1 BigInteger qMinusOne = q.Subtract(BigInteger.One); BigInteger legendreExponent = qMinusOne.ShiftRight(1); if (!(x.ModPow(legendreExponent, q).Equals(BigInteger.One))) return null; BigInteger u = qMinusOne.ShiftRight(2); BigInteger k = u.ShiftLeft(1).Add(BigInteger.One); BigInteger Q = this.x; BigInteger fourQ = Q.ShiftLeft(2).Mod(q); BigInteger U, V; do { Random rand = new Random(); BigInteger P; do { P = new BigInteger(q.BitLength, rand); } while (P.CompareTo(q) >= 0 || !(P.Multiply(P).Subtract(fourQ).ModPow(legendreExponent, q).Equals(qMinusOne))); BigInteger[] result = fastLucasSequence(q, P, Q, k); U = result[0]; V = result[1]; if (V.Multiply(V).Mod(q).Equals(fourQ)) { // Integer division by 2, mod q if (V.TestBit(0)) { V = V.Add(q); } V = V.ShiftRight(1); Debug.Assert(V.Multiply(V).Mod(q).Equals(x)); return new FpFieldElement(q, V); } } while (U.Equals(BigInteger.One) || U.Equals(qMinusOne)); return null; // BigInteger qMinusOne = q.Subtract(BigInteger.One); // // BigInteger legendreExponent = qMinusOne.ShiftRight(1); // if (!(x.ModPow(legendreExponent, q).Equals(BigInteger.One))) // return null; // // Random rand = new Random(); // BigInteger fourX = x.ShiftLeft(2); // // BigInteger r; // do // { // r = new BigInteger(q.BitLength, rand); // } // while (r.CompareTo(q) >= 0 // || !(r.Multiply(r).Subtract(fourX).ModPow(legendreExponent, q).Equals(qMinusOne))); // // BigInteger n1 = qMinusOne.ShiftRight(2); // BigInteger n2 = n1.Add(BigInteger.One); // // BigInteger wOne = WOne(r, x, q); // BigInteger wSum = W(n1, wOne, q).Add(W(n2, wOne, q)).Mod(q); // BigInteger twoR = r.ShiftLeft(1); // // BigInteger root = twoR.ModPow(q.Subtract(BigInteger.Two), q) // .Multiply(x).Mod(q) // .Multiply(wSum).Mod(q); // // return new FpFieldElement(q, root); }
/** * Multiplies this <code>ECPoint</code> by the given number. * @param k The multiplicator. * @return <code>k * this</code>. */ public override ECPoint Multiply( BigInteger k) { if (k.SignValue < 0) throw new ArgumentException("The multiplicator cannot be negative", "k"); if (this.IsInfinity) return this; if (k.SignValue == 0) return this.curve.Infinity; AssertECMultiplier(); return this.multiplier.Multiply(this, k, preCompInfo); }
public abstract ECPoint Multiply(BigInteger b);
/** * Decode a point on this curve from its ASN.1 encoding. The different * encodings are taken account of, including point compression for * <code>F<sub>p</sub></code> (X9.62 s 4.2.1 pg 17). * @return The decoded point. */ public override ECPoint DecodePoint( byte[] encoded) { ECPoint p = null; int expectedLength = (FieldSize + 7) / 8; switch (encoded[0]) { case 0x00: // infinity { if (encoded.Length != 1) throw new ArgumentException("Incorrect length for infinity encoding", "encoded"); p = Infinity; break; } case 0x02: // compressed case 0x03: // compressed { if (encoded.Length != (expectedLength + 1)) throw new ArgumentException("Incorrect length for compressed encoding", "encoded"); int yTilde = encoded[0] & 1; BigInteger X1 = new BigInteger(1, encoded, 1, encoded.Length - 1); p = DecompressPoint(yTilde, X1); break; } case 0x04: // uncompressed case 0x06: // hybrid case 0x07: // hybrid { if (encoded.Length != (2 * expectedLength + 1)) throw new ArgumentException("Incorrect length for uncompressed/hybrid encoding", "encoded"); BigInteger X1 = new BigInteger(1, encoded, 1, expectedLength); BigInteger Y1 = new BigInteger(1, encoded, 1 + expectedLength, expectedLength); p = CreatePoint(X1, Y1, false); break; } default: throw new FormatException("Invalid point encoding " + encoded[0]); } return p; }
public BigInteger And( BigInteger value) { if (this.sign == 0 || value.sign == 0) { return Zero; } int[] aMag = this.sign > 0 ? this.magnitude : Add(One).magnitude; int[] bMag = value.sign > 0 ? value.magnitude : value.Add(One).magnitude; bool resultNeg = sign < 0 && value.sign < 0; int resultLength = System.Math.Max(aMag.Length, bMag.Length); int[] resultMag = new int[resultLength]; int aStart = resultMag.Length - aMag.Length; int bStart = resultMag.Length - bMag.Length; for (int i = 0; i < resultMag.Length; ++i) { int aWord = i >= aStart ? aMag[i - aStart] : 0; int bWord = i >= bStart ? bMag[i - bStart] : 0; if (this.sign < 0) { aWord = ~aWord; } if (value.sign < 0) { bWord = ~bWord; } resultMag[i] = aWord & bWord; if (resultNeg) { resultMag[i] = ~resultMag[i]; } } BigInteger result = new BigInteger(1, resultMag, true); // TODO Optimise this case if (resultNeg) { result = result.Not(); } return result; }
protected internal override ECPoint DecompressPoint( int yTilde, BigInteger X1) { ECFieldElement x = FromBigInteger(X1); ECFieldElement alpha = x.Multiply(x.Square().Add(a)).Add(b); ECFieldElement beta = alpha.Sqrt(); // // if we can't find a sqrt we haven't got a point on the // curve - run! // if (beta == null) throw new ArithmeticException("Invalid point compression"); BigInteger betaValue = beta.ToBigInteger(); int bit0 = betaValue.TestBit(0) ? 1 : 0; if (bit0 != yTilde) { // Use the other root beta = FromBigInteger(q.Subtract(betaValue)); } return new FpPoint(this, x, beta, true); }
public static BigInteger Pow(BigInteger a, int exponent) { BigInteger result = a.Pow(exponent); result.SetEven(); return result; }
public override ECFieldElement FromBigInteger(BigInteger x) { return new FpFieldElement(this.q, x); }
public BigInteger Subtract( BigInteger n) { if (n.sign == 0) return this; if (this.sign == 0) return n.Negate(); if (this.sign != n.sign) return Add(n.Negate()); int compare = CompareNoLeadingZeroes(0, magnitude, 0, n.magnitude); if (compare == 0) return Zero; BigInteger bigun, lilun; if (compare < 0) { bigun = n; lilun = this; } else { bigun = this; lilun = n; } return new BigInteger(this.sign * compare, doSubBigLil(bigun.magnitude, lilun.magnitude), true); }
public FpCurve(BigInteger q, BigInteger a, BigInteger b) { this.q = q; this.a = FromBigInteger(a); this.b = FromBigInteger(b); this.infinity = new FpPoint(this, null, null); }
private static BigInteger createUValueOf( ulong value) { int msw = (int)(value >> 32); int lsw = (int)value; if (msw != 0) return new BigInteger(1, new int[] { msw, lsw }, false); if (lsw != 0) { BigInteger n = new BigInteger(1, new int[] { lsw }, false); // Check for a power of two if ((lsw & -lsw) == lsw) { n.nBits = 1; } return n; } return Zero; }
/** * Multiplies <code>this</code> by an integer <code>k</code> using the * Window NAF method. * @param k The integer by which <code>this</code> is multiplied. * @return A new <code>ECPoint</code> which equals <code>this</code> * multiplied by <code>k</code>. */ public ECPoint Multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo) { WNafPreCompInfo wnafPreCompInfo; if ((preCompInfo != null) && (preCompInfo is WNafPreCompInfo)) { wnafPreCompInfo = (WNafPreCompInfo)preCompInfo; } else { // Ignore empty PreCompInfo or PreCompInfo of incorrect type wnafPreCompInfo = new WNafPreCompInfo(); } // floor(log2(k)) int m = k.BitLength; // width of the Window NAF sbyte width; // Required length of precomputation array int reqPreCompLen; // Determine optimal width and corresponding length of precomputation // array based on literature values if (m < 13) { width = 2; reqPreCompLen = 1; } else { if (m < 41) { width = 3; reqPreCompLen = 2; } else { if (m < 121) { width = 4; reqPreCompLen = 4; } else { if (m < 337) { width = 5; reqPreCompLen = 8; } else { if (m < 897) { width = 6; reqPreCompLen = 16; } else { if (m < 2305) { width = 7; reqPreCompLen = 32; } else { width = 8; reqPreCompLen = 127; } } } } } } // The length of the precomputation array int preCompLen = 1; ECPoint[] preComp = wnafPreCompInfo.GetPreComp(); ECPoint twiceP = wnafPreCompInfo.GetTwiceP(); // Check if the precomputed ECPoints already exist if (preComp == null) { // Precomputation must be performed from scratch, create an empty // precomputation array of desired length preComp = new ECPoint[]{ p }; } else { // Take the already precomputed ECPoints to start with preCompLen = preComp.Length; } if (twiceP == null) { // Compute twice(p) twiceP = p.Twice(); } if (preCompLen < reqPreCompLen) { // Precomputation array must be made bigger, copy existing preComp // array into the larger new preComp array ECPoint[] oldPreComp = preComp; preComp = new ECPoint[reqPreCompLen]; Array.Copy(oldPreComp, 0, preComp, 0, preCompLen); for (int i = preCompLen; i < reqPreCompLen; i++) { // Compute the new ECPoints for the precomputation array. // The values 1, 3, 5, ..., 2^(width-1)-1 times p are // computed preComp[i] = twiceP.Add(preComp[i - 1]); } } // Compute the Window NAF of the desired width sbyte[] wnaf = WindowNaf(width, k); int l = wnaf.Length; // Apply the Window NAF to p using the precomputed ECPoint values. ECPoint q = p.Curve.Infinity; for (int i = l - 1; i >= 0; i--) { q = q.Twice(); if (wnaf[i] != 0) { if (wnaf[i] > 0) { q = q.Add(preComp[(wnaf[i] - 1)/2]); } else { // wnaf[i] < 0 q = q.Subtract(preComp[(-wnaf[i] - 1)/2]); } } } // Set PreCompInfo in ECPoint, such that it is available for next // multiplication. wnafPreCompInfo.SetPreComp(preComp); wnafPreCompInfo.SetTwiceP(twiceP); p.SetPreCompInfo(wnafPreCompInfo); return q; }
// private static BigInteger W(BigInteger n, BigInteger wOne, BigInteger p) // { // if (n.Equals(BigInteger.One)) // return wOne; // // bool isEven = !n.TestBit(0); // n = n.ShiftRight(1); // if (isEven) // { // BigInteger w = W(n, wOne, p); // return w.Multiply(w).Subtract(BigInteger.Two).Mod(p); // } // BigInteger w1 = W(n.Add(BigInteger.One), wOne, p); // BigInteger w2 = W(n, wOne, p); // return w1.Multiply(w2).Subtract(wOne).Mod(p); // } // // private BigInteger WOne(BigInteger r, BigInteger x, BigInteger p) // { // return r.Multiply(r).Multiply(x.ModPow(q.Subtract(BigInteger.Two), q)).Subtract(BigInteger.Two).Mod(p); // } private static BigInteger[] fastLucasSequence( BigInteger p, BigInteger P, BigInteger Q, BigInteger k) { // TODO Research and apply "common-multiplicand multiplication here" int n = k.BitLength; int s = k.GetLowestSetBit(); Debug.Assert(k.TestBit(s)); BigInteger Uh = BigInteger.One; BigInteger Vl = BigInteger.Two; BigInteger Vh = P; BigInteger Ql = BigInteger.One; BigInteger Qh = BigInteger.One; for (int j = n - 1; j >= s + 1; --j) { Ql = Ql.Multiply(Qh).Mod(p); if (k.TestBit(j)) { Qh = Ql.Multiply(Q).Mod(p); Uh = Uh.Multiply(Vh).Mod(p); Vl = Vh.Multiply(Vl).Subtract(P.Multiply(Ql)).Mod(p); Vh = Vh.Multiply(Vh).Subtract(Qh.ShiftLeft(1)).Mod(p); } else { Qh = Ql; Uh = Uh.Multiply(Vl).Subtract(Ql).Mod(p); Vh = Vh.Multiply(Vl).Subtract(P.Multiply(Ql)).Mod(p); Vl = Vl.Multiply(Vl).Subtract(Ql.ShiftLeft(1)).Mod(p); } } Ql = Ql.Multiply(Qh).Mod(p); Qh = Ql.Multiply(Q).Mod(p); Uh = Uh.Multiply(Vl).Subtract(Ql).Mod(p); Vl = Vh.Multiply(Vl).Subtract(P.Multiply(Ql)).Mod(p); Ql = Ql.Multiply(Qh).Mod(p); for (int j = 1; j <= s; ++j) { Uh = Uh.Multiply(Vl).Mod(p); Vl = Vl.Multiply(Vl).Subtract(Ql.ShiftLeft(1)).Mod(p); Ql = Ql.Multiply(Ql).Mod(p); } return new BigInteger[]{ Uh, Vl }; }
public abstract ECFieldElement FromBigInteger(BigInteger x);
public static BigInteger DivRem(BigInteger i1, BigInteger i2, out BigInteger i3) { BigInteger[] result = i1.DivideAndRemainder(i2); i3 = result[1]; return result[0]; }
public abstract ECPoint CreatePoint(BigInteger x, BigInteger y, bool withCompression);
public BigInteger ShiftLeft( int n) { if (sign == 0 || magnitude.Length == 0) return Zero; if (n == 0) return this; if (n < 0) return ShiftRight(-n); BigInteger result = new BigInteger(sign, ShiftLeft(magnitude, n), true); if (this.nBits != -1) { result.nBits = sign > 0 ? this.nBits : this.nBits + n; } if (this.nBitLength != -1) { result.nBitLength = this.nBitLength + n; } return result; }
protected internal abstract ECPoint DecompressPoint(int yTilde, BigInteger X1);
public override ECPoint CreatePoint( BigInteger X1, BigInteger Y1, bool withCompression) { // TODO Validation of X1, Y1? return new FpPoint( this, FromBigInteger(X1), FromBigInteger(Y1), withCompression); }
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); }