From 64754bc98150efd15305a861a6b6c420db163635 Mon Sep 17 00:00:00 2001 From: mw Date: Wed, 28 Oct 2020 15:49:41 +1100 Subject: Added CSHAKEDigest, KMac, removed unused import from NewTspTest --- crypto/src/crypto/digests/CSHAKEDigest.cs | 115 ++++++++++++++ crypto/src/crypto/digests/XofUtils.cs | 54 +++++++ crypto/src/crypto/macs/KMac.cs | 184 ++++++++++++++++++++++ crypto/test/src/crypto/test/CSHAKETest.cs | 205 +++++++++++++++++++++++++ crypto/test/src/crypto/test/KMACTest.cs | 245 ++++++++++++++++++++++++++++++ crypto/test/src/tsp/test/NewTspTest.cs | 1 - 6 files changed, 803 insertions(+), 1 deletion(-) create mode 100644 crypto/src/crypto/digests/CSHAKEDigest.cs create mode 100644 crypto/src/crypto/digests/XofUtils.cs create mode 100644 crypto/src/crypto/macs/KMac.cs create mode 100644 crypto/test/src/crypto/test/CSHAKETest.cs create mode 100644 crypto/test/src/crypto/test/KMACTest.cs diff --git a/crypto/src/crypto/digests/CSHAKEDigest.cs b/crypto/src/crypto/digests/CSHAKEDigest.cs new file mode 100644 index 000000000..5c42b4171 --- /dev/null +++ b/crypto/src/crypto/digests/CSHAKEDigest.cs @@ -0,0 +1,115 @@ +using Org.BouncyCastle.Utilities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Org.BouncyCastle.Crypto.Digests +{ + /// + /// Customizable SHAKE function. + /// + public class CSHAKEDigest : ShakeDigest + { + private static readonly byte[] padding = new byte[100]; + private readonly byte[] diff; + + /// + /// Base constructor + /// + /// bit length of the underlying SHAKE function, 128 or 256. + /// the function name string, note this is reserved for use by NIST. Avoid using it if not required. + /// the customization string - available for local use. + public CSHAKEDigest(int bitLength, byte[] N, byte[] S) : base(bitLength) + { + if ((N == null || N.Length == 0) && (S == null || S.Length == 0)) + { + diff = null; + } + else + { + diff = Arrays.ConcatenateAll(XofUtils.leftEncode(rate / 8), encodeString(N), encodeString(S)); + DiffPadAndAbsorb(); + } + } + + + // bytepad in SP 800-185 + private void DiffPadAndAbsorb() + { + int blockSize = rate / 8; + Absorb(diff, 0, diff.Length); + + int delta = diff.Length % blockSize; + + // only add padding if needed + if (delta != 0) + { + int required = blockSize - delta; + + while (required > padding.Length) + { + Absorb(padding, 0, padding.Length); + required -= padding.Length; + } + + Absorb(padding, 0, required); + } + } + + private byte[] encodeString(byte[] str) + { + if (str == null || str.Length == 0) + { + return XofUtils.leftEncode(0); + } + + return Arrays.Concatenate(XofUtils.leftEncode(str.Length * 8L), str); + } + + public override string AlgorithmName => "CSHAKE" + fixedOutputLength; + + public override int DoFinal(byte[] output, int outOff) + { + return DoFinal(output, outOff,GetDigestSize()); + } + + public override int DoFinal(byte[] output, int outOff, int outLen) + { + int length = DoOutput(output, outOff, outLen); + + Reset(); + + return length; + } + + public override int DoOutput(byte[] output, int outOff, int outLen) + { + if (diff != null) + { + if (!squeezing) + { + AbsorbBits(0x00, 2); + } + + Squeeze(output, outOff, ((long)outLen) * 8); + + return outLen; + } + else + { + return base.DoOutput(output, outOff, outLen); + } + } + + public void Reset() + { + base.Reset(); + + if (diff != null) + { + DiffPadAndAbsorb(); + } + } + } +} diff --git a/crypto/src/crypto/digests/XofUtils.cs b/crypto/src/crypto/digests/XofUtils.cs new file mode 100644 index 000000000..e4c893e01 --- /dev/null +++ b/crypto/src/crypto/digests/XofUtils.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Org.BouncyCastle.Crypto.Digests +{ + public class XofUtils + { + public static byte[] leftEncode(long strLen) + { + byte n = 1; + + long v = strLen; + while ((v >>= 8) != 0) + { + n++; + } + + byte[] b = new byte[n + 1]; + + b[0] = n; + + for (int i = 1; i <= n; i++) + { + b[i] = (byte)(strLen >> (8 * (n - i))); + } + + return b; + } + + public static byte[] rightEncode(long strLen) + { + byte n = 1; + + long v = strLen; + while ((v >>= 8) != 0) + { + n++; + } + + byte[] b = new byte[n + 1]; + + b[n] = n; + + for (int i = 0; i < n; i++) + { + b[i] = (byte)(strLen >> (8 * (n - i - 1))); + } + + return b; + } + } +} diff --git a/crypto/src/crypto/macs/KMac.cs b/crypto/src/crypto/macs/KMac.cs new file mode 100644 index 000000000..38697a9a9 --- /dev/null +++ b/crypto/src/crypto/macs/KMac.cs @@ -0,0 +1,184 @@ +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Org.BouncyCastle.Crypto.Macs +{ + public class KMac : IMac, IXof + { + + private static readonly byte[] padding = new byte[100]; + + private readonly CSHAKEDigest cshake; + private readonly int bitLength; + private readonly int outputLength; + + private byte[] key; + private bool initialised; + private bool firstOutput; + + + public KMac(int bitLength, byte[] S) + { + this.cshake = new CSHAKEDigest(bitLength, Encoding.ASCII.GetBytes("KMAC"),S); + this.bitLength = bitLength; + this.outputLength = bitLength * 2 / 8; + } + + + public string AlgorithmName => "KMAC" + cshake.AlgorithmName.Substring(6); + + public void BlockUpdate(byte[] input, int inOff, int len) + { + if (!initialised) + { + throw new InvalidOperationException("KMAC not initialized"); + } + + cshake.BlockUpdate(input, inOff, len); + } + + public int DoFinal(byte[] output, int outOff) + { + if (firstOutput) + { + if (!initialised) + { + throw new InvalidOperationException("KMAC not initialized"); + } + + byte[] encOut = XofUtils.rightEncode(GetMacSize() * 8); + + cshake.BlockUpdate(encOut, 0, encOut.Length); + } + + int rv = cshake.DoFinal(output, outOff, GetMacSize()); + + Reset(); + + return rv; + } + + public int DoFinal(byte[] output, int outOff, int outLen) + { + if (firstOutput) + { + if (!initialised) + { + throw new InvalidOperationException("KMAC not initialized"); + } + + byte[] encOut = XofUtils.rightEncode(outLen * 8); + + cshake.BlockUpdate(encOut, 0, encOut.Length); + } + + int rv = cshake.DoFinal(output, outOff, outLen); + + Reset(); + + return rv; + } + + public int DoOutput(byte[] output, int outOff, int outLen) + { + if (firstOutput) + { + if (!initialised) + { + throw new InvalidOperationException("KMAC not initialized"); + } + + byte[] encOut = XofUtils.rightEncode(0); + + cshake.BlockUpdate(encOut, 0, encOut.Length); + + firstOutput = false; + } + + return cshake.DoOutput(output, outOff, outLen); + } + + public int GetByteLength() + { + return cshake.GetByteLength(); + } + + public int GetDigestSize() + { + return outputLength; + } + + public int GetMacSize() + { + return outputLength; + } + + public void Init(ICipherParameters parameters) + { + KeyParameter kParam = (KeyParameter)parameters; + this.key = Arrays.Clone(kParam.GetKey()); + this.initialised = true; + Reset(); + } + + public void Reset() + { + cshake.Reset(); + + if (key != null) + { + if (bitLength == 128) + { + bytePad(key, 168); + } + else + { + bytePad(key, 136); + } + } + + firstOutput = true; + } + + private void bytePad(byte[] X, int w) + { + byte[] bytes = XofUtils.leftEncode(w); + BlockUpdate(bytes, 0, bytes.Length); + byte[] encX = encode(X); + BlockUpdate(encX, 0, encX.Length); + + int required = w - ((bytes.Length + encX.Length) % w); + + if (required > 0 && required != w) + { + while (required > padding.Length) + { + BlockUpdate(padding, 0, padding.Length); + required -= padding.Length; + } + + BlockUpdate(padding, 0, required); + } + } + + private static byte[] encode(byte[] X) + { + return Arrays.Concatenate(XofUtils.leftEncode(X.Length * 8), X); + } + + public void Update(byte input) + { + if (!initialised) + { + throw new InvalidOperationException("KMAC not initialized"); + } + + cshake.Update(input); + } + } +} diff --git a/crypto/test/src/crypto/test/CSHAKETest.cs b/crypto/test/src/crypto/test/CSHAKETest.cs new file mode 100644 index 000000000..80f0eb1f7 --- /dev/null +++ b/crypto/test/src/crypto/test/CSHAKETest.cs @@ -0,0 +1,205 @@ +using NUnit.Framework; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Org.BouncyCastle.Crypto.Tests +{ + public class CSHAKETest + { + [Test] + public void PerformTest() + { + CSHAKEDigest cshake = new CSHAKEDigest(128, new byte[0], Strings.ToByteArray("Email Signature")); + + cshake.BlockUpdate(Hex.Decode("00010203"), 0, 4); + + byte[] res = new byte[32]; + + cshake.DoOutput(res, 0, res.Length); + + Assert.IsTrue(Arrays.AreEqual(Hex.Decode("c1c36925b6409a04f1b504fcbca9d82b4017277cb5ed2b2065fc1d3814d5aaf5"), res)); + + cshake = new CSHAKEDigest(128, new byte[0], Strings.ToByteArray("Email Signature")); + + cshake.BlockUpdate(Hex.Decode( + "000102030405060708090A0B0C0D0E0F" + + "101112131415161718191A1B1C1D1E1F" + + "202122232425262728292A2B2C2D2E2F" + + "303132333435363738393A3B3C3D3E3F" + + "404142434445464748494A4B4C4D4E4F" + + "505152535455565758595A5B5C5D5E5F" + + "606162636465666768696A6B6C6D6E6F" + + "707172737475767778797A7B7C7D7E7F" + + "808182838485868788898A8B8C8D8E8F" + + "909192939495969798999A9B9C9D9E9F" + + "A0A1A2A3A4A5A6A7A8A9AAABACADAEAF" + + "B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF" + + "C0C1C2C3C4C5C6C7"), 0, 1600 / 8); + + res = new byte[32]; + + cshake.DoOutput(res, 0, res.Length); + + Assert.IsTrue(Arrays.AreEqual(Hex.Decode("C5221D50E4F822D96A2E8881A961420F294B7B24FE3D2094BAED2C6524CC166B "), res)); + + cshake = new CSHAKEDigest(256, new byte[0], Strings.ToByteArray("Email Signature")); + + cshake.BlockUpdate(Hex.Decode("00010203"), 0, 4); + + res = new byte[64]; + + cshake.DoOutput(res, 0, res.Length); + + Assert.IsTrue(Arrays.AreEqual(Hex.Decode( + "D008828E2B80AC9D2218FFEE1D070C48" + + "B8E4C87BFF32C9699D5B6896EEE0EDD1" + + "64020E2BE0560858D9C00C037E34A969" + + "37C561A74C412BB4C746469527281C8C"), res)); + + cshake = new CSHAKEDigest(256, new byte[0], Strings.ToByteArray("Email Signature")); + + cshake.BlockUpdate(Hex.Decode( + "000102030405060708090A0B0C0D0E0F" + + "101112131415161718191A1B1C1D1E1F" + + "202122232425262728292A2B2C2D2E2F" + + "303132333435363738393A3B3C3D3E3F" + + "404142434445464748494A4B4C4D4E4F" + + "505152535455565758595A5B5C5D5E5F" + + "606162636465666768696A6B6C6D6E6F" + + "707172737475767778797A7B7C7D7E7F" + + "808182838485868788898A8B8C8D8E8F" + + "909192939495969798999A9B9C9D9E9F" + + "A0A1A2A3A4A5A6A7A8A9AAABACADAEAF" + + "B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF" + + "C0C1C2C3C4C5C6C7"), 0, 1600 / 8); + + res = new byte[64]; + + cshake.DoOutput(res, 0, res.Length); + + Assert.IsTrue(Arrays.AreEqual(Hex.Decode( + "07DC27B11E51FBAC75BC7B3C1D983E8B" + + "4B85FB1DEFAF218912AC864302730917" + + "27F42B17ED1DF63E8EC118F04B23633C" + + "1DFB1574C8FB55CB45DA8E25AFB092BB"), res)); + + doFinalTest(); + longBlockTest(); + checkZeroPadZ(); + + checkSHAKE(128, new CSHAKEDigest(128, new byte[0], new byte[0]), Hex.Decode("eeaabeef")); + checkSHAKE(256, new CSHAKEDigest(256, new byte[0], null), Hex.Decode("eeaabeef")); + checkSHAKE(128, new CSHAKEDigest(128, null, new byte[0]), Hex.Decode("eeaabeef")); + checkSHAKE(128, new CSHAKEDigest(128, null, null), Hex.Decode("eeaabeef")); + checkSHAKE(256, new CSHAKEDigest(256, null, null), Hex.Decode("eeaabeef")); + } + + private void checkZeroPadZ() + { + byte[] buf = new byte[20]; + + CSHAKEDigest cshake1 = new CSHAKEDigest(256, new byte[0], new byte[265]); + cshake1.DoOutput(buf, 0, buf.Length); + Assert.IsTrue(Arrays.AreEqual(Hex.Decode("6e393540387004f087c4180db008acf6825190cf"), buf)); + + CSHAKEDigest cshake2 = new CSHAKEDigest(128, new byte[0], new byte[329]); + cshake2.DoOutput(buf, 0, buf.Length); + Assert.IsTrue(Arrays.AreEqual(Hex.Decode("309bd7c285fcf8b839c9686b2cc00bd578947bee"), buf)); + + cshake2 = new CSHAKEDigest(128, new byte[29], new byte[300]); + cshake2.DoOutput(buf, 0, buf.Length); + Assert.IsTrue(Arrays.AreEqual(Hex.Decode("ff6aafd83b8d22fc3e2e9b9948b581967ed9c5e7"), buf)); + } + + private void doFinalTest() + { + CSHAKEDigest cshake = new CSHAKEDigest(128, new byte[0], Strings.ToByteArray("Email Signature")); + + cshake.BlockUpdate(Hex.Decode("00010203"), 0, 4); + + byte[] res = new byte[32]; + + cshake.DoOutput(res, 0, res.Length); + + Assert.IsTrue(Arrays.AreEqual(Hex.Decode("c1c36925b6409a04f1b504fcbca9d82b4017277cb5ed2b2065fc1d3814d5aaf5"), res)); + + cshake.DoOutput(res, 0, res.Length); + + Assert.IsTrue(!Arrays.AreEqual(Hex.Decode("c1c36925b6409a04f1b504fcbca9d82b4017277cb5ed2b2065fc1d3814d5aaf5"), res)); + + cshake.DoFinal(res, 0, res.Length); + + cshake.BlockUpdate(Hex.Decode("00010203"), 0, 4); + + cshake.DoFinal(res, 0, res.Length); + + var s = Hex.ToHexString(res); + + Console.WriteLine(s); + + Assert.IsTrue(Arrays.AreEqual(Hex.Decode("c1c36925b6409a04f1b504fcbca9d82b4017277cb5ed2b2065fc1d3814d5aaf5"), res)); + + cshake.BlockUpdate(Hex.Decode("00010203"), 0, 4); + + cshake.DoOutput(res, 0, res.Length); + + Assert.IsTrue(Arrays.AreEqual(Hex.Decode("c1c36925b6409a04f1b504fcbca9d82b4017277cb5ed2b2065fc1d3814d5aaf5"), res)); + + cshake.DoFinal(res, 0, res.Length); + + Assert.IsTrue(Arrays.AreEqual(Hex.Decode("9cbce830079c452abdeb875366a49ebfe75b89ef17396e34898e904830b0e136"), res)); + } + + private void longBlockTest() + { + byte[] data = new byte[16000]; + byte[] res = new byte[32]; + + for (int i = 0; i != data.Length; i++) + { + data[i] = (byte)i; + } + + for (int i = 10000; i != data.Length; i++) + { + CSHAKEDigest cshake_ = new CSHAKEDigest(128, new byte[0], Arrays.CopyOfRange(data, 0, i)); + + cshake_.BlockUpdate(Hex.Decode("00010203"), 0, 4); + + cshake_.DoFinal(res, 0); + } + + + CSHAKEDigest cshake = new CSHAKEDigest(256, new byte[0], new byte[200]); + + cshake.BlockUpdate(Arrays.CopyOfRange(data, 0, 200), 0, 200); + + cshake.DoFinal(res, 0); + + Assert.IsTrue(Arrays.AreEqual(Hex.Decode("4a899b5be460d85a9789215bc17f88b8f8ac049bd3b519f561e7b5d3870dafa3"), res)); + } + + private void checkSHAKE(int bitSize, CSHAKEDigest cshake, byte[] msg) + { + + ShakeDigest ref_ = new ShakeDigest(bitSize); + + ref_.BlockUpdate(msg, 0, msg.Length); + cshake.BlockUpdate(msg, 0, msg.Length); + + byte[] res1 = new byte[32]; + byte[] res2 = new byte[32]; + + ref_.DoFinal(res1, 0, res1.Length); + cshake.DoFinal(res2, 0, res2.Length); + + Assert.IsTrue(Arrays.AreEqual(res1, res2)); + } + + } +} diff --git a/crypto/test/src/crypto/test/KMACTest.cs b/crypto/test/src/crypto/test/KMACTest.cs new file mode 100644 index 000000000..c7f3843c1 --- /dev/null +++ b/crypto/test/src/crypto/test/KMACTest.cs @@ -0,0 +1,245 @@ +using NUnit.Framework; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Org.BouncyCastle.Crypto.Tests +{ + public class KMACTest + { + [Test] + public void performTest() + { + KMac kmac = new KMac(128, new byte[0] { }); + + Assert.AreEqual("KMAC128", kmac.AlgorithmName); + + kmac.Init(new KeyParameter(Hex.Decode( + "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F"))); + + kmac.BlockUpdate(Hex.Decode("00010203"), 0, 4); + + byte[] res = new byte[32]; + + kmac.DoFinal(res, 0, res.Length); + + Assert.IsTrue( Arrays.AreEqual(Hex.Decode("E5780B0D3EA6F7D3A429C5706AA43A00FADBD7D49628839E3187243F456EE14E"), res), "oops: " + Hex.ToHexString(res)); + + kmac = new KMac(128, Encoding.ASCII.GetBytes("My Tagged Application")); + + kmac.Init(new KeyParameter(Hex.Decode( + "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F"))); + + kmac.BlockUpdate(Hex.Decode("00010203"), 0, 4); + + res = new byte[32]; + + kmac.DoFinal(res, 0, res.Length); + + Assert.IsTrue( Arrays.AreEqual(Hex.Decode("3B1FBA963CD8B0B59E8C1A6D71888B7143651AF8BA0A7070C0979E2811324AA5"), res), "oops: " + Hex.ToHexString(res)); + + kmac = new KMac(128, Encoding.ASCII.GetBytes("My Tagged Application")); + + kmac.Init(new KeyParameter(Hex.Decode( + "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F"))); + + byte[] data = Hex.Decode( + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1" + + "F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3" + + "E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5" + + "D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7" + + "C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9" + + "B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9B" + + "ABBBCBDBEBFC0C1C2C3C4C5C6C7"); + kmac.BlockUpdate(data, 0, data.Length); + + res = new byte[32]; + + kmac.DoFinal(res, 0, res.Length); + + Assert.IsTrue(Arrays.AreEqual(Hex.Decode("1F5B4E6CCA02209E0DCB5CA635B89A15E271ECC760071DFD805FAA38F9729230"), res), "oops:" + Hex.ToHexString(res)); + + kmac = new KMac(256, Encoding.ASCII.GetBytes("My Tagged Application")); + + Assert.AreEqual("KMAC256", kmac.AlgorithmName); + + kmac.Init(new KeyParameter(Hex.Decode("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F"))); + + data = Hex.Decode("00 01 02 03"); + kmac.BlockUpdate(data, 0, data.Length); + + res = new byte[64]; + + kmac.DoFinal(res, 0, res.Length); + + Assert.IsTrue(Arrays.AreEqual(Hex.Decode("20C570C31346F703C9AC36C61C03CB64C3970D0CFC787E9B79599D273A68D2F7F69D4CC3DE9D104A351689F27CF6F5951F0103F33F4F24871024D9C27773A8DD"), res), "oops:" + Hex.ToHexString(res)); + + kmac = new KMac(256, new byte[] { }); + + kmac.Init(new KeyParameter(Hex.Decode( + "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F"))); + + data = Hex.Decode( + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1" + + "F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3" + + "E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5" + + "D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7" + + "C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9" + + "B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9B" + + "ABBBCBDBEBFC0C1C2C3C4C5C6C7"); + kmac.BlockUpdate(data, 0, data.Length); + + res = new byte[64]; + + kmac.DoFinal(res, 0, res.Length); + + Assert.IsTrue(Arrays.AreEqual(Hex.Decode("75358CF39E41494E949707927CEE0AF20A3FF553904C86B08F21CC414BCFD691589D27CF5E15369CBBFF8B9A4C2EB17800855D0235FF635DA82533EC6B759B69"), res), "oops:" + Hex.ToHexString(res)); + + kmac = new KMac(256, Encoding.ASCII.GetBytes("My Tagged Application")); + + kmac.Init(new KeyParameter(Hex.Decode( + "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F"))); + + data = Hex.Decode( + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1" + + "F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3" + + "E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5" + + "D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7" + + "C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9" + + "B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9B" + + "ABBBCBDBEBFC0C1C2C3C4C5C6C7"); + kmac.BlockUpdate(data, 0, data.Length); + + res = new byte[64]; + + kmac.DoFinal(res, 0, res.Length); + + Assert.IsTrue(Arrays.AreEqual(Hex.Decode("B58618F71F92E1D56C1B8C55DDD7CD188B97B4CA4D99831EB2699A837DA2E4D970FBACFDE50033AEA585F1A2708510C32D07880801BD182898FE476876FC8965"), res), "oops:" + Hex.ToHexString(res)); + + doFinalTest(); + longBlockTest(); + paddingCheckTest(); + + checkKMAC(128, new KMac(128, new byte[0]), Hex.Decode("eeaabeef")); + checkKMAC(256, new KMac(256, null), Hex.Decode("eeaabeef")); + checkKMAC(128, new KMac(128, new byte[0]), Hex.Decode("eeaabeef")); + checkKMAC(128, new KMac(128, null), Hex.Decode("eeaabeef")); + checkKMAC(256, new KMac(256, null), Hex.Decode("eeaabeef")); + + } + + public void doFinalTest() + { + KMac kmac = new KMac(128, Encoding.ASCII.GetBytes("My Tagged Application")); + + kmac.Init(new KeyParameter(Hex.Decode( + "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F"))); + + kmac.BlockUpdate(Hex.Decode("00010203"), 0, 4); + + byte[] res = new byte[32]; + + kmac.DoOutput(res, 0, res.Length); + + Assert.IsTrue(Arrays.AreEqual(Hex.Decode("31a44527b4ed9f5c6101d11de6d26f0620aa5c341def41299657fe9df1a3b16c"), res), Hex.ToHexString(res)); + + kmac.DoOutput(res, 0, res.Length); + + Assert.IsTrue(!Arrays.AreEqual(Hex.Decode("31a44527b4ed9f5c6101d11de6d26f0620aa5c341def41299657fe9df1a3b16c"), res)); + + kmac.DoFinal(res, 0, res.Length); + + kmac.BlockUpdate(Hex.Decode("00010203"), 0, 4); + + kmac.DoFinal(res, 0, res.Length); + + Assert.IsTrue(Arrays.AreEqual(Hex.Decode("3B1FBA963CD8B0B59E8C1A6D71888B7143651AF8BA0A7070C0979E2811324AA5"), res)); + + kmac.BlockUpdate(Hex.Decode("00010203"), 0, 4); + + kmac.DoOutput(res, 0, res.Length); + + Assert.IsTrue(Arrays.AreEqual(Hex.Decode("31a44527b4ed9f5c6101d11de6d26f0620aa5c341def41299657fe9df1a3b16c"), res)); + + kmac.DoFinal(res, 0, res.Length); + + Assert.IsTrue(Arrays.AreEqual(Hex.Decode("ffcb48c7620ccd67d1c83224186892cef2f2a99278d5cfdde10e48bdc89718c2"), res), Hex.ToHexString(res)); + } + + private void longBlockTest() + { + byte[] data = new byte[16000]; + byte[] res = new byte[64]; + + for (int i = 0; i != data.Length; i++) + { + data[i] = (byte)i; + } + + for (int i = 10000; i != data.Length; i++) + { + KMac kmac_ = new KMac(128, Arrays.CopyOfRange(data, 0, i)); + + kmac_.Init(new KeyParameter(new byte[0])); + + kmac_.BlockUpdate(Hex.Decode("00010203"), 0, 4); + + kmac_.DoFinal(res, 0); + } + + KMac kmac = new KMac(256, new byte[200]); + + kmac.Init(new KeyParameter(new byte[0])); + + kmac.BlockUpdate(Arrays.CopyOfRange(data, 0, 200), 0, 200); + + kmac.DoFinal(res, 0); + + Assert.IsTrue(Arrays.AreEqual(Hex.Decode("f9476d9b3e42bf23307af5ccb5287fd6f033b23c400566a2ebc5829bd119aa545cd9b6bde76ef61cd31c3c0f0aaf0945f44481e863b19e9c26fb46c8b2a8a9bb"), res), Hex.ToHexString(res)); + } + + private void paddingCheckTest() + { + byte[] data = Hex.Decode("01880204187B3E43EDA8D51EC181D37DDE5B17ECCDD8BE84C268DC6C9500700857"); + byte[] out_ = new byte[32]; + + KMac k128 = new KMac(128, new byte[0]); + k128.Init(new KeyParameter(new byte[163])); + k128.BlockUpdate(data, 0, data.Length); + k128.DoOutput(out_, 0, out_.Length); + + Assert.IsTrue( Arrays.AreEqual(out_, Hex.Decode("6e6ab56468c7445f81c679f89f45c90a95a9c01afbaab5f7065b7e2e96f7d2bb")),"128 failed"); + + KMac k256 = new KMac(256, new byte[0]); + k256.Init(new KeyParameter(new byte[131])); + k256.BlockUpdate(data, 0, data.Length); + k256.DoOutput(out_, 0, out_.Length); + + Assert.IsTrue(Arrays.AreEqual(out_, Hex.Decode("f6302d4f854b4872e811b37993b6bfe027258089b6a9fbb26a755b1ebfc0d830")), "256 failed"); + } + + private void checkKMAC(int bitSize, KMac kmac, byte[] msg) + { + KMac ref_ = new KMac(bitSize, null); + + ref_.Init(new KeyParameter(new byte[0])); + kmac.Init(new KeyParameter(new byte[0])); + + ref_.BlockUpdate(msg, 0, msg.Length); + kmac.BlockUpdate(msg, 0, msg.Length); + + byte[] res1 = new byte[32]; + byte[] res2 = new byte[32]; + + ref_.DoFinal(res1, 0, res1.Length); + kmac.DoFinal(res2, 0, res2.Length); + + Assert.IsTrue(Arrays.AreEqual(res1, res2)); + } + } +} diff --git a/crypto/test/src/tsp/test/NewTspTest.cs b/crypto/test/src/tsp/test/NewTspTest.cs index 6437064c1..dd2f084f2 100644 --- a/crypto/test/src/tsp/test/NewTspTest.cs +++ b/crypto/test/src/tsp/test/NewTspTest.cs @@ -10,7 +10,6 @@ using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Cms; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Operators; -using Org.BouncyCastle.Crypto.Tls; using Org.BouncyCastle.Math; using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.Date; -- cgit 1.4.1