CachedAlgorithmHandlesTests.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. using System;
  4. using System.Text;
  5. using Microsoft.AspNetCore.Cryptography.SafeHandles;
  6. using Microsoft.AspNetCore.DataProtection.Test.Shared;
  7. using Microsoft.AspNetCore.InternalTesting;
  8. using Xunit;
  9. namespace Microsoft.AspNetCore.Cryptography.Cng;
  10. // This class tests both the properties and the output of hash algorithms.
  11. // It only tests the properties of the encryption algorithms.
  12. // Output of the encryption and key derivatoin functions are tested by other projects.
  13. public unsafe class CachedAlgorithmHandlesTests
  14. {
  15. private static readonly byte[] _dataToHash = Encoding.UTF8.GetBytes("Sample input data.");
  16. private static readonly byte[] _hmacKey = Encoding.UTF8.GetBytes("Secret key material.");
  17. [ConditionalFact]
  18. [ConditionalRunTestOnlyOnWindows]
  19. public void AES_CBC_Cached_Handle()
  20. {
  21. RunAesBlockCipherAlgorithmTest(() => CachedAlgorithmHandles.AES_CBC);
  22. }
  23. [ConditionalFact]
  24. [ConditionalRunTestOnlyOnWindows]
  25. public void AES_GCM_Cached_Handle()
  26. {
  27. RunAesBlockCipherAlgorithmTest(() => CachedAlgorithmHandles.AES_GCM);
  28. }
  29. [ConditionalFact]
  30. [ConditionalRunTestOnlyOnWindows]
  31. public void SHA1_Cached_Handle_No_HMAC()
  32. {
  33. RunHashAlgorithmTest_No_HMAC(
  34. getter: () => CachedAlgorithmHandles.SHA1,
  35. expectedAlgorithmName: "SHA1",
  36. expectedBlockSizeInBytes: 512 / 8,
  37. expectedDigestSizeInBytes: 160 / 8,
  38. expectedDigest: "MbYo3dZmXtgUZcUoWoxkCDKFvkk=");
  39. }
  40. [ConditionalFact]
  41. [ConditionalRunTestOnlyOnWindows]
  42. public void SHA1_Cached_Handle_With_HMAC()
  43. {
  44. RunHashAlgorithmTest_With_HMAC(
  45. getter: () => CachedAlgorithmHandles.HMAC_SHA1,
  46. expectedAlgorithmName: "SHA1",
  47. expectedBlockSizeInBytes: 512 / 8,
  48. expectedDigestSizeInBytes: 160 / 8,
  49. expectedDigest: "PjYTgLTWkt6NeH0NudIR7N47Ipg=");
  50. }
  51. [ConditionalFact]
  52. [ConditionalRunTestOnlyOnWindows]
  53. public void SHA256_Cached_Handle_No_HMAC()
  54. {
  55. RunHashAlgorithmTest_No_HMAC(
  56. getter: () => CachedAlgorithmHandles.SHA256,
  57. expectedAlgorithmName: "SHA256",
  58. expectedBlockSizeInBytes: 512 / 8,
  59. expectedDigestSizeInBytes: 256 / 8,
  60. expectedDigest: "5uRfQadsrnUTa3/TEo5PP6SDZQkb9AcE4wNXDVcM0Fo=");
  61. }
  62. [ConditionalFact]
  63. [ConditionalRunTestOnlyOnWindows]
  64. public void SHA256_Cached_Handle_With_HMAC()
  65. {
  66. RunHashAlgorithmTest_With_HMAC(
  67. getter: () => CachedAlgorithmHandles.HMAC_SHA256,
  68. expectedAlgorithmName: "SHA256",
  69. expectedBlockSizeInBytes: 512 / 8,
  70. expectedDigestSizeInBytes: 256 / 8,
  71. expectedDigest: "KLzo0lVg5gZkpL5D6Ck7QT8w4iuPCe/pGCrMcOXWbKY=");
  72. }
  73. [ConditionalFact]
  74. [ConditionalRunTestOnlyOnWindows]
  75. public void SHA512_Cached_Handle_No_HMAC()
  76. {
  77. RunHashAlgorithmTest_No_HMAC(
  78. getter: () => CachedAlgorithmHandles.SHA512,
  79. expectedAlgorithmName: "SHA512",
  80. expectedBlockSizeInBytes: 1024 / 8,
  81. expectedDigestSizeInBytes: 512 / 8,
  82. expectedDigest: "jKI7WrcgPP7n2HAYOb8uFRi7xEsNG/BmdGd18dwwkIpqJ4Vmlk2b+8hssLyMQlprTSKVJNObSiYUqW5THS7okw==");
  83. }
  84. [ConditionalFact]
  85. [ConditionalRunTestOnlyOnWindows]
  86. public void SHA512_Cached_Handle_With_HMAC()
  87. {
  88. RunHashAlgorithmTest_With_HMAC(
  89. getter: () => CachedAlgorithmHandles.HMAC_SHA512,
  90. expectedAlgorithmName: "SHA512",
  91. expectedBlockSizeInBytes: 1024 / 8,
  92. expectedDigestSizeInBytes: 512 / 8,
  93. expectedDigest: "pKTX5vtPtbsn7pX9ISDlOYr1NFklTBIPYAFICy0ZQbFc0QVzGaTUvtqTOi91I0sHa1DIod6uIogux5iLdHjfcA==");
  94. }
  95. private static void RunAesBlockCipherAlgorithmTest(Func<BCryptAlgorithmHandle> getter)
  96. {
  97. // Getter must return the same instance of the cached handle
  98. var algorithmHandle = getter();
  99. var algorithmHandleSecondAttempt = getter();
  100. Assert.NotNull(algorithmHandle);
  101. Assert.Same(algorithmHandle, algorithmHandleSecondAttempt);
  102. // Validate that properties are what we expect
  103. Assert.Equal("AES", algorithmHandle.GetAlgorithmName());
  104. Assert.Equal((uint)(128 / 8), algorithmHandle.GetCipherBlockLength());
  105. var supportedKeyLengths = algorithmHandle.GetSupportedKeyLengths();
  106. Assert.Equal(128U, supportedKeyLengths.dwMinLength);
  107. Assert.Equal(256U, supportedKeyLengths.dwMaxLength);
  108. Assert.Equal(64U, supportedKeyLengths.dwIncrement);
  109. }
  110. private static void RunHashAlgorithmTest_No_HMAC(
  111. Func<BCryptAlgorithmHandle> getter,
  112. string expectedAlgorithmName,
  113. uint expectedBlockSizeInBytes,
  114. uint expectedDigestSizeInBytes,
  115. string expectedDigest)
  116. {
  117. // Getter must return the same instance of the cached handle
  118. var algorithmHandle = getter();
  119. var algorithmHandleSecondAttempt = getter();
  120. Assert.NotNull(algorithmHandle);
  121. Assert.Same(algorithmHandle, algorithmHandleSecondAttempt);
  122. // Validate that properties are what we expect
  123. Assert.Equal(expectedAlgorithmName, algorithmHandle.GetAlgorithmName());
  124. Assert.Equal(expectedBlockSizeInBytes, algorithmHandle.GetHashBlockLength());
  125. Assert.Equal(expectedDigestSizeInBytes, algorithmHandle.GetHashDigestLength());
  126. // Perform the digest calculation and validate against our expectation
  127. var hashHandle = algorithmHandle.CreateHash();
  128. byte[] outputHash = new byte[expectedDigestSizeInBytes];
  129. fixed (byte* pInput = _dataToHash)
  130. {
  131. fixed (byte* pOutput = outputHash)
  132. {
  133. hashHandle.HashData(pInput, (uint)_dataToHash.Length, pOutput, (uint)outputHash.Length);
  134. }
  135. }
  136. Assert.Equal(expectedDigest, Convert.ToBase64String(outputHash));
  137. }
  138. private static void RunHashAlgorithmTest_With_HMAC(
  139. Func<BCryptAlgorithmHandle> getter,
  140. string expectedAlgorithmName,
  141. uint expectedBlockSizeInBytes,
  142. uint expectedDigestSizeInBytes,
  143. string expectedDigest)
  144. {
  145. // Getter must return the same instance of the cached handle
  146. var algorithmHandle = getter();
  147. var algorithmHandleSecondAttempt = getter();
  148. Assert.NotNull(algorithmHandle);
  149. Assert.Same(algorithmHandle, algorithmHandleSecondAttempt);
  150. // Validate that properties are what we expect
  151. Assert.Equal(expectedAlgorithmName, algorithmHandle.GetAlgorithmName());
  152. Assert.Equal(expectedBlockSizeInBytes, algorithmHandle.GetHashBlockLength());
  153. Assert.Equal(expectedDigestSizeInBytes, algorithmHandle.GetHashDigestLength());
  154. // Perform the digest calculation and validate against our expectation
  155. fixed (byte* pKey = _hmacKey)
  156. {
  157. var hashHandle = algorithmHandle.CreateHmac(pKey, (uint)_hmacKey.Length);
  158. byte[] outputHash = new byte[expectedDigestSizeInBytes];
  159. fixed (byte* pInput = _dataToHash)
  160. {
  161. fixed (byte* pOutput = outputHash)
  162. {
  163. hashHandle.HashData(pInput, (uint)_dataToHash.Length, pOutput, (uint)outputHash.Length);
  164. }
  165. }
  166. Assert.Equal(expectedDigest, Convert.ToBase64String(outputHash));
  167. }
  168. }
  169. }