internal override MutableECPoint Dup() { MutableECPointPrime Q = new MutableECPointPrime(curve); Q.Set(this); return(Q); }
internal override MutableECPoint MakeGenerator() { /* * We do not have to check the generator, since * it was already done in the constructor. */ MutableECPointPrime G = new MutableECPointPrime(this); G.Set(gx, gy, false); return(G); }
/* * Extra checks: * -- modulus is prime * -- subgroup order is prime * -- generator indeed generates subgroup */ public override void CheckValid() { /* * Check that the modulus is prime. */ if (!BigInt.IsPrime(mod)) { throw new CryptoException( "Invalid curve: modulus is not prime"); } /* * Check that the subgroup order is prime. */ if (!BigInt.IsPrime(SubgroupOrder)) { throw new CryptoException( "Invalid curve: subgroup order is not prime"); } /* * Check that the G point is indeed a generator of the * subgroup. Note that since it has explicit coordinates, * it cannot be the point at infinity; it suffices to * verify that, when multiplied by the subgroup order, * it yields infinity. */ MutableECPointPrime G = new MutableECPointPrime(this); G.Set(gx, gy, false); if (G.MulSpecCT(SubgroupOrder) == 0 || !G.IsInfinity) { throw new CryptoException( "Invalid curve: generator does not match" + " subgroup order"); } /* * TODO: check cofactor. * * If the cofactor is small, then we can simply compute * the complete curve order by multiplying the cofactor * with the subgroup order, and see whether it is in the * proper range with regards to the field cardinal (by * using Hasse's theorem). However, if the cofactor is * larger than the subgroup order, then detecting a * wrong cofactor value is a bit more complex. We could * generate a few random points and multiply them by * the computed order, but this may be expensive. */ }
internal override uint MulSpecCT(byte[] n) { uint good = 0xFFFFFFFF; /* * Create and populate window. * * If this instance is 0, then we only add 0 to 0 and * double 0, for which DoubleCT() and AddCT() work * properly. * * If this instance (P) is non-zero, then x*P for all * x in the 1..16 range shall be non-zero and distinct, * since the subgroup order is prime and at least 17. * Thus, we never add two equal points together in the * window construction. * * We MUST ensure that all points are in the same * coordinate convention (affine or Jacobian) to ensure * constant-time execution. TODO: measure to see which * is best: all affine or all Jacobian. All affine implies * 14 or 15 extra divisions, but saves a few hundreds of * multiplications. */ MutableECPointPrime[] w = new MutableECPointPrime[16]; w[0] = new MutableECPointPrime(curve); w[0].ToJacobian(); w[1] = new MutableECPointPrime(curve); w[1].Set(this); w[1].ToJacobian(); for (int i = 2; (i + 1) < w.Length; i += 2) { w[i] = new MutableECPointPrime(curve); w[i].Set(w[i >> 1]); w[i].DoubleCT(); w[i + 1] = new MutableECPointPrime(curve); w[i + 1].Set(w[i]); good &= w[i + 1].AddCT(this); } /* obsolete * for (int i = 0; i < w.Length; i ++) { * w[i].ToAffine(); * w[i].Print("Win " + i); * w[i].ToJacobian(); * } * Console.WriteLine("good = {0}", (int)good); */ /* * Set this value to 0. We also set it already to * Jacobian coordinates, since it will be done that * way anyway. This instance will serve as accumulator. */ mx.Set(0); my.Set(0); mz.Set(0); affine = 0x00000000; /* * We process the multiplier by 4-bit nibbles, starting * with the most-significant one (the high nibble of the * first byte, since we use big-endian notation). * * For each nibble, we perform a constant-time lookup * in the window, to obtain the point to add to the * current value of the accumulator. Thanks to the * conditions on the operands (prime subgroup order and * so on), all the additions below must work. */ MutableECPointPrime t = new MutableECPointPrime(curve); for (int i = (n.Length << 1) - 1; i >= 0; i--) { int b = n[n.Length - 1 - (i >> 1)]; int j = (b >> ((i & 1) << 2)) & 0x0F; for (int k = 0; k < 16; k++) { t.Set(w[k], ~(uint)(((j - k) | (k - j)) >> 31)); } good &= AddCT(t); if (i > 0) { DoubleCT(); DoubleCT(); DoubleCT(); DoubleCT(); } } return(good); }
/* * 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; }