예제 #1
0
        public virtual byte[] Decrypt(ReadOnlySpan <byte> nonce, ReadOnlySpan <byte> ciphertext, ReadOnlySpan <byte> associatedData = default)
        {
            if (ciphertext.Length + nonce.Length < _snuffle.NonceSizeInBytes + Poly1305.MAC_TAG_SIZE_IN_BYTES)
            {
                throw new ArgumentException($"The {nameof(ciphertext)} is too short.");
            }

            if (nonce.IsEmpty || nonce.Length != _snuffle.NonceSizeInBytes)
            {
                throw new ArgumentException(_snuffle.FormatNonceLengthExceptionMessage(_snuffle.GetType().Name, nonce.Length, _snuffle.NonceSizeInBytes));
            }

            var limit = ciphertext.Length - Poly1305.MAC_TAG_SIZE_IN_BYTES;

            try
            {
                Poly1305.VerifyMac(GetMacKey(nonce), GetMacDataRfc8439(associatedData, ciphertext.Slice(0, limit)), ciphertext.Slice(limit, Poly1305.MAC_TAG_SIZE_IN_BYTES));
            }
            catch (Exception ex)
            {
                throw new CryptographicException(AEAD_EXCEPTION_INVALID_TAG, ex);
            }

            return(_snuffle.Decrypt(ciphertext.Slice(0, limit), nonce));
        }
예제 #2
0
        /// <summary>
        /// Decrypts the <paramref name="ciphertext"/> into the <paramref name="plaintext"/> provided destination buffer if the authentication <paramref name="tag"/> can be validated.
        /// </summary>
        /// <param name="nonce">The nonce associated with this message, which must match the value provided during encryption.</param>
        /// <param name="ciphertext">The encrypted content to decrypt.</param>
        /// <param name="tag">The authentication tag produced for this message during encryption.</param>
        /// <param name="plaintext">The byte span to receive the decrypted contents.</param>
        /// <param name="associatedData">Extra data associated with this message, which must match the value provided during encryption.</param>
        /// <exception cref="CryptographicException">The tag value could not be verified, or the decryption operation otherwise failed.</exception>
        public void Decrypt(ReadOnlySpan <byte> nonce, ReadOnlySpan <byte> ciphertext, ReadOnlySpan <byte> tag, Span <byte> plaintext, ReadOnlySpan <byte> associatedData = default)
        {
            if (nonce.IsEmpty || nonce.Length != _snuffle.NonceSizeInBytes)
            {
                throw new ArgumentException(Snuffle.FormatNonceLengthExceptionMessage(_snuffle.GetType().Name, nonce.Length, _snuffle.NonceSizeInBytes));
            }

            try
            {
                var aadPaddedLen        = GetPaddedLength(associatedData, Poly1305.MAC_TAG_SIZE_IN_BYTES);
                var ciphertextPaddedLen = GetPaddedLength(ciphertext, Poly1305.MAC_TAG_SIZE_IN_BYTES);
                var macData             = new Span <byte>(new byte[aadPaddedLen + ciphertextPaddedLen + Poly1305.MAC_TAG_SIZE_IN_BYTES]);

                PrepareMacDataRfc8439(macData, associatedData, aadPaddedLen, ciphertext, ciphertextPaddedLen);
                Poly1305.VerifyMac(GetMacKey(nonce), macData, tag);
            }
            catch (CryptographicException ex) when(ex.Message.Contains("length"))
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new CryptographicException(AEAD_EXCEPTION_INVALID_TAG, ex);
            }

            _snuffle.Decrypt(ciphertext, nonce, plaintext);
        }
예제 #3
0
        public void VerifyMacWhenTagLengthIsEmptyFails()
        {
            // Arrange, Act & Assert
            Action act = () => Poly1305.VerifyMac(new byte[Poly1305.MAC_KEY_SIZE_IN_BYTES], new byte[0], new byte[0]);

            act.Should().Throw <CryptographicException>().WithMessage(EXCEPTION_MESSAGE_TAG_LENGTH);
        }
예제 #4
0
        public void VerifyMacWhenTagLengthIsInvalidFails()
        {
            // Arrange, Act & Assert
            Action act = () => Poly1305.VerifyMac(new byte[Poly1305.MAC_KEY_SIZE_IN_BYTES], new byte[0], new byte[Poly1305.MAC_TAG_SIZE_IN_BYTES + TestHelpers.ReturnRandomPositiveNegative()]);

            act.Should().Throw <CryptographicException>().WithMessage(EXCEPTION_MESSAGE_TAG_LENGTH);
        }
예제 #5
0
        public void VerifyMacWhenKeyLengthIsLessThan32Fails()
        {
            // Arrange, Act & Assert
            Action act = () => Poly1305.VerifyMac(new byte[Poly1305.MAC_KEY_SIZE_IN_BYTES - 1], new byte[0], new byte[0]);

            act.Should().Throw <CryptographicException>();
        }
예제 #6
0
        public void VerifyMacFails()
        {
            // Arrange
            var key = new byte[Poly1305.MAC_KEY_SIZE_IN_BYTES];

            key[0] = 1;

            // Act & Assert
            Assert.Throws <CryptographicException>(() => Poly1305.VerifyMac(key, new byte[] { 1 }, new byte[Poly1305.MAC_TAG_SIZE_IN_BYTES]));
        }
예제 #7
0
        /// <summary>
        /// Decrypts the <paramref name="ciphertext"> into the <paramref name="plaintext"> provided destination buffer if the authentication <paramref name="tag"> can be validated.
        /// </summary>
        /// <param name="nonce">The nonce associated with this message, which must match the value provided during encryption.</param>
        /// <param name="ciphertext">The encrypted content to decrypt.</param>
        /// <param name="tag">The authentication tag produced for this message during encryption.</param>
        /// <param name="plaintext">The byte span to receive the decrypted contents.</param>
        /// <param name="associatedData">Extra data associated with this message, which must match the value provided during encryption.</param>
        /// <exception cref="CryptographicException">The tag value could not be verified, or the decryption operation otherwise failed.</exception>
        public virtual void Decrypt(ReadOnlySpan <byte> nonce, ReadOnlySpan <byte> ciphertext, ReadOnlySpan <byte> tag, Span <byte> plaintext, ReadOnlySpan <byte> associatedData = default)
        {
            if (nonce.IsEmpty || nonce.Length != _snuffle.NonceSizeInBytes)
            {
                throw new ArgumentException(_snuffle.FormatNonceLengthExceptionMessage(_snuffle.GetType().Name, nonce.Length, _snuffle.NonceSizeInBytes));
            }

            try
            {
                Poly1305.VerifyMac(GetMacKey(nonce), GetMacDataRfc8439(associatedData, ciphertext), tag);
            }
            catch (Exception ex)
            {
                throw new CryptographicException(AEAD_EXCEPTION_INVALID_TAG, ex);
            }

            _snuffle.Decrypt(ciphertext, nonce, plaintext);
        }
예제 #8
0
        public void RandomMacTest()
        {
            var rnd = new Random();

            for (var i = 0; i < 1000; i++)
            {
                // Arrange
                var data = new byte[rnd.Next(300)];
                rnd.NextBytes(data);
                var key = new byte[Poly1305.MAC_KEY_SIZE_IN_BYTES];
                rnd.NextBytes(key);

                // Act
                var mac = Poly1305.ComputeMac(key, data);

                // Assert
                Assert.DoesNotThrow(() => Poly1305.VerifyMac(key, data, mac));
            }
        }
예제 #9
0
        public void RandomMacOldMethodSignatureTest()
        {
            var rnd = new Random();

            for (var i = 0; i < 1000; i++)
            {
                // Arrange
                var key = new byte[Poly1305.MAC_KEY_SIZE_IN_BYTES];
                RandomNumberGenerator.Fill(key);

                var data = new byte[rnd.Next(300)];
                rnd.NextBytes(data);

                // Act
                var mac = Poly1305.ComputeMac(key, data);

                // Assert
                Action act = () => Poly1305.VerifyMac(key, data, mac);
                act.Should().NotThrow();
            }
        }
예제 #10
0
 public void VerifyMacWhenKeyLengthIsGreaterThan32Fails()
 {
     // Arrange, Act & Assert
     Assert.Throws <CryptographicException>(() => Poly1305.VerifyMac(new byte[Poly1305.MAC_KEY_SIZE_IN_BYTES + 1], new byte[0], new byte[0]));
 }