ManagedAuthenticatedEncryptorTests.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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.Linq;
  5. using System.Security.Cryptography;
  6. using System.Text;
  7. using Microsoft.AspNetCore.DataProtection.Test.Shared;
  8. using Microsoft.AspNetCore.Testing.xunit;
  9. using Xunit;
  10. namespace Microsoft.AspNetCore.DataProtection.Managed
  11. {
  12. public class ManagedAuthenticatedEncryptorTests
  13. {
  14. [Fact]
  15. public void Encrypt_Decrypt_RoundTrips()
  16. {
  17. // Arrange
  18. Secret kdk = new Secret(new byte[512 / 8]);
  19. ManagedAuthenticatedEncryptor encryptor = new ManagedAuthenticatedEncryptor(kdk,
  20. symmetricAlgorithmFactory: Aes.Create,
  21. symmetricAlgorithmKeySizeInBytes: 256 / 8,
  22. validationAlgorithmFactory: () => new HMACSHA256());
  23. ArraySegment<byte> plaintext = new ArraySegment<byte>(Encoding.UTF8.GetBytes("plaintext"));
  24. ArraySegment<byte> aad = new ArraySegment<byte>(Encoding.UTF8.GetBytes("aad"));
  25. // Act
  26. byte[] ciphertext = encryptor.Encrypt(plaintext, aad);
  27. byte[] decipheredtext = encryptor.Decrypt(new ArraySegment<byte>(ciphertext), aad);
  28. // Assert
  29. Assert.Equal(plaintext, decipheredtext);
  30. }
  31. [Fact]
  32. public void Encrypt_Decrypt_Tampering_Fails()
  33. {
  34. // Arrange
  35. Secret kdk = new Secret(new byte[512 / 8]);
  36. ManagedAuthenticatedEncryptor encryptor = new ManagedAuthenticatedEncryptor(kdk,
  37. symmetricAlgorithmFactory: Aes.Create,
  38. symmetricAlgorithmKeySizeInBytes: 256 / 8,
  39. validationAlgorithmFactory: () => new HMACSHA256());
  40. ArraySegment<byte> plaintext = new ArraySegment<byte>(Encoding.UTF8.GetBytes("plaintext"));
  41. ArraySegment<byte> aad = new ArraySegment<byte>(Encoding.UTF8.GetBytes("aad"));
  42. byte[] validCiphertext = encryptor.Encrypt(plaintext, aad);
  43. // Act & assert - 1
  44. // Ciphertext is too short to be a valid payload
  45. byte[] invalidCiphertext_tooShort = new byte[10];
  46. Assert.Throws<CryptographicException>(() =>
  47. {
  48. encryptor.Decrypt(new ArraySegment<byte>(invalidCiphertext_tooShort), aad);
  49. });
  50. // Act & assert - 2
  51. // Ciphertext has been manipulated
  52. byte[] invalidCiphertext_manipulated = (byte[])validCiphertext.Clone();
  53. invalidCiphertext_manipulated[0] ^= 0x01;
  54. Assert.Throws<CryptographicException>(() =>
  55. {
  56. encryptor.Decrypt(new ArraySegment<byte>(invalidCiphertext_manipulated), aad);
  57. });
  58. // Act & assert - 3
  59. // Ciphertext is too long
  60. byte[] invalidCiphertext_tooLong = validCiphertext.Concat(new byte[] { 0 }).ToArray();
  61. Assert.Throws<CryptographicException>(() =>
  62. {
  63. encryptor.Decrypt(new ArraySegment<byte>(invalidCiphertext_tooLong), aad);
  64. });
  65. // Act & assert - 4
  66. // AAD is incorrect
  67. Assert.Throws<CryptographicException>(() =>
  68. {
  69. encryptor.Decrypt(new ArraySegment<byte>(validCiphertext), new ArraySegment<byte>(Encoding.UTF8.GetBytes("different aad")));
  70. });
  71. }
  72. [Fact]
  73. public void Encrypt_KnownKey()
  74. {
  75. // Arrange
  76. Secret kdk = new Secret(Encoding.UTF8.GetBytes("master key"));
  77. ManagedAuthenticatedEncryptor encryptor = new ManagedAuthenticatedEncryptor(kdk,
  78. symmetricAlgorithmFactory: Aes.Create,
  79. symmetricAlgorithmKeySizeInBytes: 256 / 8,
  80. validationAlgorithmFactory: () => new HMACSHA256(),
  81. genRandom: new SequentialGenRandom());
  82. ArraySegment<byte> plaintext = new ArraySegment<byte>(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }, 2, 3);
  83. ArraySegment<byte> aad = new ArraySegment<byte>(new byte[] { 7, 6, 5, 4, 3, 2, 1, 0 }, 1, 4);
  84. // Act
  85. byte[] retVal = encryptor.Encrypt(
  86. plaintext: plaintext,
  87. additionalAuthenticatedData: aad);
  88. // Assert
  89. // retVal := 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F (keyModifier)
  90. // | 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F (IV)
  91. // | B7 EA 3E 32 58 93 A3 06 03 89 C6 66 03 63 08 4B (encryptedData)
  92. // | 9D 8A 85 C7 0F BD 98 D8 7F 72 E7 72 3E B5 A6 26 (HMAC)
  93. // | 6C 38 77 F7 66 19 A2 C9 2C BB AD DA E7 62 00 00
  94. string retValAsString = Convert.ToBase64String(retVal);
  95. Assert.Equal("AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh+36j4yWJOjBgOJxmYDYwhLnYqFxw+9mNh/cudyPrWmJmw4d/dmGaLJLLut2udiAAA=", retValAsString);
  96. }
  97. }
  98. }