public override void Write(byte[] buffer, int offset, int count)
        {
            byte[] output    = new byte[cipher.GetUpdateOutputSize(count)];
            int    encrypted = cipher.ProcessBytes(buffer, offset, count, output, 0);

            base.Write(output, 0, encrypted);
        }
        public byte[] EncryptName(byte[] input, int paddedLength)
        {
            try
            {
                byte[] inputPadded = new byte[paddedLength];

                if (input.Length > inputPadded.Length)
                {
                    throw new ArgumentException($"Input is too long: {Encoding.UTF8.GetString(input)}");
                }

                Array.Copy(input, 0, inputPadded, 0, input.Length);

                byte[] nonce = Util.GetSecretBytes(12);

                GcmBlockCipher cipher = new GcmBlockCipher(new AesEngine());
                cipher.Init(true, new AeadParameters(new KeyParameter(key), 128, nonce));

                byte[] ciphertext = new byte[cipher.GetUpdateOutputSize(inputPadded.Length)];
                cipher.ProcessBytes(inputPadded, 0, inputPadded.Length, ciphertext, 0);

                byte[] tag = new byte[cipher.GetOutputSize(0)];
                cipher.DoFinal(tag, 0);

                return(ByteUtil.combine(nonce, ciphertext, tag));
            }
            catch (InvalidCipherTextException ex)
            {
                throw new ArgumentException(null, ex);
            }
        }
        internal static AesEncryptedResult Encrypt(byte[] key, byte[]?aad, byte[] requestData)
        {
            try
            {
                byte[] iv     = Util.GetSecretBytes(12);
                var    cipher = new GcmBlockCipher(new AesEngine());
                cipher.Init(true, new AeadParameters(new KeyParameter(key), TAG_LENGTH_BITS, iv));
                if (aad != null)
                {
                    cipher.ProcessAadBytes(aad, 0, aad.Length);
                }

                byte[] cipherText1 = new byte[cipher.GetUpdateOutputSize(requestData.Length)];
                cipher.ProcessBytes(requestData, 0, requestData.Length, cipherText1, 0);

                byte[] cipherText2 = new byte[cipher.GetOutputSize(0)];
                cipher.DoFinal(cipherText2, 0);

                byte[]   cipherText = ByteUtil.combine(cipherText1, cipherText2);
                byte[][] parts      = ByteUtil.split(cipherText, cipherText.Length - TAG_LENGTH_BYTES, TAG_LENGTH_BYTES);

                return(new AesEncryptedResult(iv, parts[0], parts[1], aad));
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException(null, ex);
            }
        }
        internal static byte[] Decrypt(byte[] key, byte[] iv, byte[] ciphertext, byte[] tag)
        {
            var cipher = new GcmBlockCipher(new AesEngine());

            cipher.Init(false, new AeadParameters(new KeyParameter(key), TAG_LENGTH_BITS, iv));

            byte[] combined      = ByteUtil.combine(ciphertext, tag);
            byte[] cipherTextOne = new byte[cipher.GetUpdateOutputSize(combined.Length)];
            cipher.ProcessBytes(combined, 0, combined.Length, cipherTextOne, 0);

            byte[] cipherTextTwo = new byte[cipher.GetOutputSize(0)];
            cipher.DoFinal(cipherTextTwo, 0);
            return(ByteUtil.combine(cipherTextOne, cipherTextTwo));
        }
Beispiel #5
0
        private void OutputSizeTests()
        {
            byte[] K  = new byte[16];
            byte[] A  = null;
            byte[] IV = new byte[16];

            AeadParameters parameters = new AeadParameters(new KeyParameter(K), 16 * 8, IV, A);
            GcmBlockCipher cipher     = InitCipher(null, true, parameters);

            if (cipher.GetUpdateOutputSize(0) != 0)
            {
                Fail("incorrect getUpdateOutputSize for initial 0 bytes encryption");
            }

            if (cipher.GetOutputSize(0) != 16)
            {
                Fail("incorrect getOutputSize for initial 0 bytes encryption");
            }

            cipher.Init(false, parameters);

            if (cipher.GetUpdateOutputSize(0) != 0)
            {
                Fail("incorrect getUpdateOutputSize for initial 0 bytes decryption");
            }

            // NOTE: 0 bytes would be truncated data, but we want it to fail in the doFinal, not here
            if (cipher.GetOutputSize(0) != 0)
            {
                Fail("fragile getOutputSize for initial 0 bytes decryption");
            }

            if (cipher.GetOutputSize(16) != 0)
            {
                Fail("incorrect getOutputSize for initial MAC-size bytes decryption");
            }
        }
        public static byte[] DeriveAccessKeyFrom(byte[] profileKey)
        {
            byte[] nonce  = new byte[12];
            byte[] input  = new byte[16];
            var    cipher = new GcmBlockCipher(new AesEngine());

            cipher.Init(false, new AeadParameters(new KeyParameter(profileKey), 128, nonce));

            byte[] ciphertext = new byte[cipher.GetUpdateOutputSize(input.Length)];
            cipher.ProcessBytes(input, 0, input.Length, ciphertext, 0);

            byte[] tag = new byte[cipher.GetOutputSize(0)];
            cipher.DoFinal(tag, 0);

            byte[] combined = ByteUtil.combine(ciphertext, tag);
            return(ByteUtil.trim(combined, 16));
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="InvalidCiphertextException"></exception>
        public byte[] DecryptName(byte[] input)
        {
            try
            {
                if (input.Length < 12 + 16 + 1)
                {
                    throw new InvalidCipherTextException($"Too short: {input.Length}");
                }

                byte[] nonce = new byte[12];
                Array.Copy(input, 0, nonce, 0, nonce.Length);

                GcmBlockCipher cipher = new GcmBlockCipher(new AesEngine());
                cipher.Init(false, new AeadParameters(new KeyParameter(key), 128, nonce));

                byte[] paddedPlaintextOne = new byte[cipher.GetUpdateOutputSize(input.Length - 12)];
                cipher.ProcessBytes(input, 12, input.Length - 12, paddedPlaintextOne, 0);

                byte[] paddedPlaintextTwo = new byte[cipher.GetOutputSize(0)];
                cipher.DoFinal(paddedPlaintextTwo, 0);

                byte[] paddedPlaintext = ByteUtil.combine(paddedPlaintextOne, paddedPlaintextTwo);
                int    plaintextLength = 0;

                for (int i = paddedPlaintext.Length - 1; i >= 0; i--)
                {
                    if (paddedPlaintext[i] != 0x00)
                    {
                        plaintextLength = i + 1;
                        break;
                    }
                }

                byte[] plaintext = new byte[plaintextLength];
                Array.Copy(paddedPlaintext, 0, plaintext, 0, plaintextLength);

                return(plaintext);
            }
            catch (InvalidCipherTextException ex)
            {
                throw new InvalidCiphertextException(ex);
            }
        }
Beispiel #8
0
        private void RandomTest(SecureRandom srng, IGcmMultiplier m)
        {
            int kLength = 16 + 8 * srng.Next(3);

            byte[] K = new byte[kLength];
            srng.NextBytes(K);

            int pLength = srng.Next(65536);

            byte[] P = new byte[pLength];
            srng.NextBytes(P);

            int aLength = srng.Next(256);

            byte[] A = new byte[aLength];
            srng.NextBytes(A);

            int saLength = srng.Next(256);

            byte[] SA = new byte[saLength];
            srng.NextBytes(SA);

            int ivLength = 1 + srng.Next(256);

            byte[] IV = new byte[ivLength];
            srng.NextBytes(IV);

            AeadParameters parameters = new AeadParameters(new KeyParameter(K), 16 * 8, IV, A);
            GcmBlockCipher cipher     = InitCipher(m, true, parameters);

            byte[] C         = new byte[cipher.GetOutputSize(P.Length)];
            int    predicted = cipher.GetUpdateOutputSize(P.Length);

            int split = srng.Next(SA.Length + 1);

            cipher.ProcessAadBytes(SA, 0, split);
            int len = cipher.ProcessBytes(P, 0, P.Length, C, 0);

            cipher.ProcessAadBytes(SA, split, SA.Length - split);

            if (predicted != len)
            {
                Fail("encryption reported incorrect update length in randomised test");
            }

            len += cipher.DoFinal(C, len);

            if (C.Length != len)
            {
                Fail("encryption reported incorrect length in randomised test");
            }

            byte[] encT = cipher.GetMac();
            byte[] tail = new byte[C.Length - P.Length];
            Array.Copy(C, P.Length, tail, 0, tail.Length);

            if (!AreEqual(encT, tail))
            {
                Fail("stream contained wrong mac in randomised test");
            }

            cipher.Init(false, parameters);
            byte[] decP = new byte[cipher.GetOutputSize(C.Length)];
            predicted = cipher.GetUpdateOutputSize(C.Length);

            split = srng.Next(SA.Length + 1);
            cipher.ProcessAadBytes(SA, 0, split);
            len = cipher.ProcessBytes(C, 0, C.Length, decP, 0);
            cipher.ProcessAadBytes(SA, split, SA.Length - split);

            if (predicted != len)
            {
                Fail("decryption reported incorrect update length in randomised test");
            }

            len += cipher.DoFinal(decP, len);

            if (!AreEqual(P, decP))
            {
                Fail("incorrect decrypt in randomised test");
            }

            byte[] decT = cipher.GetMac();
            if (!AreEqual(encT, decT))
            {
                Fail("decryption produced different mac from encryption");
            }

            //
            // key reuse test
            //
            cipher.Init(false, AeadTestUtilities.ReuseKey(parameters));
            decP = new byte[cipher.GetOutputSize(C.Length)];

            split = NextInt(srng, SA.Length + 1);
            cipher.ProcessAadBytes(SA, 0, split);
            len = cipher.ProcessBytes(C, 0, C.Length, decP, 0);
            cipher.ProcessAadBytes(SA, split, SA.Length - split);

            len += cipher.DoFinal(decP, len);

            if (!AreEqual(P, decP))
            {
                Fail("incorrect decrypt in randomised test");
            }

            decT = cipher.GetMac();
            if (!AreEqual(encT, decT))
            {
                Fail("decryption produced different mac from encryption");
            }
        }