Beispiel #1
0
            /// <summary>
            /// Generate a key.
            /// </summary>
            /// <returns>A Poly1305 key.</returns>
            public Key GenerateKey()
            {
                Poly1305KeyGenerator cipherKeyGenerator = new Poly1305KeyGenerator();

                cipherKeyGenerator.Init(new Internal.KeyGenerationParameters(random, keySizeInBits));
                return(new Key(cipherKeyGenerator.GenerateKey()));
            }
Beispiel #2
0
 public TestCase(string key, string nonce, string message, string expectedMac)
 {
     this.key = Hex.Decode(key);
     // nacl test case keys are not pre-Clamped
     Poly1305KeyGenerator.Clamp(this.key);
     this.nonce       = (nonce == null) ? null : Hex.Decode(nonce);
     this.message     = Hex.Decode(message);
     this.expectedMac = Hex.Decode(expectedMac);
 }
Beispiel #3
0
        private void testReset()
        {
            CipherKeyGenerator gen = new Poly1305KeyGenerator();

            gen.Init(new KeyGenerationParameters(new SecureRandom(), 256));
            byte[] k = gen.GenerateKey();

            byte[] m      = new byte[10000];
            byte[] check  = new byte[16];
            byte[] output = new byte[16];

            // Generate baseline
            IMac poly = new Poly1305(new AesFastEngine());

            poly.Init(new ParametersWithIV(new KeyParameter(k), new byte[16]));

            poly.BlockUpdate(m, 0, m.Length);
            poly.DoFinal(check, 0);

            // Check reset after doFinal
            poly.BlockUpdate(m, 0, m.Length);
            poly.DoFinal(output, 0);

            if (!Arrays.AreEqual(check, output))
            {
                Fail("Mac not reset after doFinal");
            }

            // Check reset
            poly.Update((byte)1);
            poly.Update((byte)2);
            poly.Reset();
            poly.BlockUpdate(m, 0, m.Length);
            poly.DoFinal(output, 0);

            if (!Arrays.AreEqual(check, output))
            {
                Fail("Mac not reset after doFinal");
            }

            // Check init resets
            poly.Update((byte)1);
            poly.Update((byte)2);
            poly.Init(new ParametersWithIV(new KeyParameter(k), new byte[16]));
            poly.BlockUpdate(m, 0, m.Length);
            poly.DoFinal(output, 0);

            if (!Arrays.AreEqual(check, output))
            {
                Fail("Mac not reset after doFinal");
            }
        }
Beispiel #4
0
        protected virtual KeyParameter InitRecordMac(ChaChaEngine cipher, bool forEncryption, long seqNo)
        {
            byte[] array = new byte[8];
            TlsUtilities.WriteUint64(seqNo, array, 0);
            cipher.Init(forEncryption, new ParametersWithIV(null, array));
            byte[] array2 = new byte[64];
            cipher.ProcessBytes(array2, 0, array2.Length, array2, 0);
            Array.Copy(array2, 0, array2, 32, 16);
            KeyParameter keyParameter = new KeyParameter(array2, 16, 32);

            Poly1305KeyGenerator.Clamp(keyParameter.GetKey());
            return(keyParameter);
        }
        protected virtual KeyParameter GenerateRecordMacKey(IStreamCipher cipher)
        {
            byte[] firstBlock = new byte[64];
            cipher.ProcessBytes(firstBlock, 0, firstBlock.Length, firstBlock, 0);

            // NOTE: The BC implementation puts 'r' after 'k'
            Array.Copy(firstBlock, 0, firstBlock, 32, 16);
            Poly1305KeyGenerator.Clamp(firstBlock, 16);
            KeyParameter macKey = new KeyParameter(firstBlock, 16, 32);

            Arrays.Fill(firstBlock, (byte)0);
            return(macKey);
        }
        protected virtual KeyParameter InitRecordMac(ChaChaEngine cipher, bool forEncryption, long seqNo)
        {
            byte[] nonce = new byte[8];
            TlsUtilities.WriteUint64(seqNo, nonce, 0);

            cipher.Init(forEncryption, new ParametersWithIV(null, nonce));

            byte[] firstBlock = new byte[64];
            cipher.ProcessBytes(firstBlock, 0, firstBlock.Length, firstBlock, 0);

            // NOTE: The BC implementation puts 'r' after 'k'
            Array.Copy(firstBlock, 0, firstBlock, 32, 16);
            KeyParameter macKey = new KeyParameter(firstBlock, 16, 32);

            Poly1305KeyGenerator.Clamp(macKey.GetKey());
            return(macKey);
        }
Beispiel #7
0
        private void testInit()
        {
            CipherKeyGenerator gen = new Poly1305KeyGenerator();

            gen.Init(new KeyGenerationParameters(new SecureRandom(), 256));
            byte[] k = gen.GenerateKey();

            IMac poly = new Poly1305(new AesFastEngine());

            poly.Init(new ParametersWithIV(new KeyParameter(k), new byte[16]));

            try
            {
                poly.Init(new ParametersWithIV(new KeyParameter(k), new byte[15]));
                Fail("16 byte nonce required");
            }
            catch (ArgumentException)
            {
                // Expected
            }

            try
            {
                byte[] k2 = new byte[k.Length - 1];
                Array.Copy(k, 0, k2, 0, k2.Length);
                poly.Init(new ParametersWithIV(new KeyParameter(k2), new byte[16]));
                Fail("32 byte key required");
            }
            catch (ArgumentException)
            {
                // Expected
            }

            /*
             *          try
             *          {
             *                  k[19] = (byte)0xFF;
             *                  poly.Init(new ParametersWithIV(new KeyParameter(k), new byte[16]));
             *                  Fail("UnClamped key should not be accepted.");
             *          }
             * catch (ArgumentException)
             *          {
             *                  // Expected
             *          }
             */
        }
Beispiel #8
0
        private void SetKey(byte[] key, byte[] nonce)
        {
            if (cipher != null && (nonce == null || nonce.Length != BLOCK_SIZE))
            {
                throw new ArgumentException("Poly1305 requires a 128 bit IV.");
            }

            Poly1305KeyGenerator.CheckKey(key);

            // Extract r portion of key
            uint t0 = Pack.LE_To_UInt32(key, BLOCK_SIZE + 0);
            uint t1 = Pack.LE_To_UInt32(key, BLOCK_SIZE + 4);
            uint t2 = Pack.LE_To_UInt32(key, BLOCK_SIZE + 8);
            uint t3 = Pack.LE_To_UInt32(key, BLOCK_SIZE + 12);

            r0 = t0 & 0x3ffffff; t0 >>= 26; t0 |= t1 << 6;
            r1 = t0 & 0x3ffff03; t1 >>= 20; t1 |= t2 << 12;
            r2 = t1 & 0x3ffc0ff; t2 >>= 14; t2 |= t3 << 18;
            r3 = t2 & 0x3f03fff; t3 >>= 8;
            r4 = t3 & 0x00fffff;

            // Precompute multipliers
            s1 = r1 * 5;
            s2 = r2 * 5;
            s3 = r3 * 5;
            s4 = r4 * 5;

            byte[] kBytes;
            if (cipher == null)
            {
                kBytes = key;
            }
            else
            {
                // Compute encrypted nonce
                kBytes = new byte[BLOCK_SIZE];
                cipher.Init(true, new KeyParameter(key, 0, BLOCK_SIZE));
                cipher.ProcessBlock(nonce, 0, kBytes, 0);
            }

            k0 = Pack.LE_To_UInt32(kBytes, 0);
            k1 = Pack.LE_To_UInt32(kBytes, 4);
            k2 = Pack.LE_To_UInt32(kBytes, 8);
            k3 = Pack.LE_To_UInt32(kBytes, 12);
        }
Beispiel #9
0
        private void SetKey(byte[] key, byte[] nonce)
        {
            //IL_0017: Unknown result type (might be due to invalid IL or missing references)
            if (cipher != null && (nonce == null || nonce.Length != 16))
            {
                throw new ArgumentException("Poly1305 requires a 128 bit IV.");
            }
            Poly1305KeyGenerator.CheckKey(key);
            uint num  = Pack.LE_To_UInt32(key, 16);
            uint num2 = Pack.LE_To_UInt32(key, 20);
            uint num3 = Pack.LE_To_UInt32(key, 24);
            uint num4 = Pack.LE_To_UInt32(key, 28);

            r0     = num & 0x3FFFFFFu;
            num  >>= 26;
            num   |= num2 << 6;
            r1     = num & 0x3FFFF03u;
            num2 >>= 20;
            num2  |= num3 << 12;
            r2     = num2 & 0x3FFC0FFu;
            num3 >>= 14;
            num3  |= num4 << 18;
            r3     = num3 & 0x3F03FFFu;
            num4 >>= 8;
            r4     = num4 & 0xFFFFFu;
            s1     = r1 * 5;
            s2     = r2 * 5;
            s3     = r3 * 5;
            s4     = r4 * 5;
            byte[] array;
            if (cipher == null)
            {
                array = key;
            }
            else
            {
                array = new byte[16];
                cipher.Init(forEncryption: true, new KeyParameter(key, 0, 16));
                cipher.ProcessBlock(nonce, 0, array, 0);
            }
            k0 = Pack.LE_To_UInt32(array, 0);
            k1 = Pack.LE_To_UInt32(array, 4);
            k2 = Pack.LE_To_UInt32(array, 8);
            k3 = Pack.LE_To_UInt32(array, 12);
        }
Beispiel #10
0
        private void SetKey(byte[] key, byte[] nonce)
        {
            if (this.cipher != null && (nonce == null || nonce.Length != 16))
            {
                throw new ArgumentException("Poly1305 requires a 128 bit IV.");
            }
            Poly1305KeyGenerator.CheckKey(key);
            uint num  = Pack.LE_To_UInt32(key, 16);
            uint num2 = Pack.LE_To_UInt32(key, 20);
            uint num3 = Pack.LE_To_UInt32(key, 24);
            uint num4 = Pack.LE_To_UInt32(key, 28);

            this.r0 = (num & 67108863u);
            num   >>= 26;
            num    |= num2 << 6;
            this.r1 = (num & 67108611u);
            num2  >>= 20;
            num2   |= num3 << 12;
            this.r2 = (num2 & 67092735u);
            num3  >>= 14;
            num3   |= num4 << 18;
            this.r3 = (num3 & 66076671u);
            num4  >>= 8;
            this.r4 = (num4 & 1048575u);
            this.s1 = this.r1 * 5u;
            this.s2 = this.r2 * 5u;
            this.s3 = this.r3 * 5u;
            this.s4 = this.r4 * 5u;
            byte[] array;
            if (this.cipher == null)
            {
                array = key;
            }
            else
            {
                array = new byte[16];
                this.cipher.Init(true, new KeyParameter(key, 0, 16));
                this.cipher.ProcessBlock(nonce, 0, array, 0);
            }
            this.k0 = Pack.LE_To_UInt32(array, 0);
            this.k1 = Pack.LE_To_UInt32(array, 4);
            this.k2 = Pack.LE_To_UInt32(array, 8);
            this.k3 = Pack.LE_To_UInt32(array, 12);
        }
Beispiel #11
0
        private void testKeyGenerator()
        {
            CipherKeyGenerator gen = new Poly1305KeyGenerator();

            gen.Init(new KeyGenerationParameters(new SecureRandom(), 256));
            byte[] k = gen.GenerateKey();

            if (k.Length != 32)
            {
                Fail("Poly1305 key should be 256 bits.");
            }

            try
            {
                Poly1305KeyGenerator.CheckKey(k);
            }
            catch (ArgumentException)
            {
                Fail("Poly1305 key should be Clamped on generation.");
            }

            byte[] k2 = new byte[k.Length];
            Array.Copy(k, 0, k2, 0, k2.Length);
            Poly1305KeyGenerator.Clamp(k);
            if (!Arrays.AreEqual(k, k2))
            {
                Fail("Poly1305 key should be Clamped on generation.");
            }

            /*
             *          try
             *          {
             *                  k2[19] = (byte)0xff;
             *                  Poly1305KeyGenerator.CheckKey(k2);
             *                  Fail("UnClamped key should fail check.");
             *          }
             * catch (ArgumentException)
             *          {
             *                  // Expected
             *          }
             */
        }
        private KeyParameter InitRecordMAC(ChaChaEngine cipher)
        {
            byte[] zeroes = StringToByteArray(
                "00000000000000000000000000000000"
                + "00000000000000000000000000000000"
                + "00000000000000000000000000000000"
                + "00000000000000000000000000000000");

            byte[] firstBlock = new byte[64];
            cipher.ProcessBytes(zeroes, 0, firstBlock.Length, firstBlock, 0);

            Console.WriteLine("ChaCha OutBytes");
            Console.WriteLine(ByteArrayToString(firstBlock));

            // NOTE: The BC implementation puts 'r' after 'k'
            //Array.Copy(firstBlock, 0, firstBlock, 32, 16);
            //KeyParameter macKey = new KeyParameter(firstBlock, 16, 32);
            //Poly1305KeyGenerator.clamp(macKey.getKey());

            // 8th January, 2018 21:05
            //
            // The above code is from the github HAP-Java implementation. The problem was that the clamp() operator
            // wasn't having any effect! I'm guessing it's because the getKey() returns a new instance each time.
            // To work around this, I create a buffer, clamp it and then create a KeyParameter with the new byte[]
            // How the f**k I spotted this I'll never know.
            //

            KeyParameter macKey = new KeyParameter(firstBlock, 0, 32);

            var key = macKey.GetKey();

            //Console.WriteLine(ByteArrayToString(key));

            Poly1305KeyGenerator.Clamp(key);

            //Console.WriteLine(ByteArrayToString(key));

            Poly1305KeyGenerator.CheckKey(key);

            return(new KeyParameter(key));
        }
Beispiel #13
0
        private void testSequential()
        {
            // Sequential test, adapted from test-poly1305aes
            int len;

            byte[] kr     = new byte[32];
            byte[] m      = new byte[MAXLEN];
            byte[] n      = new byte[16];
            byte[] output = new byte[16];

            int  c   = 0;
            IMac mac = new Poly1305(new AesFastEngine());

            for (int loop = 0; loop < 13; loop++)
            {
                len = 0;
                for (;;)
                {
                    c++;
                    mac.Init(new ParametersWithIV(new KeyParameter(kr), n));
                    mac.BlockUpdate(m, 0, len);
                    mac.DoFinal(output, 0);

                    // if (c == 678)
                    // {
                    // TestCase tc = CASES[0];
                    //
                    // if (!Arrays.AreEqual(tc.key, kr))
                    // {
                    // System.err.println("Key bad");
                    // System.err.println(Hex.ToHexString(tc.key)));
                    // System.err.println(Hex.ToHexString(kr)));
                    // System.exit(1);
                    // }
                    // if (!Arrays.AreEqual(tc.nonce, n))
                    // {
                    // System.err.println("Nonce bad");
                    // System.exit(1);
                    // }
                    // System.out.printf("[%d] m: %s\n", c, Hex.ToHexString(m, 0, len)));
                    // System.out.printf("[%d] K: %s\n", c, new string(Hex.encodje(kr)));
                    // System.out.printf("[%d] N: %s\n", c, Hex.ToHexString(n)));
                    // System.out.printf("[%d] M: ", c);
                    // }
                    // System.out.printf("%d/%s\n", c, Hex.ToHexString(out)));

                    if (len >= MAXLEN)
                    {
                        break;
                    }
                    n[0] = (byte)(n[0] ^ loop);
                    for (int i = 0; i < 16; ++i)
                    {
                        n[i] ^= output[i];
                    }
                    if (len % 2 != 0)
                    {
                        for (int i = 0; i < 16; ++i)
                        {
                            kr[i] ^= output[i];
                        }
                    }
                    if (len % 3 != 0)
                    {
                        for (int i = 0; i < 16; ++i)
                        {
                            kr[i + 16] ^= output[i];
                        }
                    }
                    Poly1305KeyGenerator.Clamp(kr);
                    m[len++] ^= output[0];
                }
            }
            // Output after 13 loops as generated by poly1305 ref
            if (c != 13013 || !Arrays.AreEqual(output, Hex.Decode("c96f60a23701a5b0fd2016f58cbe4f7e")))
            {
                Fail("Sequential Poly1305 " + c, "c96f60a23701a5b0fd2016f58cbe4f7e", Hex.ToHexString(output));
            }
        }