190 lines
8.0 KiB
C#
190 lines
8.0 KiB
C#
// Copyright (c) .NET Foundation. All rights reserved.
|
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
|
|
using System;
|
|
using System.Text;
|
|
using Microsoft.AspNetCore.Cryptography.SafeHandles;
|
|
using Microsoft.AspNetCore.DataProtection.Test.Shared;
|
|
using Microsoft.AspNetCore.Testing.xunit;
|
|
using Xunit;
|
|
|
|
namespace Microsoft.AspNetCore.Cryptography.Cng
|
|
{
|
|
// This class tests both the properties and the output of hash algorithms.
|
|
// It only tests the properties of the encryption algorithms.
|
|
// Output of the encryption and key derivatoin functions are tested by other projects.
|
|
public unsafe class CachedAlgorithmHandlesTests
|
|
{
|
|
private static readonly byte[] _dataToHash = Encoding.UTF8.GetBytes("Sample input data.");
|
|
private static readonly byte[] _hmacKey = Encoding.UTF8.GetBytes("Secret key material.");
|
|
|
|
[ConditionalFact]
|
|
[ConditionalRunTestOnlyOnWindows]
|
|
public void AES_CBC_Cached_Handle()
|
|
{
|
|
RunAesBlockCipherAlgorithmTest(() => CachedAlgorithmHandles.AES_CBC);
|
|
}
|
|
|
|
[ConditionalFact]
|
|
[ConditionalRunTestOnlyOnWindows]
|
|
public void AES_GCM_Cached_Handle()
|
|
{
|
|
RunAesBlockCipherAlgorithmTest(() => CachedAlgorithmHandles.AES_GCM);
|
|
}
|
|
|
|
[ConditionalFact]
|
|
[ConditionalRunTestOnlyOnWindows]
|
|
public void SHA1_Cached_Handle_No_HMAC()
|
|
{
|
|
RunHashAlgorithmTest_No_HMAC(
|
|
getter: () => CachedAlgorithmHandles.SHA1,
|
|
expectedAlgorithmName: "SHA1",
|
|
expectedBlockSizeInBytes: 512 / 8,
|
|
expectedDigestSizeInBytes: 160 / 8,
|
|
expectedDigest: "MbYo3dZmXtgUZcUoWoxkCDKFvkk=");
|
|
}
|
|
|
|
[ConditionalFact]
|
|
[ConditionalRunTestOnlyOnWindows]
|
|
public void SHA1_Cached_Handle_With_HMAC()
|
|
{
|
|
RunHashAlgorithmTest_With_HMAC(
|
|
getter: () => CachedAlgorithmHandles.HMAC_SHA1,
|
|
expectedAlgorithmName: "SHA1",
|
|
expectedBlockSizeInBytes: 512 / 8,
|
|
expectedDigestSizeInBytes: 160 / 8,
|
|
expectedDigest: "PjYTgLTWkt6NeH0NudIR7N47Ipg=");
|
|
}
|
|
|
|
[ConditionalFact]
|
|
[ConditionalRunTestOnlyOnWindows]
|
|
public void SHA256_Cached_Handle_No_HMAC()
|
|
{
|
|
RunHashAlgorithmTest_No_HMAC(
|
|
getter: () => CachedAlgorithmHandles.SHA256,
|
|
expectedAlgorithmName: "SHA256",
|
|
expectedBlockSizeInBytes: 512 / 8,
|
|
expectedDigestSizeInBytes: 256 / 8,
|
|
expectedDigest: "5uRfQadsrnUTa3/TEo5PP6SDZQkb9AcE4wNXDVcM0Fo=");
|
|
}
|
|
|
|
[ConditionalFact]
|
|
[ConditionalRunTestOnlyOnWindows]
|
|
public void SHA256_Cached_Handle_With_HMAC()
|
|
{
|
|
RunHashAlgorithmTest_With_HMAC(
|
|
getter: () => CachedAlgorithmHandles.HMAC_SHA256,
|
|
expectedAlgorithmName: "SHA256",
|
|
expectedBlockSizeInBytes: 512 / 8,
|
|
expectedDigestSizeInBytes: 256 / 8,
|
|
expectedDigest: "KLzo0lVg5gZkpL5D6Ck7QT8w4iuPCe/pGCrMcOXWbKY=");
|
|
}
|
|
|
|
[ConditionalFact]
|
|
[ConditionalRunTestOnlyOnWindows]
|
|
public void SHA512_Cached_Handle_No_HMAC()
|
|
{
|
|
RunHashAlgorithmTest_No_HMAC(
|
|
getter: () => CachedAlgorithmHandles.SHA512,
|
|
expectedAlgorithmName: "SHA512",
|
|
expectedBlockSizeInBytes: 1024 / 8,
|
|
expectedDigestSizeInBytes: 512 / 8,
|
|
expectedDigest: "jKI7WrcgPP7n2HAYOb8uFRi7xEsNG/BmdGd18dwwkIpqJ4Vmlk2b+8hssLyMQlprTSKVJNObSiYUqW5THS7okw==");
|
|
}
|
|
|
|
[ConditionalFact]
|
|
[ConditionalRunTestOnlyOnWindows]
|
|
public void SHA512_Cached_Handle_With_HMAC()
|
|
{
|
|
RunHashAlgorithmTest_With_HMAC(
|
|
getter: () => CachedAlgorithmHandles.HMAC_SHA512,
|
|
expectedAlgorithmName: "SHA512",
|
|
expectedBlockSizeInBytes: 1024 / 8,
|
|
expectedDigestSizeInBytes: 512 / 8,
|
|
expectedDigest: "pKTX5vtPtbsn7pX9ISDlOYr1NFklTBIPYAFICy0ZQbFc0QVzGaTUvtqTOi91I0sHa1DIod6uIogux5iLdHjfcA==");
|
|
}
|
|
|
|
private static void RunAesBlockCipherAlgorithmTest(Func<BCryptAlgorithmHandle> getter)
|
|
{
|
|
// Getter must return the same instance of the cached handle
|
|
var algorithmHandle = getter();
|
|
var algorithmHandleSecondAttempt = getter();
|
|
Assert.NotNull(algorithmHandle);
|
|
Assert.Same(algorithmHandle, algorithmHandleSecondAttempt);
|
|
|
|
// Validate that properties are what we expect
|
|
Assert.Equal("AES", algorithmHandle.GetAlgorithmName());
|
|
Assert.Equal((uint)(128 / 8), algorithmHandle.GetCipherBlockLength());
|
|
var supportedKeyLengths = algorithmHandle.GetSupportedKeyLengths();
|
|
Assert.Equal(128U, supportedKeyLengths.dwMinLength);
|
|
Assert.Equal(256U, supportedKeyLengths.dwMaxLength);
|
|
Assert.Equal(64U, supportedKeyLengths.dwIncrement);
|
|
}
|
|
|
|
private static void RunHashAlgorithmTest_No_HMAC(
|
|
Func<BCryptAlgorithmHandle> getter,
|
|
string expectedAlgorithmName,
|
|
uint expectedBlockSizeInBytes,
|
|
uint expectedDigestSizeInBytes,
|
|
string expectedDigest)
|
|
{
|
|
// Getter must return the same instance of the cached handle
|
|
var algorithmHandle = getter();
|
|
var algorithmHandleSecondAttempt = getter();
|
|
Assert.NotNull(algorithmHandle);
|
|
Assert.Same(algorithmHandle, algorithmHandleSecondAttempt);
|
|
|
|
// Validate that properties are what we expect
|
|
Assert.Equal(expectedAlgorithmName, algorithmHandle.GetAlgorithmName());
|
|
Assert.Equal(expectedBlockSizeInBytes, algorithmHandle.GetHashBlockLength());
|
|
Assert.Equal(expectedDigestSizeInBytes, algorithmHandle.GetHashDigestLength());
|
|
|
|
// Perform the digest calculation and validate against our expectation
|
|
var hashHandle = algorithmHandle.CreateHash();
|
|
byte[] outputHash = new byte[expectedDigestSizeInBytes];
|
|
fixed (byte* pInput = _dataToHash)
|
|
{
|
|
fixed (byte* pOutput = outputHash)
|
|
{
|
|
hashHandle.HashData(pInput, (uint)_dataToHash.Length, pOutput, (uint)outputHash.Length);
|
|
}
|
|
}
|
|
Assert.Equal(expectedDigest, Convert.ToBase64String(outputHash));
|
|
}
|
|
|
|
private static void RunHashAlgorithmTest_With_HMAC(
|
|
Func<BCryptAlgorithmHandle> getter,
|
|
string expectedAlgorithmName,
|
|
uint expectedBlockSizeInBytes,
|
|
uint expectedDigestSizeInBytes,
|
|
string expectedDigest)
|
|
{
|
|
// Getter must return the same instance of the cached handle
|
|
var algorithmHandle = getter();
|
|
var algorithmHandleSecondAttempt = getter();
|
|
Assert.NotNull(algorithmHandle);
|
|
Assert.Same(algorithmHandle, algorithmHandleSecondAttempt);
|
|
|
|
// Validate that properties are what we expect
|
|
Assert.Equal(expectedAlgorithmName, algorithmHandle.GetAlgorithmName());
|
|
Assert.Equal(expectedBlockSizeInBytes, algorithmHandle.GetHashBlockLength());
|
|
Assert.Equal(expectedDigestSizeInBytes, algorithmHandle.GetHashDigestLength());
|
|
|
|
// Perform the digest calculation and validate against our expectation
|
|
fixed (byte* pKey = _hmacKey)
|
|
{
|
|
var hashHandle = algorithmHandle.CreateHmac(pKey, (uint)_hmacKey.Length);
|
|
byte[] outputHash = new byte[expectedDigestSizeInBytes];
|
|
fixed (byte* pInput = _dataToHash)
|
|
{
|
|
fixed (byte* pOutput = outputHash)
|
|
{
|
|
hashHandle.HashData(pInput, (uint)_dataToHash.Length, pOutput, (uint)outputHash.Length);
|
|
}
|
|
}
|
|
Assert.Equal(expectedDigest, Convert.ToBase64String(outputHash));
|
|
}
|
|
}
|
|
}
|
|
}
|