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); } }
/* * 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); }
/* * Convert to affine coordinates (if not already done). */ void ToAffine() { if (affine != 0) { return; } /* * Divisions are expensive, so we want to make only one, * not two. This involves some games with Montgomery * representation. * * A number a in Montgomery representation means that * the value we have is equal to aR. Montgomery * multiplication of a by b yields ab/R (so, if we * apply it to aR and bR, we get abR). */ /* Save Z*R in mt1. */ mt1.Set(mz); /* Compute Z^3 in mz. */ mz.MontySquare(); mz.MontyMul(mt1); mz.FromMonty(); /* Compute t2 = 1/Z^3. */ mt2.Set(mz); mt2.Invert(); uint cc = ~mt2.IsZeroCT; /* Compute y. */ my.MontyMul(mt2); /* Compute t2 = 1/Z^2. */ mt2.MontyMul(mt1); /* Compute x. */ mx.MontyMul(mt2); /* * If the point is infinity (division by Z^2 failed), * then set all coordinates to 0. Otherwise, set mz * to exactly 1. */ mx.CondCopy(curve.mp, ~cc); my.CondCopy(curve.mp, ~cc); mz.Set((int)cc & 1); affine = 0xFFFFFFFF; }
/* * CheckValid() will verify that the prime factors are indeed * prime, and that all other values are correct. */ public void CheckValid() { /* * Factors ought to be prime. */ if (!BigInt.IsPrime(p) || !BigInt.IsPrime(q)) { throw new CryptoException("Invalid RSA private key" + " (non-prime factor)"); } /* * FIXME: Verify that: * dp = d mod p-1 * e*dp = 1 mod p-1 * dq = d mod q-1 * e*dq = 1 mod q-1 * (This is not easy with existing code because p-1 and q-1 * are even, but ModInt tolerates only odd moduli.) * * CheckExp(p, d, dp, e); * CheckExp(q, d, dq, e); */ /* * Verify that: * q*iq = 1 mod p */ ModInt x = new ModInt(p); ModInt y = x.Dup(); x.DecodeReduce(q); x.ToMonty(); y.Decode(iq); x.MontyMul(y); if (!x.IsOne) { throw new CryptoException("Invalid RSA private key" + " (wrong CRT coefficient)"); } }
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); }
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); }
public static bool VerifyRaw(ECPublicKey pk, byte[] hash, int hashOff, int hashLen, byte[] sig, int sigOff, int sigLen) { try { /* * Get the curve. */ ECCurve curve = pk.Curve; /* * Get r and s from signature. This also verifies * that they do not exceed the subgroup order. */ if (sigLen == 0 || (sigLen & 1) != 0) { return(false); } int tlen = sigLen >> 1; ModInt oneQ = new ModInt(curve.SubgroupOrder); oneQ.Set(1); ModInt r = oneQ.Dup(); ModInt s = oneQ.Dup(); r.Decode(sig, sigOff, tlen); s.Decode(sig, sigOff + tlen, tlen); /* * If either r or s was too large, it got set to * zero. We also don't want real zeros. */ if (r.IsZero || s.IsZero) { return(false); } /* * Convert the hash value to an integer modulo q. * As per FIPS 186-4, if the hash value is larger * than q, then we keep the qlen leftmost bits of * the hash value. */ int qBitLength = oneQ.ModBitLength; int hBitLength = hashLen << 3; byte[] hv; if (hBitLength <= qBitLength) { hv = new byte[hashLen]; Array.Copy(hash, hashOff, hv, 0, hashLen); } else { int qlen = (qBitLength + 7) >> 3; hv = new byte[qlen]; Array.Copy(hash, hashOff, hv, 0, qlen); int rs = (8 - (qBitLength & 7)) & 7; BigInt.RShift(hv, rs); } ModInt z = oneQ.Dup(); z.DecodeReduce(hv); /* * Apply the verification algorithm: * w = 1/s mod q * u = z*w mod q * v = r*w mod q * T = u*G + v*Pub * test whether T.x mod q == r. */ /* * w = 1/s mod q */ ModInt w = s.Dup(); w.Invert(); /* * u = z*w mod q */ w.ToMonty(); ModInt u = w.Dup(); u.MontyMul(z); /* * v = r*w mod q */ ModInt v = w.Dup(); v.MontyMul(r); /* * Compute u*G */ MutableECPoint T = curve.MakeGenerator(); uint good = T.MulSpecCT(u.Encode()); /* * Compute v*iPub */ MutableECPoint M = pk.iPub.Dup(); good &= M.MulSpecCT(v.Encode()); /* * Compute T = u*G+v*iPub */ uint nd = T.AddCT(M); M.DoubleCT(); T.Set(M, ~nd); good &= ~T.IsInfinityCT; /* * Get T.x, reduced modulo q. * Signature is valid if and only if we get * the same value as r (and we did not encounter * an error previously). */ s.DecodeReduce(T.X); return((good & r.EqCT(s)) != 0); } catch (CryptoException) { /* * Exceptions may occur if the key or signature * have invalid values (non invertible, out of * range...). Any such occurrence means that the * signature is not valid. */ return(false); } }