/// <inheritsdoc /> public override bool Verify(ReadOnlySpan <byte> input, ReadOnlySpan <byte> signature) { Debug.Assert(!_disposed); Span <byte> hash = stackalloc byte[Sha2.HashSizeStackallocThreshold].Slice(0, _hashSizeInBytes); _hashAlgorithm.ComputeHash(input, hash); return(CryptographicOperations.FixedTimeEquals(signature, hash)); }
private bool VerifyAuthenticationTag(ReadOnlySpan <byte> key, ReadOnlySpan <byte> iv, ReadOnlySpan <byte> associatedData, ReadOnlySpan <byte> ciphertext, ReadOnlySpan <byte> authenticationTag) { int tagSize = GetTagSize(); if (authenticationTag.Length != tagSize) { return(false); } byte[]? byteArrayToReturnToPool = null; int macLength = associatedData.Length + iv.Length + ciphertext.Length + sizeof(long); Span <byte> macBytes = macLength > Constants.MaxStackallocBytes ? (byteArrayToReturnToPool = ArrayPool <byte> .Shared.Rent(macLength)) : stackalloc byte[Constants.MaxStackallocBytes]; try { macBytes = macBytes.Slice(0, macLength); associatedData.CopyTo(macBytes); var bytes = macBytes.Slice(associatedData.Length); iv.CopyTo(bytes); bytes = bytes.Slice(iv.Length); ciphertext.CopyTo(bytes); bytes = bytes.Slice(ciphertext.Length); BinaryPrimitives.WriteInt64BigEndian(bytes, associatedData.Length << 3); Sha2 hashAlgorithm = _encryptionAlgorithm.SignatureAlgorithm.Sha; Span <byte> hmacKey = stackalloc byte[Sha2.BlockSizeStackallocThreshold * 2] .Slice(0, hashAlgorithm.BlockSize * 2); Hmac hmac = new Hmac(hashAlgorithm, key, hmacKey); Span <byte> hash = stackalloc byte[AuthenticatedEncryptor.TagSizeStackallocThreshold] .Slice(0, authenticationTag.Length * 2); hmac.ComputeHash(macBytes, hash); CryptographicOperations.ZeroMemory(hmacKey); return(CryptographicOperations.FixedTimeEquals(authenticationTag, hash.Slice(0, tagSize))); } finally { if (byteArrayToReturnToPool != null) { ArrayPool <byte> .Shared.Return(byteArrayToReturnToPool); } } }
public static void EmptyReturnTrue() { int byteLength = 0; byte[] rented = ArrayPool <byte> .Shared.Rent(byteLength); Span <byte> testSpan = new Span <byte>(rented, 0, byteLength); Fill(rented, 0, byteLength); ReadOnlySpan <byte> emptySpan = ReadOnlySpan <byte> .Empty; bool isEqualA = CryptographicOperations.FixedTimeEquals(testSpan, emptySpan); bool isEqualB = CryptographicOperations.FixedTimeEquals(emptySpan, testSpan); ArrayPool <byte> .Shared.Return(rented); Assert.True(isEqualA, "FixedTimeEquals(testSpan, emptySpan)"); Assert.True(isEqualB, "FixedTimeEquals(emptySpan, testSpan)"); }
public static void EqualReturnsTrue(int byteLength) { byte[] rented = ArrayPool <byte> .Shared.Rent(byteLength); Span <byte> testSpan = new Span <byte>(rented, 0, byteLength); Fill(rented, 0, byteLength); byte[] rented2 = ArrayPool <byte> .Shared.Rent(byteLength); Span <byte> testSpan2 = new Span <byte>(rented2, 0, byteLength); testSpan.CopyTo(testSpan2); bool isEqual = CryptographicOperations.FixedTimeEquals(testSpan, testSpan2); ArrayPool <byte> .Shared.Return(rented); ArrayPool <byte> .Shared.Return(rented2); Assert.True(isEqual); }
public static void DifferentLengthsReturnFalse(int byteLength) { byte[] rented = ArrayPool <byte> .Shared.Rent(byteLength); Span <byte> testSpan = new Span <byte>(rented, 0, byteLength); Fill(rented, 0, byteLength); byte[] rented2 = ArrayPool <byte> .Shared.Rent(byteLength); Span <byte> testSpan2 = new Span <byte>(rented2, 0, byteLength); testSpan.CopyTo(testSpan2); bool isEqualA = CryptographicOperations.FixedTimeEquals(testSpan, testSpan2.Slice(0, byteLength - 1)); bool isEqualB = CryptographicOperations.FixedTimeEquals(testSpan.Slice(0, byteLength - 1), testSpan2); ArrayPool <byte> .Shared.Return(rented); ArrayPool <byte> .Shared.Return(rented2); Assert.False(isEqualA, "value, value missing last byte"); Assert.False(isEqualB, "value missing last byte, value"); }