ZInt RunInner(ZInt a, ZInt r, byte[] data, int off, int len) { byte[] tmp = new byte[16]; while (len > 0) { if (len >= 16) { Array.Copy(data, off, tmp, 0, 16); } else { Array.Copy(data, off, tmp, 0, len); for (int i = len; i < 16; i++) { tmp[i] = 0; } } ByteSwap(tmp, 0, 16); ZInt v = ZInt.DecodeUnsignedBE(tmp) | ((ZInt)1 << 128); a = ((a + v) * r) % p; off += 16; len -= 16; } return(a); }
public void Run(byte[] iv, byte[] data, int off, int len, byte[] aad, int offAAD, int lenAAD, byte[] tag, bool encrypt) { byte[] pkey = new byte[32]; ChaCha.Run(iv, 0, pkey); if (encrypt) { ChaCha.Run(iv, 1, data, off, len); } ByteSwap(pkey, 0, 16); ZInt r = ZInt.DecodeUnsignedBE(pkey, 0, 16); r &= rmask; ZInt a = (ZInt)0; a = RunInner(a, r, aad, offAAD, lenAAD); a = RunInner(a, r, data, off, len); byte[] foot = new byte[16]; foot[0] = (byte)lenAAD; foot[1] = (byte)(lenAAD >> 8); foot[2] = (byte)(lenAAD >> 16); foot[3] = (byte)(lenAAD >> 24); foot[8] = (byte)len; foot[9] = (byte)(len >> 8); foot[10] = (byte)(len >> 16); foot[11] = (byte)(len >> 24); a = RunInner(a, r, foot, 0, 16); ByteSwap(pkey, 16, 16); ZInt s = ZInt.DecodeUnsignedBE(pkey, 16, 16); a += s; a.ToBytesLE(tag, 0, 16); if (!encrypt) { ChaCha.Run(iv, 1, data, off, len); } }
internal static void TestModInt() { Console.Write("Test ModInt: "); for (int k = 2; k <= 128; k++) { for (int i = 0; i < 10; i++) { int kwlen = (k + 30) / 31; int kwb = 31 * kwlen; ZInt p; if (k >= 9) { p = ZInt.DecodeUnsignedBE( BigInt.RandPrime(k)); if (p.BitLength != k) { throw new Exception( "wrong prime size"); } if (!p.IsPrime) { throw new Exception( "not prime"); } } else { p = RandPrime(k); } ZInt a = ZInt.MakeRand(p); ZInt b = ZInt.MakeRand(p); ZInt v = ZInt.MakeRand(k + 60); if (b == ZInt.Zero) { b = ZInt.One; } byte[] ea = a.ToBytesBE(); byte[] eb = b.ToBytesBE(); byte[] ev = v.ToBytesBE(); ModInt mz = new ModInt(p.ToBytesBE()); ModInt ma = mz.Dup(); ModInt mb = mz.Dup(); ma.Decode(ea); CheckEq(ma, a); ma.Decode(ea); mb.Decode(eb); ma.Add(mb); CheckEq(ma, (a + b).Mod(p)); ma.Decode(ea); mb.Decode(eb); ma.Sub(mb); CheckEq(ma, (a - b).Mod(p)); ma.Decode(ea); ma.Negate(); CheckEq(ma, (-a).Mod(p)); ma.Decode(ea); mb.Decode(eb); ma.MontyMul(mb); CheckEq((ZInt.DecodeUnsignedBE(ma.Encode()) << kwb).Mod(p), (a * b).Mod(p)); ma.Decode(ea); ma.ToMonty(); CheckEq(ma, (a << kwb).Mod(p)); ma.FromMonty(); CheckEq(ma, a); ma.Decode(ea); mb.Decode(eb); ma.ToMonty(); mb.ToMonty(); ma.MontyMul(mb); ma.FromMonty(); CheckEq(ma, (a * b).Mod(p)); mb.Decode(eb); mb.Invert(); ZInt r = ZInt.DecodeUnsignedBE(mb.Encode()); CheckEq(ZInt.One, (r * b).Mod(p)); ma.Decode(ea); ma.Pow(ev); CheckEq(ma, ZInt.ModPow(a, v, p)); ma.DecodeReduce(ev); CheckEq(ma, v.Mod(p)); mb.Decode(eb); ma.Set(mb); CheckEq(ma, b); ModInt mv = new ModInt( ((p << 61) + 1).ToBytesBE()); mv.Decode(ev); ma.Set(mv); CheckEq(ma, v.Mod(p)); if (k >= 9) { ma.Decode(ea); mb.Set(ma); mb.ToMonty(); mb.MontyMul(ma); if ((int)mb.SqrtBlum() != -1) { throw new CryptoException( "square root failed"); } if (!mb.Eq(ma)) { mb.Negate(); } CheckEq(mb, a); mb.Decode(eb); mb.ToMonty(); mb.MontySquare(); mb.FromMonty(); mb.Negate(); if (mb.SqrtBlum() != 0) { throw new CryptoException( "square root should" + " have failed"); } } } Console.Write("."); } Console.WriteLine(" done."); }
static void CheckEq(ModInt m, ZInt z) { CheckEq(ZInt.DecodeUnsignedBE(m.Encode()), z); }