private void MacTest(byte[] Key, byte[] Input, byte[] Expected) { byte[] hash = new byte[16]; using (CMAC mac = new CMAC(new RHX())) { mac.Initialize(Key, null); mac.BlockUpdate(Input, 0, Input.Length); mac.DoFinal(hash, 0); } if (!Evaluate.AreEqual(Expected, hash)) { throw new Exception("CMAC is not equal! Expected: " + HexConverter.ToString(Expected) + " Received: " + HexConverter.ToString(hash)); } }
private void CmacDescriptionTest() { CSPPrng rng = new CSPPrng(); byte[] data = rng.GetBytes(rng.Next(100, 400)); byte[] key = rng.GetBytes(32); byte[] iv = rng.GetBytes(16); CMAC mac = new CMAC(BlockCiphers.Rijndael); mac.Initialize(key, iv); byte[] c1 = mac.ComputeMac(data); MacDescription mds = new MacDescription(32, BlockCiphers.Rijndael, IVSizes.V128, BlockSizes.B128, RoundCounts.R14); MacStream mst = new MacStream(mds, new KeyParams(key, iv)); mst.Initialize(new MemoryStream(data)); byte[] c2 = mst.ComputeMac(); if (!Evaluate.AreEqual(c1, c2)) { throw new Exception("MacStreamTest: CMAC code arrays are not equal!"); } }
private void Process(ReadOnlySpan <byte> nonce, ReadOnlySpan <byte> input, Span <byte> output, Span <byte> tag, ReadOnlySpan <byte> associatedData, bool outputIsCiphertext) { using var encryptor = aes.CreateEncryptor(); var tmp = CryptoPool.Rent(16); var counter = CryptoPool.Rent(16); var counterEnc = CryptoPool.Rent(16); var nonceMac = CryptoPool.Rent(16); var associatedDataMac = CryptoPool.Rent(16); var ciphertextMac = CryptoPool.Rent(16); try { CryptographicOperations.ZeroMemory(tmp.AsSpan(0, 15)); tmp[15] = 0; // N tag cmac.TransformBlock(tmp, 0, 16, null, 0); cmac.TryComputeHash(nonce, nonceMac, out var _); tmp[15] = 1; // H tag cmac.TransformBlock(tmp, 0, 16, null, 0); cmac.TryComputeHash(associatedData, associatedDataMac, out var _); cmac.Initialize(); tmp[15] = 2; // C tag cmac.TransformBlock(tmp, 0, 16, null, 0); nonceMac.AsSpan().CopyTo(counter); while (input.Length >= 16) { encryptor.TransformBlock(counter, 0, 16, counterEnc, 0); if (outputIsCiphertext) { for (int i = 0; i < 16; i++) { tmp[i] = (byte)(input[i] ^ counterEnc[i]); } cmac.TransformBlock(tmp, 0, 16, null, 0); tmp.AsSpan(0, 16).CopyTo(output); } else { input.Slice(0, 16).CopyTo(tmp); cmac.TransformBlock(tmp, 0, 16, null, 0); for (int i = 0; i < 16; i++) { output[i] = (byte)(input[i] ^ counterEnc[i]); } } byte add = 1; for (int i = 15; i >= 0; i--) { counter[i] += add; add = counter[i] == 0 ? 1 : 0; } input = input.Slice(16); output = output.Slice(16); } if (input.Length > 0) { encryptor.TransformBlock(counter, 0, 16, counterEnc, 0); if (outputIsCiphertext) { for (int i = 0; i < input.Length; i++) { tmp[i] = (byte)(input[i] ^ counterEnc[i]); } cmac.TransformBlock(tmp, 0, input.Length, null, 0); tmp.AsSpan(0, input.Length).CopyTo(output); } else { input.CopyTo(tmp); cmac.TransformBlock(tmp, 0, input.Length, null, 0); for (int i = 0; i < input.Length; i++) { output[i] = (byte)(input[i] ^ counterEnc[i]); } } } cmac.TryComputeHash(Array.Empty <byte>(), ciphertextMac, out var _); for (int i = 0; i < tag.Length; i++) { tag[i] = (byte)(nonceMac[i] ^ associatedDataMac[i] ^ ciphertextMac[i]); } } finally { cmac.Initialize(); CryptoPool.Return(tmp, 16); CryptoPool.Return(counter, 16); CryptoPool.Return(counterEnc, 16); CryptoPool.Return(nonceMac, 16); CryptoPool.Return(associatedDataMac, 16); CryptoPool.Return(ciphertextMac, 16); } }