internal RFC6979(IDigest h, byte[] q, byte[] x, byte[] hv, int hvOff, int hvLen, bool deterministic) { if (h == null) { h = new SHA256(); } else { h = h.Dup(); h.Reset(); } drbg = new HMAC_DRBG(h); mh = new ModInt(q); qlen = mh.ModBitLength; int qolen = (qlen + 7) >> 3; this.q = new byte[qolen]; Array.Copy(q, q.Length - qolen, this.q, 0, qolen); int hlen = hvLen << 3; if (hlen > qlen) { byte[] htmp = new byte[hvLen]; Array.Copy(hv, hvOff, htmp, 0, hv.Length); BigInt.RShift(htmp, hlen - qlen); hv = htmp; hvOff = 0; } mh.DecodeReduce(hv, hvOff, hvLen); ModInt mx = mh.Dup(); mx.Decode(x); byte[] seed = new byte[(qolen << 1) + (deterministic ? 0 : 32)]; mx.Encode(seed, 0, qolen); mh.Encode(seed, qolen, qolen); if (!deterministic) { RNG.GetBytes(seed, qolen << 1, seed.Length - (qolen << 1)); } drbg.SetSeed(seed); }
/* * Create a new instance. It is initialized to the point at * infinity (represented with a 0). */ internal MutableECPointCurve25519() { ECCurve25519 ccc = (ECCurve25519)EC.Curve25519; x = ccc.mp.Dup(); x1 = ccc.mp.Dup(); x2 = ccc.mp.Dup(); z2 = ccc.mp.Dup(); x3 = ccc.mp.Dup(); z3 = ccc.mp.Dup(); a = ccc.mp.Dup(); aa = ccc.mp.Dup(); b = ccc.mp.Dup(); bb = ccc.mp.Dup(); c = ccc.mp.Dup(); d = ccc.mp.Dup(); e = ccc.mp.Dup(); u = new byte[32]; }
/* * Create a new instance. It is initialized to the point at * infinity. */ internal MutableECPointPrime(ECCurvePrime curve) { this.curve = curve; mx = curve.mp.Dup(); my = curve.mp.Dup(); mz = curve.mp.Dup(); mt1 = curve.mp.Dup(); mt2 = curve.mp.Dup(); mt3 = curve.mp.Dup(); mt4 = curve.mp.Dup(); mt5 = curve.mp.Dup(); ms1 = curve.mp.Dup(); ms2 = curve.mp.Dup(); ms3 = curve.mp.Dup(); ms4 = curve.mp.Dup(); ms5 = curve.mp.Dup(); ms6 = curve.mp.Dup(); 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)"); } }
/* * Inner function for addition. The Jacobian coordinates for * the operand are provided in Montogomery representation. If * p2affine is true, then it is guaranteed that p2z is 1 * (converted to Montogomery). */ uint AddCTInner(ModInt p2x, ModInt p2y, ModInt p2z, bool p2affine) { /* * In this comment, the two operands are called P1 and * P2. P1 is this instance; P2 is the operand. Coordinates * of P1 are (X1,Y1,Z1). Coordinates of P2 are (X2,Y2,Z2). * * Formulas: * U1 = X1 * Z2^2 * U2 = X2 * Z1^2 * S1 = Y1 * Z2^3 * S2 = Y2 * Z1^3 * H = U2 - U1 * R = S2 - S1 * X3 = R^2 - H^3 - 2*U1*H^2 * Y3 = R*(U1*H^2 - X3) - S1*H^3 * Z3 = H*Z1*Z2 * * If both P1 and P2 are 0, then the formulas yield 0, * which is fine. If one of P1 and P2 is 0 (but not both), * then we get 0 as result, which is wrong and must be * fixed at the end. * * If U1 == U2 and S1 == S2 then this means that either * P1 or P2 is 0 (or both), or P1 == P2. In the latter * case, the formulas are wrong and we must report * an error. * * If U1 == U2 and S1 != S2 then P1 + P2 = 0. We get H = 0, * which implies that we obtain the point at infinity, * which is fine. */ uint P1IsZero = mz.IsZeroCT; uint P2IsZero = p2z.IsZeroCT; ToJacobian(); /* * Save this value, in case the operand turns out to * be the point at infinity. */ ms1.Set(mx); ms2.Set(my); ms3.Set(mz); /* * Compute U1 = X1*Z2^2 in t1, and S1 = Y1*Z2^3 in t3. */ if (p2affine) { mt1.Set(mx); mt3.Set(my); } else { mt3.Set(p2z); mt3.MontySquare(); mt1.Set(mx); mt1.MontyMul(mt3); mt3.MontyMul(p2z); mt3.MontyMul(my); } //PrintMR(" u1 = x1*z2^2", mt1); //PrintMR(" s1 = y1*z2^3", mt3); /* * Compute U2 = X2*Z1^2 in t2, and S2 = Y2*Z1^3 in t4. */ mt4.Set(mz); mt4.MontySquare(); mt2.Set(p2x); mt2.MontyMul(mt4); mt4.MontyMul(mz); mt4.MontyMul(p2y); //PrintMR(" u2 = x2*z1^2", mt2); //PrintMR(" s2 = y2*z1^3", mt4); /* * Compute H = U2 - U1 in t2, and R = S2 - S1 in t4. */ mt2.Sub(mt1); mt4.Sub(mt3); //PrintMR(" h = u2-u1", mt2); //PrintMR(" r = s2-s1", mt4); /* * If both H and R are 0, then we may have a problem * (either P1 == P2, or P1 == 0, or P2 == 0). */ uint formProb = mt2.IsZeroCT & mt4.IsZeroCT; /* * Compute U1*H^2 in t1 and H^3 in t5. */ mt5.Set(mt2); mt5.MontySquare(); mt1.MontyMul(mt5); mt5.MontyMul(mt2); //PrintMR(" u1*h^2", mt1); //PrintMR(" h^3", mt5); /* * Compute X3 = R^2 - H^3 - 2*U1*H^2. */ mx.Set(mt4); mx.MontySquare(); mx.Sub(mt5); mx.Sub(mt1); mx.Sub(mt1); //PrintMR(" x3 = r^2-h^3-2*u1*h^2", mx); /* * Compute Y3 = R*(U1*H^2 - X3) - S1*H^3. */ mt1.Sub(mx); mt1.MontyMul(mt4); mt5.MontyMul(mt3); mt1.Sub(mt5); my.Set(mt1); //PrintMR(" y3 = r*(u1*h^2-x3)-s1*h^3", my); /* * Compute Z3 = H*Z1*Z2. */ mz.MontyMul(mt2); if (!p2affine) { mz.MontyMul(p2z); } //PrintMR(" z3 = h*z1*z2", mz); /* * Fixup: handle the cases where P1 = 0 or P2 = 0. */ mx.CondCopy(ms1, P2IsZero); my.CondCopy(ms2, P2IsZero); mz.CondCopy(ms3, P2IsZero); mx.CondCopy(p2x, P1IsZero); my.CondCopy(p2y, P1IsZero); mz.CondCopy(p2z, P1IsZero); /* * Report failure when P1 == P2, except when one of * the points was zero (or both) because that case * was properly handled. */ return((~formProb) | P1IsZero | P2IsZero); }
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); }
internal void Set(ModInt X, ModInt Y, bool check) { throw new CryptoException("Not implemented for Curve25519"); }
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); }
/* * Compare for equality this value with another. Comparison still * works if the two values use distinct moduli. */ public bool Eq(ModInt b) { return(EqCT(b) != 0); }
/* * 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; }
/* * Test an integer for primality. This function runs up to 50 * Miller-Rabin rounds, which is a lot of overkill but ensures * that non-primes will be reliably detected (with overwhelming * probability) even with maliciously crafted inputs. "Normal" * non-primes will be detected most of the time at the first * iteration. * * This function is not constant-time. */ public static bool IsPrime(byte[] x) { x = NormalizeBE(x); /* * Handle easy cases: * 0 is not prime * small primes (one byte) are known in a constant bit-field * even numbers (larger than one byte) are non-primes */ if (x.Length == 0) { return(false); } if (x.Length == 1) { return(IsSmallPrime(x[0])); } if ((x[x.Length - 1] & 0x01) == 0) { return(false); } /* * Perform some trial divisions by small primes. */ for (int sp = 3; sp < 256; sp += 2) { if (!IsSmallPrime(sp)) { continue; } int z = 0; foreach (byte b in x) { z = ((z << 8) + b) % sp; } if (z == 0) { return(false); } } /* * Run some Miller-Rabin rounds. We use as basis random * integers that are one byte smaller than the modulus. */ ModInt xm1 = new ModInt(x); ModInt y = xm1.Dup(); y.Set(1); xm1.Sub(y); byte[] e = xm1.Encode(); ModInt a = new ModInt(x); byte[] buf = new byte[x.Length - 1]; for (int i = 0; i < 50; i++) { RNG.GetBytes(buf); a.Decode(buf); a.Pow(e); if (!a.IsOne) { return(false); } } return(true); }
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); } }