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); }
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); }
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); }
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)); }