示例#1
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");
            }
        }
示例#2
0
        public void PolyReferenceTests(byte[] key, byte[] iv, byte[] data, byte[] expected)
        {
            Poly pmac = new Poly(Common.AesFactory);

            pmac.Init(key, iv, 16);
            pmac.Process(new ArraySegment <byte>(data));
            byte[] mac = pmac.Compute();

            var bcpoly = new Poly1305(new AesEngine());

            bcpoly.Init(new ParametersWithIV(new KeyParameter(key), iv));
            bcpoly.BlockUpdate(data, 0, data.Length);
            byte[] bcmac = new byte[bcpoly.GetMacSize()];
            bcpoly.DoFinal(bcmac, 0);

            var _key      = string.Join(", ", key.Select(b => $"0x{b:x2}"));
            var _iv       = string.Join(", ", iv.Select(b => $"0x{b:x2}"));
            var _data     = string.Join(", ", data.Select(b => $"0x{b:x2}"));
            var _expected = string.Join(", ", bcmac.Select(b => $"0x{b:x2}"));

            Log.Verbose($"[InlineData(new byte[] {{{_key}}}, new byte[] {{{_iv}}}, new byte[] {{{_data}}}, new byte[] {{{_expected}}})]");

            Assert.Equal(expected, mac);
            Assert.Equal(expected, bcmac);
        }
        // Strings are very unsafe to store passwords, or keys in. This is because strings in .NET will always be subject to garbage collection
        // which means they can always be dumped out of memory onto disk through various methods, and exploits. However, especially when dealing
        // with website logins through forms. It's almost impossible to avoid the risk completely. Below are some examples of best dealing with
        // these conditions. Ultimately however, if you can record your secure input directly in byte, char, or SecureString you will always be better off.
        public static void Poly()
        {
            using var poly = new Poly1305(new PinnedMemory <byte>(new byte[] { 63, 61, 77, 20, 63, 61, 77 }, false));
            using var hash = new PinnedMemory <byte>(new byte[poly.GetLength()]);

            var unsafeCaw = "caw caw caw";                                                     // this is unsafe because string's can't be pinned and are subject to garbage collection, and being written to disk (pagefile).
            var caw       = new PinnedMemory <byte>(Encoding.UTF8.GetBytes(unsafeCaw), false); // this is now safe but ONLY the variable caw, unsafeCaw is STILL exposed.

            unsafeCaw = string.Empty;                                                          // unsafeCaw COULD STILL exposed even tho we set it to empty because this depends on garbage collection getting around to clearing it.
            poly.UpdateBlock(caw, 0, caw.Length);
            poly.DoFinal(hash, 0);

            Console.WriteLine(BitConverter.ToString(hash.ToArray()));

            // This is a more uncommon but should be safer example of how to use strings with SecureString for input.
            using var exampleHash2 = new PinnedMemory <byte>(new byte[poly.GetLength()]);

            var secureCaw = new SecureString();

            secureCaw.AppendChar('c');
            secureCaw.AppendChar('a');
            secureCaw.AppendChar('w');
            secureCaw.AppendChar(' ');
            secureCaw.AppendChar('c');
            secureCaw.AppendChar('a');
            secureCaw.AppendChar('w');
            secureCaw.AppendChar(' ');
            secureCaw.AppendChar('c');
            secureCaw.AppendChar('a');
            secureCaw.AppendChar('w');
            secureCaw.MakeReadOnly();

            using var pinnedCaw = new PinnedMemory <char>(new char[secureCaw.Length]);
            var cawPointer = Marshal.SecureStringToBSTR(secureCaw);

            for (var i = 0; i <= secureCaw.Length - 1; i++)
            {
                var c = (char)Marshal.ReadByte(cawPointer, i * 2);
                pinnedCaw[i] = c;
            }

            using var pinnedCawBytes = new PinnedMemory <byte>(Encoding.UTF8.GetBytes(pinnedCaw.ToArray()), false);
            poly.UpdateBlock(pinnedCawBytes, 0, secureCaw.Length);
            poly.DoFinal(exampleHash2, 0);
            Console.WriteLine(BitConverter.ToString(exampleHash2.ToArray()));
        }
示例#4
0
        static bool crypto_aead_chacha20poly1305_ietf_decrypt_detached(Memory <byte> m, ReadOnlyMemory <byte> c, ReadOnlyMemory <byte> mac, ReadOnlyMemory <byte> ad, ReadOnlyMemory <byte> npub, ReadOnlyMemory <byte> k)
        {
            var kk = k._AsSegment();
            var nn = npub._AsSegment();
            var cc = c._AsSegment();
            var aa = ad._AsSegment();
            var mm = m._AsSegment();

            byte[] block0 = new byte[64];

            ChaCha7539Engine ctx = new ChaCha7539Engine();

            ctx.Init(true, new ParametersWithIV(new KeyParameter(kk.Array, kk.Offset, kk.Count), nn.Array, nn.Offset, nn.Count));
            ctx.ProcessBytes(block0, 0, block0.Length, block0, 0);

            Poly1305 state = new Poly1305();

            state.Init(new KeyParameter(block0, 0, AeadChaCha20Poly1305KeySize));

            state.BlockUpdate(aa.Array, aa.Offset, aa.Count);
            if ((aa.Count % 16) != 0)
            {
                state.BlockUpdate(zero15, 0, 16 - (aa.Count % 16));
            }

            state.BlockUpdate(cc.Array, cc.Offset, cc.Count);
            if ((cc.Count % 16) != 0)
            {
                state.BlockUpdate(zero15, 0, 16 - (cc.Count % 16));
            }

            byte[] slen = BitConverter.GetBytes((ulong)aa.Count);
            if (Env.IsBigEndian)
            {
                Array.Reverse(slen);
            }
            state.BlockUpdate(slen, 0, slen.Length);

            byte[] mlen = BitConverter.GetBytes((ulong)cc.Count);
            if (Env.IsBigEndian)
            {
                Array.Reverse(mlen);
            }
            state.BlockUpdate(mlen, 0, mlen.Length);

            byte[] computed_mac = new byte[AeadChaCha20Poly1305MacSize];
            state.DoFinal(computed_mac, 0);

            if (computed_mac.AsSpan().SequenceEqual(mac.Span) == false)
            {
                return(false);
            }

            ctx.ProcessBytes(cc.Array, cc.Offset, cc.Count, mm.Array, mm.Offset);

            return(true);
        }
示例#5
0
        /// <summary>
        /// Branca specification-level token generation
        /// </summary>
        /// <param name="payload">The payload to be encrypted into the Branca token</param>
        /// <param name="key">32-byte private key used to encrypt and decrypt the Branca token</param>
        /// <returns>Base62 encoded Branca Token</returns>
        public virtual string CreateToken(string payload, byte[] key)
        {
            if (string.IsNullOrWhiteSpace(payload))
            {
                throw new ArgumentNullException(nameof(payload));
            }
            if (!IsValidKey(key))
            {
                throw new InvalidOperationException("Invalid encryption key");
            }

            var nonce = new byte[24];

            RandomNumberGenerator.Create().GetBytes(nonce);

            var timestamp = Convert.ToUInt32(DateTimeOffset.UtcNow.ToUnixTimeSeconds());

            // header
            var header = new byte[29];

            using (var stream = new MemoryStream(header))
            {
                // version
                stream.WriteByte(0xBA);

                // timestamp
                stream.Write(BitConverter.GetBytes(timestamp), 0, 4);

                // nonce
                stream.Write(nonce, 0, nonce.Length);
            }

            var keyMaterial = new KeyParameter(key);
            var parameters  = new ParametersWithIV(keyMaterial, nonce);

            var engine = new XChaChaEngine();

            engine.Init(true, parameters);

            var plaintextBytes = Encoding.UTF8.GetBytes(payload);
            var ciphertext     = new byte[plaintextBytes.Length + 16];

            engine.ProcessBytes(plaintextBytes, 0, plaintextBytes.Length, ciphertext, 0);

            var poly = new Poly1305();

            poly.Init(keyMaterial);
            poly.BlockUpdate(header, 0, header.Length);
            poly.DoFinal(ciphertext, plaintextBytes.Length);

            var tokenBytes = new byte[header.Length + ciphertext.Length];

            Buffer.BlockCopy(header, 0, tokenBytes, 0, header.Length);
            Buffer.BlockCopy(ciphertext, 0, tokenBytes, header.Length, ciphertext.Length);

            return(Base62.Encode(tokenBytes));
        }
示例#6
0
        public static void Poly()
        {
            using var poly = new Poly1305(new PinnedMemory <byte>(new byte[] { 63, 61, 77, 20, 63, 61, 77 }, false));
            using var hash = new PinnedMemory <byte>(new byte[poly.GetLength()]);

            // digest.UpdateBlock(new byte[] {63, 61, 77, 20, 63, 61, 77, 20, 63, 61, 77}, 0, 11); // This may be exposed without being pinned.
            poly.UpdateBlock(new PinnedMemory <byte>(new byte[] { 63, 61, 77, 20, 63, 61, 77, 20, 63, 61, 77 }, false), 0, 11);
            poly.DoFinal(hash, 0);

            Console.WriteLine(BitConverter.ToString(hash.ToArray()));
        }
示例#7
0
        private static byte[] CalculateMac(byte[] key, byte[] data)
        {
            var      tag  = new byte[16];
            Poly1305 poly = new Poly1305();

            poly.Init(new KeyParameter(key));
            poly.BlockUpdate(data, 0, data.Length);
            poly.DoFinal(tag, 0);

            return(tag);
        }
示例#8
0
        private void CheckVector(byte[] keyMaterial, byte[] input, byte[] tag)
        {
            Poly1305 poly1305 = new Poly1305();

            poly1305.Init(new KeyParameter(keyMaterial));

            poly1305.BlockUpdate(input, 0, input.Length);

            byte[] mac = new byte[poly1305.GetMacSize()];

            poly1305.DoFinal(mac, 0);

            if (!Arrays.AreEqual(tag, mac))
            {
                Fail("rfc7539", Hex.ToHexString(tag), Hex.ToHexString(mac));
            }
        }
        private byte[] CalcMac(byte[] key, byte[] nonce, byte[] cipherText, byte[] ad)
        {
            var mac     = new Poly1305();
            var polyKey = EncryptOrDecrypt(true, new byte[32], key, nonce, false);

            mac.Init(new KeyParameter(polyKey));
            mac.BlockUpdate(ad, 0, ad.Length);
            Pad(mac, ad.Length);
            mac.BlockUpdate(cipherText, 0, cipherText.Length);
            Pad(mac, cipherText.Length);
            WriteLE(mac, ad.Length);
            WriteLE(mac, cipherText.Length);
            var tag       = new byte[16];
            var macreslen = mac.DoFinal(tag, 0);

            Debug.Assert(macreslen == 16);
            return(tag);
        }
示例#10
0
        private byte[] EncryptXSalsa20Poly1305(byte[] bytes, byte[] key, byte[] nonce)
        {
            var salsa = new XSalsa20Engine();
            var poly  = new Poly1305();

            salsa.Init(true, new ParametersWithIV(new KeyParameter(key), nonce));

            byte[] subKey = new byte[key.Length];
            salsa.ProcessBytes(subKey, 0, key.Length, subKey, 0);

            byte[] output = new byte[bytes.Length + poly.GetMacSize()];

            salsa.ProcessBytes(bytes, 0, bytes.Length, output, poly.GetMacSize());

            poly.Init(new KeyParameter(subKey));
            poly.BlockUpdate(output, poly.GetMacSize(), bytes.Length);
            poly.DoFinal(output, 0);

            return(output);
        }
示例#11
0
        public void BasicPolyTests(int ivBytes, int dataBytes, int macSize)
        {
            RandomNumberGenerator rng = new RandomNumberGenerator();

            byte[] iv   = rng.Generate(ivBytes);
            byte[] key  = rng.Generate(32);
            byte[] data = rng.Generate(dataBytes);

            Poly pmac   = new Poly(Common.AesFactory);
            var  bcpoly = new Poly1305(new AesEngine());

            pmac.Init(key, iv, macSize);
            bcpoly.Init(new ParametersWithIV(new KeyParameter(key), iv));
            pmac.Process(new ArraySegment <byte>(data));
            byte[] mac = pmac.Compute();

            bcpoly.BlockUpdate(data, 0, data.Length);
            byte[] bcmac = new byte[bcpoly.GetMacSize()];
            bcpoly.DoFinal(bcmac, 0);
            bcmac = bcmac.Take(macSize).ToArray();

            Assert.Equal(bcmac, mac);
        }
示例#12
0
        public void PolyReuseKeyTest(int ivBytes, int dataBytes, int macSize)
        {
            RandomNumberGenerator rng = new RandomNumberGenerator();

            byte[] iv    = rng.Generate(ivBytes);
            byte[] key   = rng.Generate(32);
            byte[] data1 = rng.Generate(dataBytes);
            byte[] data2 = rng.Generate(dataBytes);

            var pmac = new Poly(Common.AesFactory);

            pmac.Init(key, iv, macSize);
            pmac.Process(new ArraySegment <byte>(data1));
            byte[] mac1 = pmac.Compute();
            pmac.Init(key, iv, macSize);
            pmac.Process(new ArraySegment <byte>(data2));
            byte[] mac2 = pmac.Compute();

            var bcpoly1 = new Poly1305(new AesEngine());

            bcpoly1.Init(new ParametersWithIV(new KeyParameter(key), iv));
            bcpoly1.BlockUpdate(data1, 0, data1.Length);
            byte[] bcmac1 = new byte[bcpoly1.GetMacSize()];
            bcpoly1.DoFinal(bcmac1, 0);
            bcmac1 = bcmac1.Take(macSize).ToArray();

            var bcpoly2 = new Poly1305(new AesEngine());

            bcpoly2.Init(new ParametersWithIV(new KeyParameter(key), iv));
            bcpoly2.BlockUpdate(data2, 0, data2.Length);
            byte[] bcmac2 = new byte[bcpoly2.GetMacSize()];
            bcpoly2.DoFinal(bcmac2, 0);
            bcmac2 = bcmac2.Take(macSize).ToArray();

            Assert.Equal(bcmac1, mac1);
            Assert.Equal(bcmac2, mac2);
        }
示例#13
0
        public static void SelfTest()
        {
            byte[] key = new byte[] {
                0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a, 0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0,
                0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09, 0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0
            };

            byte[] nonce = new byte[] {
                0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
            };

            byte[] cipherText = new byte[] {
                0x64, 0xa0, 0x86, 0x15, 0x75, 0x86, 0x1a, 0xf4, 0x60, 0xf0, 0x62, 0xc7, 0x9b, 0xe6, 0x43, 0xbd,
                0x5e, 0x80, 0x5c, 0xfd, 0x34, 0x5c, 0xf3, 0x89, 0xf1, 0x08, 0x67, 0x0a, 0xc7, 0x6c, 0x8c, 0xb2,
                0x4c, 0x6c, 0xfc, 0x18, 0x75, 0x5d, 0x43, 0xee, 0xa0, 0x9e, 0xe9, 0x4e, 0x38, 0x2d, 0x26, 0xb0,
                0xbd, 0xb7, 0xb7, 0x3c, 0x32, 0x1b, 0x01, 0x00, 0xd4, 0xf0, 0x3b, 0x7f, 0x35, 0x58, 0x94, 0xcf,
                0x33, 0x2f, 0x83, 0x0e, 0x71, 0x0b, 0x97, 0xce, 0x98, 0xc8, 0xa8, 0x4a, 0xbd, 0x0b, 0x94, 0x81,
                0x14, 0xad, 0x17, 0x6e, 0x00, 0x8d, 0x33, 0xbd, 0x60, 0xf9, 0x82, 0xb1, 0xff, 0x37, 0xc8, 0x55,
                0x97, 0x97, 0xa0, 0x6e, 0xf4, 0xf0, 0xef, 0x61, 0xc1, 0x86, 0x32, 0x4e, 0x2b, 0x35, 0x06, 0x38,
                0x36, 0x06, 0x90, 0x7b, 0x6a, 0x7c, 0x02, 0xb0, 0xf9, 0xf6, 0x15, 0x7b, 0x53, 0xc8, 0x67, 0xe4,
                0xb9, 0x16, 0x6c, 0x76, 0x7b, 0x80, 0x4d, 0x46, 0xa5, 0x9b, 0x52, 0x16, 0xcd, 0xe7, 0xa4, 0xe9,
                0x90, 0x40, 0xc5, 0xa4, 0x04, 0x33, 0x22, 0x5e, 0xe2, 0x82, 0xa1, 0xb0, 0xa0, 0x6c, 0x52, 0x3e,
                0xaf, 0x45, 0x34, 0xd7, 0xf8, 0x3f, 0xa1, 0x15, 0x5b, 0x00, 0x47, 0x71, 0x8c, 0xbc, 0x54, 0x6a,
                0x0d, 0x07, 0x2b, 0x04, 0xb3, 0x56, 0x4e, 0xea, 0x1b, 0x42, 0x22, 0x73, 0xf5, 0x48, 0x27, 0x1a,
                0x0b, 0xb2, 0x31, 0x60, 0x53, 0xfa, 0x76, 0x99, 0x19, 0x55, 0xeb, 0xd6, 0x31, 0x59, 0x43, 0x4e,
                0xce, 0xbb, 0x4e, 0x46, 0x6d, 0xae, 0x5a, 0x10, 0x73, 0xa6, 0x72, 0x76, 0x27, 0x09, 0x7a, 0x10,
                0x49, 0xe6, 0x17, 0xd9, 0x1d, 0x36, 0x10, 0x94, 0xfa, 0x68, 0xf0, 0xff, 0x77, 0x98, 0x71, 0x30,
                0x30, 0x5b, 0xea, 0xba, 0x2e, 0xda, 0x04, 0xdf, 0x99, 0x7b, 0x71, 0x4d, 0x6c, 0x6f, 0x2c, 0x29,
                0xa6, 0xad, 0x5c, 0xb4, 0x02, 0x2b, 0x02, 0x70, 0x9b,
                0xee, 0xad, 0x9d, 0x67, 0x89, 0x0c, 0xbb, 0x22, 0x39, 0x23, 0x36, 0xfe, 0xa1, 0x85, 0x1f, 0x38
            };

            byte[] aad = new byte[] {
                0xf3, 0x33, 0x88, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x91
            };

            byte[] plainText = new byte[] {
                0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x73, 0x20,
                0x61, 0x72, 0x65, 0x20, 0x64, 0x72, 0x61, 0x66, 0x74, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65,
                0x6e, 0x74, 0x73, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20,
                0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x69, 0x78, 0x20, 0x6d,
                0x6f, 0x6e, 0x74, 0x68, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65,
                0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x2c, 0x20, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63,
                0x65, 0x64, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x6f, 0x62, 0x73, 0x6f, 0x6c, 0x65, 0x74, 0x65, 0x64,
                0x20, 0x62, 0x79, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65,
                0x6e, 0x74, 0x73, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x2e,
                0x20, 0x49, 0x74, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x70, 0x72,
                0x69, 0x61, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65,
                0x72, 0x6e, 0x65, 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x73, 0x20, 0x61, 0x73, 0x20, 0x72,
                0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61,
                0x6c, 0x20, 0x6f, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x69, 0x74, 0x65, 0x20, 0x74, 0x68, 0x65,
                0x6d, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x61, 0x73, 0x20,
                0x2f, 0xe2, 0x80, 0x9c, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x72, 0x6f, 0x67,
                0x72, 0x65, 0x73, 0x73, 0x2e, 0x2f, 0xe2, 0x80, 0x9d
            };

            Poly1305 p = new Poly1305();

            byte[]       pKey    = new byte[] { 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8, 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b };
            KeyParameter paramsX = new KeyParameter(pKey);

            p.Init(paramsX);

            byte[] msg = UTF8Encoding.ASCII.GetBytes("Cryptographic Forum Research Group");
            p.BlockUpdate(msg, 0, msg.Length);
            byte[] output = new byte[30];
            p.DoFinal(output, 0);


            ChaCha20Poly1305 cipher = new ChaCha20Poly1305();

            KeyParameter   ContentKey = new KeyParameter(key);
            AeadParameters parameters = new AeadParameters(ContentKey, 128, nonce, aad);

            cipher.Init(true, parameters);

            byte[] C   = new byte[cipher.GetOutputSize(plainText.Length)];
            int    len = cipher.ProcessBytes(plainText, 0, plainText.Length, C, 0);

            len += cipher.DoFinal(C, len);
        }
示例#14
0
        public int DoFinal(byte[] output, int outOff)
        {
            byte[] zeros;

            if (data.Length + aadLength == 0)
            {
                InitCipher();
            }

            int extra = (int)data.Length;

            if (forEncryption)
            {
                // Check.OutputLength(output, outOff, bufOff, extra + macSize, "Output buffer too short");
            }
            else
            {
                if (extra < macSize)
                {
                    throw new InvalidCipherTextException("data too short");
                }

                extra -= macSize;

                // Check.OutputLength(output, outOff, extra, "Output buffer too short");
            }

            //  Pad out the AD

            zeros = new byte[16 - (aadLength % 16)];
            if (zeros.Length != 16)
            {
                poly.BlockUpdate(zeros, 0, zeros.Length);
            }

            chacha20.ProcessBytes(data.GetBuffer(), 0, extra, output, outOff);

            if (forEncryption)
            {
                poly.BlockUpdate(output, outOff, extra);
            }
            else
            {
                poly.BlockUpdate(data.GetBuffer(), 0, extra);
            }

            int resultLen = 0;

            zeros = new byte[16 - (extra % 16)];
            if (zeros.Length != 16)
            {
                poly.BlockUpdate(zeros, 0, zeros.Length);
            }

            byte[] lengths = BitConverter.GetBytes((Int64)aadLength);
            poly.BlockUpdate(lengths, 0, lengths.Length);
            lengths = BitConverter.GetBytes((Int64)extra);
            poly.BlockUpdate(lengths, 0, lengths.Length);

            macResult = new byte[macSize];
            if (poly.DoFinal(macResult, 0) != macResult.Length)
            {
                throw new Exception("Internal Error");
            }

            if (forEncryption)
            {
                resultLen = extra + macSize;
                Array.Copy(macResult, 0, output, extra + outOff, macSize);
            }
            else
            {
                bool f = true;
                for (int i = 0; i < macSize; i++)
                {
                    f &= (macResult[i] == data.GetBuffer()[extra + i]);
                }
                if (!f)
                {
                    throw new Exception("Authentication Failed");
                }
                resultLen = extra;
            }

            Reset(false);

            return(resultLen);
        }
示例#15
0
        /// <summary>
        /// Branca specification level token decryption.
        /// </summary>
        /// <param name="token">Base62 encoded Branca token</param>
        /// <param name="key">32-byte private key used to encrypt and decrypt the Branca token</param>
        /// <returns>Pared and decrypted Branca Token</returns>
        public virtual BrancaToken DecryptToken(string token, byte[] key)
        {
            if (string.IsNullOrWhiteSpace(token))
            {
                throw new ArgumentNullException(nameof(token));
            }
            if (!CanReadToken(token))
            {
                throw new InvalidCastException("Unable to read token");
            }
            if (!IsValidKey(key))
            {
                throw new InvalidOperationException("Invalid decryption key");
            }

            var tokenBytes = Base62.Decode(token);

            using (var stream = new MemoryStream(tokenBytes, false))
            {
                // header
                var header = GuaranteedRead(stream, 29);

                byte[] nonce;
                uint   timestamp;
                using (var headerStream = new MemoryStream(header))
                {
                    // version
                    var version = headerStream.ReadByte();
                    if (version != 0xBA)
                    {
                        throw new SecurityTokenException("Unsupported Branca version");
                    }

                    // timestamp
                    var timestampBytes = GuaranteedRead(headerStream, 4);
                    timestamp = BitConverter.ToUInt32(timestampBytes, 0);

                    // nonce
                    nonce = GuaranteedRead(headerStream, 24);
                }

                // ciphertext
                var ciphertextLength = (stream.Length - 16) - stream.Position;
                var ciphertext       = GuaranteedRead(stream, (int)ciphertextLength);

                // tag
                var tag = GuaranteedRead(stream, 16);

                // XChaCha20-Poly1305
                var keyMaterial = new KeyParameter(key);
                var parameters  = new ParametersWithIV(keyMaterial, nonce);

                var headerMac = new byte[16];
                var poly1305  = new Poly1305();
                poly1305.Init(keyMaterial);
                poly1305.BlockUpdate(header, 0, header.Length);
                poly1305.DoFinal(headerMac, 0);

                if (!headerMac.SequenceEqual(tag))
                {
                    throw new SecurityTokenException("Invalid message authentication code");
                }

                var engine = new XChaChaEngine();
                engine.Init(false, parameters);
                var decryptedPlaintext = new byte[ciphertext.Length];
                engine.ProcessBytes(ciphertext, 0, ciphertext.Length, decryptedPlaintext, 0);

                return(new BrancaToken(
                           Encoding.UTF8.GetString(decryptedPlaintext),
                           timestamp));
            }
        }
示例#16
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));
            }
        }