/// <summary>
        /// When overridden in a derived class, writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written.
        /// </summary>
        /// <param name="buffer">An array of bytes. This method copies <paramref name="count"/> bytes from <paramref name="buffer"/> to the current stream.</param>
        /// <param name="offset">The zero-based byte offset in <paramref name="buffer"/> at which to begin copying bytes to the current stream.</param>
        /// <param name="count">The number of bytes to be written to the current stream.</param>
        /// <exception cref="T:System.ArgumentException">The sum of <paramref name="offset"/> and <paramref name="count"/> is greater than the buffer length. </exception>
        /// <exception cref="T:System.ArgumentNullException">
        ///     <paramref name="buffer"/> is null. </exception>
        /// <exception cref="T:System.ArgumentOutOfRangeException">
        ///     <paramref name="offset"/> or <paramref name="count"/> is negative. </exception>
        /// <exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
        /// <exception cref="T:System.NotSupportedException">The stream does not support writing. </exception>
        /// <exception cref="T:System.ObjectDisposedException">Methods were called after the stream was closed. </exception>
        public override void Write(byte[] buffer, int offset, int count)
        {
            if (!_init)
            {
                if (_encrypt)
                {
                    _output.Write(_nonce, 0, _nonce.Length);
                }
                else
                {
                    Array.Copy(buffer, 0, _nonce, 0, _nonce.Length);

                    offset = offset + _nonce.Length;
                    count  = count - _nonce.Length;
                }
                _initFunc(_nonce, _cipher, _header, _encrypt);
                _init = true;
            }

            var outBuffer = new byte[_cipher.GetUpdateOutputSize(count)];
            var outLen    = _cipher.ProcessBytes(buffer, offset, count, outBuffer, 0);

            _output.Write(outBuffer, 0, outLen);
            Secure.Clear(outBuffer);
            _outLen += outLen;
            _inLen  += count;
        }
Exemple #2
0
        private void OutputSizeTests()
        {
            byte[] K  = new byte[16];
            byte[] A  = null;
            byte[] IV = new byte[15];

            AeadParameters   parameters = new AeadParameters(new KeyParameter(K), 16 * 8, IV, A);
            IAeadBlockCipher cipher     = InitOcbCipher(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");
            }
        }
Exemple #3
0
 /**
  * return the size of the output buffer required for an update
  * an input of len bytes.
  *
  * @param len the length of the input.
  * @return the space required to accommodate a call to update
  * with len bytes of input.
  */
 public override int GetUpdateOutputSize(
     int length)
 {
     return(cipher.GetUpdateOutputSize(length));
 }
Exemple #4
0
        private void RandomTest(SecureRandom srng)
        {
            int kLength = 16 + 8 * (System.Math.Abs(srng.NextInt()) % 3);

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

            int pLength = (int)((uint)srng.NextInt() >> 16);

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

            int aLength = (int)((uint)srng.NextInt() >> 24);

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

            int saLength = (int)((uint)srng.NextInt() >> 24);

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

            int ivLength = 1 + NextInt(srng, 15);

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

            AeadParameters   parameters = new AeadParameters(new KeyParameter(K), 16 * 8, IV, A);
            IAeadBlockCipher cipher     = InitOcbCipher(true, parameters);

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

            int split = NextInt(srng, 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 = 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);

            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");
            }
        }
 public int GetUpdateOutputSize(int inputLen)
 {
     return(cipher.GetUpdateOutputSize(inputLen));
 }