/* * Compute a modular exponentiation (x^e mod n). Conditions: * -- x[], e[] and n[] use big-endian encoding. * -- x[] must be numerically smaller than n[]. * -- n[] must be odd. * Result is returned as a newly allocated array of bytes of * the same length as n[]. */ public static byte[] ModPow(byte[] x, byte[] e, byte[] n) { ModInt mx = new ModInt(n); mx.Decode(x); mx.Pow(e); return(mx.Encode()); }
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); } }
/* * Create a new instance with the provided elements. The * constructor verifies that the provided private integer * is non-zero and is less than the subgroup order. */ public ECPrivateKey(ECCurve curve, byte[] X) { this.curve = curve; ModInt ms = new ModInt(curve.SubgroupOrder); uint good = ms.Decode(X); good &= ~ms.IsZeroCT; if (good == 0) { throw new CryptoException("Invalid private key"); } priv = ms.Encode(); dpk = null; }
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); }
/* * 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 uint DecodeCT(byte[] enc) { /* * Format (specified in IEEE P1363, annex E): * * 0x00 point at infinity * 0x02+b <X> compressed, b = lsb of Y * 0x04 <X> <Y> uncompressed * 0x06+b <X> <Y> uncompressed, b = lsb of Y * * Coordinates X and Y are in unsigned big-endian * notation with exactly the length of the modulus. * * We want constant-time decoding, up to the encoded * length. This means that the four following situations * can be differentiated: * -- Point is zero (length = 1) * -- Point is compressed (length = 1 + flen) * -- Point is uncompressed or hybrid (length = 1 + 2*flen) * -- Length is neither 1, 1+flen or 1+2*flen. */ int flen = curve.flen; uint good = 0xFFFFFFFF; if (enc.Length == 1) { /* * 1-byte encoding is point at infinity; the * byte shall have value 0. */ int z = enc[0]; good &= ~(uint)((z | -z) >> 31); SetZero(); } else if (enc.Length == 1 + flen) { /* * Compressed encoding. Leading byte is 0x02 or * 0x03. */ int z = (enc[0] & 0xFE) - 0x02; good &= ~(uint)((z | -z) >> 31); uint lsbValue = (uint)(enc[0] & 1); good &= mx.Decode(enc, 1, flen); RebuildY2(); if (curve.pMod4 == 3) { good &= my.SqrtBlum(); } else { /* * Square roots modulo a non-Blum prime * are a bit more complex. We do not * support them yet (TODO). */ good = 0x00000000; } /* * Adjust Y depending on LSB. */ mt1.Set(my); mt1.Negate(); uint dn = (uint)-(int)(my.GetLSB() ^ lsbValue); my.CondCopy(mt1, dn); /* * A corner case: LSB adjustment works only if * Y != 0. If Y is 0 and requested LSB is 1, * then the decoding fails. Note that this case * cannot happen with usual prime curves, because * they have a prime order, implying that there is * no valid point such that Y = 0 (that would be * a point of order 2). */ good &= ~(uint)-(int)(my.GetLSB() ^ lsbValue); mz.Set(1); } else if (enc.Length == 1 + (flen << 1)) { /* * Uncompressed or hybrid. Leading byte is either * 0x04, 0x06 or 0x07. We verify that the X and * Y coordinates fulfill the curve equation. */ int fb = enc[0]; int z = (fb & 0xFC) - 0x04; good &= ~(uint)((z | -z) >> 31); z = fb - 0x05; good &= (uint)((z | -z) >> 31); good &= mx.Decode(enc, 1, flen); RebuildY2(); mt1.Set(my); mt1.FromMonty(); good &= my.Decode(enc, 1 + flen, flen); mt2.Set(my); mt2.MontySquare(); good &= mt1.EqCT(mt2); /* * We must check the LSB for hybrid encoding. * The check fails if the encoding is marked as * hybrid AND the LSB does not match. */ int lm = (fb >> 1) & ((int)my.GetLSB() ^ fb) & 1; good &= ~(uint)-lm; mz.Set(1); } else { good = 0x00000000; } /* * If decoding failed, then we force the value to 0. * Otherwise, we got a value. Either way, this uses * affine coordinates. */ mx.CondCopy(curve.mp, ~good); my.CondCopy(curve.mp, ~good); mz.CondCopy(curve.mp, ~good); affine = 0xFFFFFFFF; return(good); }
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; }
/* * 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); } }