Example #1
0
        /// <summary>
        /// Transforms the specified region of the data array and copies the resulting transform to the specified region of the destination array.
        /// </summary>
        /// <param name="data"></param>
        /// <param name="dataOffset"></param>
        /// <param name="dataCount"></param>
        /// <param name="destination"></param>
        /// <param name="destinationOffset"></param>
        public int TransformBlock(byte[] data, int dataOffset, int dataCount, byte[] destination, int destinationOffset)
        {
            var dataBuffer          = data.AsSpan(dataOffset);
            var destinationBuffer   = destination.AsSpan(destinationOffset);
            var keyStreamBuffer     = (Span <byte>) stackalloc byte[ChaCha.BlockLength];
            var keyStreamPosition   = m_iv;
            var numBytesTransformed = 0;

            while (ChaCha.BlockLength <= dataCount)
            {
                var destinationBufferSlice = destinationBuffer.Slice(numBytesTransformed, ChaCha.BlockLength);

                dataBuffer.Slice(numBytesTransformed, ChaCha.BlockLength).CopyTo(destinationBufferSlice);
                ChaCha.WriteKeyStreamBlock(m_state, checked (keyStreamPosition++), m_numRounds, keyStreamBuffer);
                Operations.Xor(keyStreamBuffer, destinationBufferSlice);

                dataCount           -= ChaCha.BlockLength;
                numBytesTransformed += ChaCha.BlockLength;
            }

            if (0 < dataCount)
            {
                var destinationBufferSlice = destinationBuffer.Slice(numBytesTransformed, dataCount);

                dataBuffer.Slice(numBytesTransformed, dataCount).CopyTo(destinationBufferSlice);
                ChaCha.WriteKeyStreamBlock(m_state, checked (keyStreamPosition++), m_numRounds, keyStreamBuffer);
                Operations.Xor(keyStreamBuffer.Slice(0, dataCount), destinationBufferSlice);

                numBytesTransformed += dataCount;
            }

            m_iv = keyStreamPosition;

            return(numBytesTransformed);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="AeadChaCha20Poly1305"/> class.
        /// </summary>
        /// <param name="key">The secret that will be used during initialization.</param>
        /// <param name="nonce">The one-time use state parameter.</param>
        /// <param name="aad">The arbitrary length additional authenticated data parameter.</param>
        public AeadChaCha20Poly1305(ReadOnlySpan <byte> key, ReadOnlySpan <byte> nonce, ReadOnlySpan <byte> aad)
        {
            var ivLow      = 0U;
            var ivHigh     = BinaryPrimitives.ReadUInt32LittleEndian(nonce);
            var oneTimeKey = new byte[64];

            ChaCha.WriteKeyStreamBlock(ChaCha.Initialize(key, nonce, ivLow), Operations.ConcatBits(ivHigh, ivLow), 20U, oneTimeKey);

            m_aad      = aad.ToArray();
            m_chaCha20 = ChaCha20.New(key, nonce, 1U);
            m_poly1305 = Poly1305.New(oneTimeKey.AsSpan(0, 32).ToArray());
        }