CachedAlgorithmHandlesTests.cs 8.0 KB

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