public void StreamSalsaTest() { byte[] secondkey = new byte[32] { 0xdc, 0x90, 0x8d, 0xda, 0x0b, 0x93, 0x44, 0xa9, 0x53, 0x62, 0x9b, 0x73, 0x38, 0x20, 0x77, 0x88, 0x80, 0xf3, 0xce, 0xb4, 0x21, 0xbb, 0x61, 0xb9, 0x1c, 0xbd, 0x4c, 0x3e, 0x66, 0x25, 0x6c, 0xe4 }; byte[] noncesuffix = new byte[8] { 0x82, 0x19, 0xe0, 0x03, 0x6b, 0x7a, 0x0b, 0x37 }; byte[] output = new byte[4000]; StreamSalsa20.Transform(output, noncesuffix, secondkey); StreamSalsa20Xor.Transform(new Span <byte>(output, 0, 4000), new ReadOnlySpan <byte>(output, 0, 4000), noncesuffix, secondkey, 0); for (int i = 0; i < 4000; i++) { Assert.AreEqual(0, output[i]); } }
/// <summary> /// Verifies and decrypts a ciphertext produced by <see> /// <cref>Encrypt</cref> /// </see> /// </summary> /// <remarks> /// Detached mode, some applications may need to store the authentication tag and /// the encrypted message at different locations. /// </remarks> /// <returns>True if successfully verified and decrypted ciphertext.</returns> public bool TryDecrypt(Span <byte> message, ReadOnlySpan <byte> cipher, ReadOnlySpan <byte> mac, ReadOnlySpan <byte> nonce) { Span <byte> block0 = stackalloc byte[64]; Span <byte> subkey = stackalloc byte[Salsa20.KeyLength]; HSalsa20.Transform(subkey, nonce, key, ReadOnlySpan <byte> .Empty); StreamSalsa20.Transform(block0.Slice(0, StreamSalsa20.KeyLength), nonce.Slice(16), subkey); poly1305.SetKey(block0.Slice(0, Poly1305.KeyLength)); if (!poly1305.Verify(mac, cipher)) { poly1305.Reset(); subkey.Clear(); return(false); } int mlen0 = cipher.Length; if (mlen0 > 64 - ZeroBytesLength) { mlen0 = 64 - ZeroBytesLength; } for (int i = 0; i < mlen0; i++) { block0[ZeroBytesLength + i] = cipher[i]; } StreamSalsa20Xor.Transform(block0, block0.Slice(0, ZeroBytesLength + mlen0), nonce.Slice(16), subkey); for (int i = 0; i < mlen0; i++) { message[i] = block0[i + ZeroBytesLength]; } if (cipher.Length > mlen0) { StreamSalsa20Xor.Transform(message.Slice(mlen0), cipher.Slice(mlen0), nonce.Slice(16), subkey, 1UL); } subkey.Clear(); poly1305.Reset(); return(true); }