/* * Given a value X in sx, this method computes X^3+aX+b into sd. * 'sx' is unmodified. 'st' is modified (it receives a*X). * The sx, sd and st instances MUST be distinct. */ internal void RebuildY2(ModInt sx, ModInt sd, ModInt st) { sd.Set(sx); sd.ToMonty(); st.Set(sd); sd.MontySquare(); sd.MontyMul(sx); st.MontyMul(ma); sd.Add(st); sd.Add(mb); }
public static byte[] SignRaw(ECPrivateKey sk, IDigest rfc6979Hash, byte[] hash, int hashOff, int hashLen) { ECCurve curve = sk.Curve; byte[] q = curve.SubgroupOrder; RFC6979 rf = new RFC6979(rfc6979Hash, q, sk.X, hash, hashOff, hashLen, rfc6979Hash != null); ModInt mh = rf.GetHashMod(); ModInt mx = mh.Dup(); mx.Decode(sk.X); /* * Compute DSA signature. We use a loop to enumerate * candidates for k until a proper one is found (it * is VERY improbable that we may have to loop). */ ModInt mr = mh.Dup(); ModInt ms = mh.Dup(); ModInt mk = mh.Dup(); byte[] k = new byte[q.Length]; for (;;) { rf.NextK(k); MutableECPoint G = curve.MakeGenerator(); if (G.MulSpecCT(k) == 0) { /* * We may get an error here only if the * curve is invalid (generator does not * produce the expected subgroup). */ throw new CryptoException( "Invalid EC private key / curve"); } mr.DecodeReduce(G.X); if (mr.IsZero) { continue; } ms.Set(mx); ms.ToMonty(); ms.MontyMul(mr); ms.Add(mh); mk.Decode(k); mk.Invert(); ms.ToMonty(); ms.MontyMul(mk); byte[] sig = new byte[q.Length << 1]; mr.Encode(sig, 0, q.Length); ms.Encode(sig, q.Length, q.Length); return(sig); } }
internal override void DoubleCT() { ToJacobian(); /* * Formulas are: * S = 4*X*Y^2 * M = 3*X^2 + a*Z^4 * X' = M^2 - 2*S * Y' = M*(S - X') - 8*Y^4 * Z' = 2*Y*Z * * These formulas also happen to work properly (with our * chosen representation) when the source point has * order 2 (Y = 0 implies Z' = 0) and when the source * point is already the point at infinity (Z = 0 implies * Z' = 0). * * When a = -3, the value of M can be computed with the * more efficient formula: * M = 3*(X+Z^2)*(X-Z^2) */ /* * Compute M in t1. */ if (curve.aIsM3) { /* * Set t1 = Z^2. */ mt1.Set(mz); mt1.MontySquare(); /* * Set t2 = X-Z^2 and then t1 = X+Z^2. */ mt2.Set(mx); mt2.Sub(mt1); mt1.Add(mx); /* * Set t1 = 3*(X+Z^2)*(X-Z^2). */ mt1.MontyMul(mt2); mt2.Set(mt1); mt1.Add(mt2); mt1.Add(mt2); } else { /* * Set t1 = 3*X^2. */ mt1.Set(mx); mt1.MontySquare(); mt2.Set(mt1); mt1.Add(mt2); mt1.Add(mt2); /* * Set t2 = a*Z^4. */ mt2.Set(mz); mt2.MontySquare(); mt2.MontySquare(); mt2.MontyMul(curve.ma); /* * Set t1 = 3*X^2 + a*Z^4. */ mt1.Add(mt2); } /* * Compute S = 4*X*Y^2 in t2. We also save 2*Y^2 in mt3. */ mt2.Set(my); mt2.MontySquare(); mt2.Add(mt2); mt3.Set(mt2); mt2.Add(mt2); mt2.MontyMul(mx); /* * Compute X' = M^2 - 2*S. */ mx.Set(mt1); mx.MontySquare(); mx.Sub(mt2); mx.Sub(mt2); /* * Compute Z' = 2*Y*Z. */ mz.MontyMul(my); mz.Add(mz); /* * Compute Y' = M*(S - X') - 8*Y^4. We already have * 4*Y^2 in t3. */ mt2.Sub(mx); mt2.MontyMul(mt1); mt3.MontySquare(); mt3.Add(mt3); my.Set(mt2); my.Sub(mt3); }
internal override uint MulSpecCT(byte[] n) { /* * Copy scalar into a temporary array (u[]) for * normalisation to 32 bytes and clamping. */ if (n.Length > 32) { return(0); } Array.Copy(n, 0, u, 32 - n.Length, n.Length); for (int i = 0; i < 32 - n.Length; i++) { u[i] = 0; } u[31] &= 0xF8; u[0] &= 0x7F; u[0] |= 0x40; x1.Set(x); x1.ToMonty(); x2.SetMonty(0xFFFFFFFF); z2.Set(0); x3.Set(x1); z3.Set(x2); uint swap = 0; ModInt ma24 = ((ECCurve25519)EC.Curve25519).ma24; for (int t = 254; t >= 0; t--) { uint kt = (uint)-((u[31 - (t >> 3)] >> (t & 7)) & 1); swap ^= kt; x2.CondSwap(x3, swap); z2.CondSwap(z3, swap); swap = kt; a.Set(x2); a.Add(z2); aa.Set(a); aa.MontySquare(); b.Set(x2); b.Sub(z2); bb.Set(b); bb.MontySquare(); e.Set(aa); e.Sub(bb); c.Set(x3); c.Add(z3); d.Set(x3); d.Sub(z3); d.MontyMul(a); c.MontyMul(b); x3.Set(d); x3.Add(c); x3.MontySquare(); z3.Set(d); z3.Sub(c); z3.MontySquare(); z3.MontyMul(x1); x2.Set(aa); x2.MontyMul(bb); z2.Set(e); z2.MontyMul(ma24); z2.Add(aa); z2.MontyMul(e); } x2.CondSwap(x3, swap); z2.CondSwap(z3, swap); /* * We need to restore z2 to normal representation before * inversion. Then the final Montgomery multiplication * will cancel out with x2, which is still in Montgomery * representation. */ z2.FromMonty(); z2.Invert(); x2.MontyMul(z2); /* * x2 now contains the result. */ x.Set(x2); return(0xFFFFFFFF); }
public static void DoPrivate(RSAPrivateKey sk, byte[] x, int off, int len) { /* * Check that the source array has the proper length * (identical to the length of the modulus). */ if (len != sk.N.Length) { throw new CryptoException( "Invalid source length for RSA private"); } /* * Reduce the source value to the proper range. */ ModInt mx = new ModInt(sk.N); mx.DecodeReduce(x, off, len); /* * Compute m1 = x^dp mod p. */ ModInt m1 = new ModInt(sk.P); m1.Set(mx); m1.Pow(sk.DP); /* * Compute m2 = x^dq mod q. */ ModInt m2 = new ModInt(sk.Q); m2.Set(mx); m2.Pow(sk.DQ); /* * Compute h = (m1 - m2) / q mod p. * (Result goes in m1.) */ ModInt m3 = m1.Dup(); m3.Set(m2); m1.Sub(m3); m3.Decode(sk.IQ); m1.ToMonty(); m1.MontyMul(m3); /* * Compute m_2 + q*h. This works on plain integers, but * we have efficient and constant-time code for modular * integers, so we will do it modulo n. */ m3 = mx; m3.Set(m1); m1 = m3.Dup(); m1.Decode(sk.Q); m1.ToMonty(); m3.MontyMul(m1); m1.Set(m2); m3.Add(m1); /* * Write result back in x[]. */ m3.Encode(x, off, len); }
/* * Checks enforced by the constructor: * -- modulus is odd and at least 80-bit long * -- subgroup order is odd and at least 30-bit long * -- parameters a[] and b[] are lower than modulus * -- coordinates gx and gy are lower than modulus * -- coordinates gx and gy match curve equation */ internal ECCurvePrime(string name, byte[] mod, byte[] a, byte[] b, byte[] gx, byte[] gy, byte[] subgroupOrder, byte[] cofactor) : base(subgroupOrder, cofactor) { this.mod = mod = BigInt.NormalizeBE(mod); int modLen = BigInt.BitLength(mod); if (modLen < 80) { throw new CryptoException( "Invalid curve: modulus is too small"); } if ((mod[mod.Length - 1] & 0x01) == 0) { throw new CryptoException( "Invalid curve: modulus is even"); } int sgLen = BigInt.BitLength(subgroupOrder); if (sgLen < 30) { throw new CryptoException( "Invalid curve: subgroup is too small"); } if ((subgroupOrder[subgroupOrder.Length - 1] & 0x01) == 0) { throw new CryptoException( "Invalid curve: subgroup order is even"); } mp = new ModInt(mod); flen = (modLen + 7) >> 3; pMod4 = mod[mod.Length - 1] & 3; this.a = a = BigInt.NormalizeBE(a); this.b = b = BigInt.NormalizeBE(b); if (BigInt.CompareCT(a, mod) >= 0 || BigInt.CompareCT(b, mod) >= 0) { throw new CryptoException( "Invalid curve: out-of-range parameter"); } ma = mp.Dup(); ma.Decode(a); ma.Add(3); aIsM3 = ma.IsZero; ma.Sub(3); mb = mp.Dup(); mb.Decode(b); this.gx = gx = BigInt.NormalizeBE(gx); this.gy = gy = BigInt.NormalizeBE(gy); if (BigInt.CompareCT(gx, mod) >= 0 || BigInt.CompareCT(gy, mod) >= 0) { throw new CryptoException( "Invalid curve: out-of-range coordinates"); } MutableECPointPrime G = new MutableECPointPrime(this); G.Set(gx, gy, true); hashCode = (int)(BigInt.HashInt(mod) ^ BigInt.HashInt(a) ^ BigInt.HashInt(b) ^ BigInt.HashInt(gx) ^ BigInt.HashInt(gy)); if (name == null) { name = string.Format("generic prime {0}/{1}", modLen, sgLen); } this.name = name; }