/// <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()); }