internal ZMod(byte[] bmod, int off, int len) { bitLen = BigInt.BitLength(bmod, off, len); if (bitLen <= 1 || (bmod[off + len - 1] & 1) == 0) { throw new CryptoException("invalid modulus"); } int n = (bitLen + 30) / 31; val = new uint[n]; DecodeBE(bmod, off, len, val); uint x = val[0]; uint y = 2 - x; y *= 2 - y * x; y *= 2 - y * x; y *= 2 - y * x; y *= 2 - y * x; n0i = (1 + ~y) & 0x7FFFFFFF; /* * Compute the Rx[] values. */ int zk = 0; while ((n >> zk) != 0) { zk++; } R = new uint[n]; R[n - 1] = 1; for (int i = 0; i < 31; i++) { ModMul2(R, val); } Rx = new uint[zk][]; Rx[0] = new uint[n]; Array.Copy(R, 0, Rx[0], 0, n); for (int i = 0; i < 31; i++) { ModMul2(Rx[0], val); } for (int k = 1; k < zk; k++) { Rx[k] = new uint[n]; MontyMul(Rx[k - 1], Rx[k - 1], Rx[k], val, n0i); } /* * Compute R2 by multiplying the relevant Rx[] * values. */ R2 = null; uint[] tt = new uint[n]; for (int k = 0; k < zk; k++) { if (((n >> k) & 1) == 0) { continue; } if (R2 == null) { R2 = new uint[n]; Array.Copy(Rx[k], 0, R2, 0, n); } else { MontyMul(Rx[k], R2, tt, val, n0i); Array.Copy(tt, 0, R2, 0, n); } } /* * Compute N-2; used as an exponent for modular * inversion. Since modulus N is odd and greater * than 1, N-2 is necessarily positive. */ vm2 = new byte[(bitLen + 7) >> 3]; int cc = 2; for (int i = 0; i < vm2.Length; i++) { int b = bmod[off + len - 1 - i]; b -= cc; vm2[vm2.Length - 1 - i] = (byte)b; cc = (b >> 8) & 1; } }
/* * 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; }