From c959795a6461a9150fbabfd5c08486d05e363057 Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Wed, 5 Apr 2017 21:00:39 -0700 Subject: [PATCH] Creating one IAuthenticatedEncryptor per IKey --- .../KeyManagement/DefaultKeyResolver.cs | 16 +---- .../KeyManagement/DeferredKey.cs | 12 +++- .../KeyManagement/IKey.cs | 7 ++ .../Internal/CacheableKeyRing.cs | 4 +- .../Internal/DefaultKeyResolution.cs | 4 +- .../KeyManagement/Key.cs | 16 ++++- .../KeyManagement/KeyBase.cs | 31 +++++++- .../KeyManagement/KeyRing.cs | 19 ++--- .../KeyManagement/KeyRingProvider.cs | 20 +----- .../KeyManagement/XmlKeyManager.cs | 9 ++- ...tedEncryptorDescriptorDeserializerTests.cs | 7 +- .../AuthenticatedEncryptorDescriptorTests.cs | 8 ++- ...tedEncryptorDescriptorDeserializerTests.cs | 7 +- ...tedEncryptorDescriptorDeserializerTests.cs | 7 +- ...tedEncryptorDescriptorDeserializerTests.cs | 8 +-- .../KeyManagement/DefaultKeyResolverTests.cs | 68 +++++++----------- .../KeyManagement/DeferredKeyTests.cs | 12 ++-- .../KeyRingBasedDataProtectorTests.cs | 26 +++---- .../KeyManagement/KeyRingProviderTests.cs | 1 + .../KeyManagement/KeyRingTests.cs | 72 +++++++------------ .../KeyManagement/KeyTests.cs | 7 +- 21 files changed, 180 insertions(+), 181 deletions(-) diff --git a/src/Microsoft.AspNetCore.DataProtection/KeyManagement/DefaultKeyResolver.cs b/src/Microsoft.AspNetCore.DataProtection/KeyManagement/DefaultKeyResolver.cs index c2efbf14bb..9c545c793f 100644 --- a/src/Microsoft.AspNetCore.DataProtection/KeyManagement/DefaultKeyResolver.cs +++ b/src/Microsoft.AspNetCore.DataProtection/KeyManagement/DefaultKeyResolver.cs @@ -29,8 +29,6 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement private readonly ILogger _logger; - private readonly IEnumerable _encryptorFactories; - /// /// The maximum skew that is allowed between servers. /// This is used to allow newly-created keys to be used across servers even though @@ -46,7 +44,6 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement { _keyPropagationWindow = keyManagementOptions.Value.KeyPropagationWindow; _maxServerToServerClockSkew = keyManagementOptions.Value.MaxServerClockSkew; - _encryptorFactories = keyManagementOptions.Value.AuthenticatedEncryptorFactories; _logger = loggerFactory.CreateLogger(); } @@ -54,16 +51,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement { try { - IAuthenticatedEncryptor encryptorInstance = null; - foreach (var factory in _encryptorFactories) - { - encryptorInstance = factory.CreateEncryptorInstance(key); - if (encryptorInstance != null) - { - break; - } - } - + var encryptorInstance = key.CreateEncryptor(); if (encryptorInstance == null) { CryptoUtil.Fail("CreateEncryptorInstance returned null."); @@ -73,7 +61,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement } catch (Exception ex) { - _logger.KeyIsIneligibleToBeTheDefaultKeyBecauseItsMethodFailed(key.KeyId, nameof(IAuthenticatedEncryptorFactory.CreateEncryptorInstance), ex); + _logger.KeyIsIneligibleToBeTheDefaultKeyBecauseItsMethodFailed(key.KeyId, nameof(IKey.CreateEncryptor), ex); return false; } } diff --git a/src/Microsoft.AspNetCore.DataProtection/KeyManagement/DeferredKey.cs b/src/Microsoft.AspNetCore.DataProtection/KeyManagement/DeferredKey.cs index 9afea8a92d..a21210aceb 100644 --- a/src/Microsoft.AspNetCore.DataProtection/KeyManagement/DeferredKey.cs +++ b/src/Microsoft.AspNetCore.DataProtection/KeyManagement/DeferredKey.cs @@ -2,7 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Xml.Linq; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; using Microsoft.AspNetCore.DataProtection.XmlEncryption; @@ -21,8 +23,14 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement DateTimeOffset activationDate, DateTimeOffset expirationDate, IInternalXmlKeyManager keyManager, - XElement keyElement) - : base(keyId, creationDate, activationDate, expirationDate, new Lazy(GetLazyDescriptorDelegate(keyManager, keyElement))) + XElement keyElement, + IEnumerable encryptorFactories) + : base(keyId, + creationDate, + activationDate, + expirationDate, + new Lazy(GetLazyDescriptorDelegate(keyManager, keyElement)), + encryptorFactories) { } diff --git a/src/Microsoft.AspNetCore.DataProtection/KeyManagement/IKey.cs b/src/Microsoft.AspNetCore.DataProtection/KeyManagement/IKey.cs index 0ac314449f..f590c01c1b 100644 --- a/src/Microsoft.AspNetCore.DataProtection/KeyManagement/IKey.cs +++ b/src/Microsoft.AspNetCore.DataProtection/KeyManagement/IKey.cs @@ -49,5 +49,12 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement /// Gets the instance associated with this key. /// IAuthenticatedEncryptorDescriptor Descriptor { get; } + + /// + /// Creates an instance that can be used to encrypt data + /// to and decrypt data from this key. + /// + /// An . + IAuthenticatedEncryptor CreateEncryptor(); } } diff --git a/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/CacheableKeyRing.cs b/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/CacheableKeyRing.cs index 36c9b00ac8..ff6fa87fce 100644 --- a/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/CacheableKeyRing.cs +++ b/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/CacheableKeyRing.cs @@ -15,8 +15,8 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement.Internal { private readonly CancellationToken _expirationToken; - internal CacheableKeyRing(CancellationToken expirationToken, DateTimeOffset expirationTime, IKey defaultKey, IEnumerable allKeys, IEnumerable encryptorFactories) - : this(expirationToken, expirationTime, keyRing: new KeyRing(defaultKey, allKeys, encryptorFactories)) + internal CacheableKeyRing(CancellationToken expirationToken, DateTimeOffset expirationTime, IKey defaultKey, IEnumerable allKeys) + : this(expirationToken, expirationTime, keyRing: new KeyRing(defaultKey, allKeys)) { } diff --git a/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/DefaultKeyResolution.cs b/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/DefaultKeyResolution.cs index 2d5b06d841..1c4170607b 100644 --- a/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/DefaultKeyResolution.cs +++ b/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Internal/DefaultKeyResolution.cs @@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement.Internal /// The default key, may be null if no key is a good default candidate. /// /// - /// If this property is non-null, its method will succeed + /// If this property is non-null, its method will succeed /// so is appropriate for use with deferred keys. /// public IKey DefaultKey; @@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement.Internal /// be null if there is no viable fallback key. /// /// - /// If this property is non-null, its method will succeed + /// If this property is non-null, its method will succeed /// so is appropriate for use with deferred keys. /// public IKey FallbackKey; diff --git a/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Key.cs b/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Key.cs index fd049a6695..84569a8e1b 100644 --- a/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Key.cs +++ b/src/Microsoft.AspNetCore.DataProtection/KeyManagement/Key.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; @@ -13,8 +14,19 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement /// internal sealed class Key : KeyBase { - public Key(Guid keyId, DateTimeOffset creationDate, DateTimeOffset activationDate, DateTimeOffset expirationDate, IAuthenticatedEncryptorDescriptor descriptor) - : base(keyId, creationDate, activationDate, expirationDate, new Lazy(() => descriptor)) + public Key( + Guid keyId, + DateTimeOffset creationDate, + DateTimeOffset activationDate, + DateTimeOffset expirationDate, + IAuthenticatedEncryptorDescriptor descriptor, + IEnumerable encryptorFactories) + : base(keyId, + creationDate, + activationDate, + expirationDate, + new Lazy(() => descriptor), + encryptorFactories) { } } diff --git a/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyBase.cs b/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyBase.cs index cd14b5e209..005a6ea9d5 100644 --- a/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyBase.cs +++ b/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyBase.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; @@ -13,14 +14,24 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement internal abstract class KeyBase : IKey { private readonly Lazy _lazyDescriptor; + private readonly IEnumerable _encryptorFactories; - public KeyBase(Guid keyId, DateTimeOffset creationDate, DateTimeOffset activationDate, DateTimeOffset expirationDate, Lazy lazyDescriptor) + private IAuthenticatedEncryptor _encryptor; + + public KeyBase( + Guid keyId, + DateTimeOffset creationDate, + DateTimeOffset activationDate, + DateTimeOffset expirationDate, + Lazy lazyDescriptor, + IEnumerable encryptorFactories) { KeyId = keyId; CreationDate = creationDate; ActivationDate = activationDate; ExpirationDate = expirationDate; _lazyDescriptor = lazyDescriptor; + _encryptorFactories = encryptorFactories; } public DateTimeOffset ActivationDate { get; } @@ -41,6 +52,24 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement } } + public IAuthenticatedEncryptor CreateEncryptor() + { + if (_encryptor == null) + { + foreach (var factory in _encryptorFactories) + { + var encryptor = factory.CreateEncryptorInstance(this); + if (encryptor != null) + { + _encryptor = encryptor; + break; + } + } + } + + return _encryptor; + } + internal void SetRevoked() { IsRevoked = true; diff --git a/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyRing.cs b/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyRing.cs index b8392d548e..2bbba031a6 100644 --- a/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyRing.cs +++ b/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyRing.cs @@ -17,12 +17,12 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement private readonly KeyHolder _defaultKeyHolder; private readonly Dictionary _keyIdToKeyHolderMap; - public KeyRing(IKey defaultKey, IEnumerable allKeys, IEnumerable encryptorFactories) + public KeyRing(IKey defaultKey, IEnumerable allKeys) { _keyIdToKeyHolderMap = new Dictionary(); foreach (IKey key in allKeys) { - _keyIdToKeyHolderMap.Add(key.KeyId, new KeyHolder(key, encryptorFactories)); + _keyIdToKeyHolderMap.Add(key.KeyId, new KeyHolder(key)); } // It's possible under some circumstances that the default key won't be part of 'allKeys', @@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement // wasn't in the underlying repository. In this case, we just add it now. if (!_keyIdToKeyHolderMap.ContainsKey(defaultKey.KeyId)) { - _keyIdToKeyHolderMap.Add(defaultKey.KeyId, new KeyHolder(defaultKey, encryptorFactories)); + _keyIdToKeyHolderMap.Add(defaultKey.KeyId, new KeyHolder(defaultKey)); } DefaultKeyId = defaultKey.KeyId; @@ -61,12 +61,10 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement { private readonly IKey _key; private IAuthenticatedEncryptor _encryptor; - private readonly IEnumerable _encryptorFactories; - internal KeyHolder(IKey key, IEnumerable encryptorFactories) + internal KeyHolder(IKey key) { _key = key; - _encryptorFactories = encryptorFactories; } internal IAuthenticatedEncryptor GetEncryptorInstance(out bool isRevoked) @@ -81,14 +79,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement encryptor = Volatile.Read(ref _encryptor); if (encryptor == null) { - foreach (var factory in _encryptorFactories) - { - encryptor = factory.CreateEncryptorInstance(_key); - if (encryptor != null) - { - break; - } - } + encryptor = _key.CreateEncryptor(); Volatile.Write(ref _encryptor, encryptor); } } diff --git a/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyRingProvider.cs b/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyRingProvider.cs index 7e953cbd5f..8b0b25e7a7 100644 --- a/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyRingProvider.cs +++ b/src/Microsoft.AspNetCore.DataProtection/KeyManagement/KeyRingProvider.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Threading; using Microsoft.AspNetCore.Cryptography; -using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -118,7 +117,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement Debug.Assert(defaultKey != null); // Invariant: our caller ensures that CreateEncryptorInstance succeeded at least once - Debug.Assert(CreateEncryptorForKey(defaultKey) != null); + Debug.Assert(defaultKey.CreateEncryptor() != null); _logger.UsingKeyAsDefaultKey(defaultKey.KeyId); @@ -135,8 +134,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement expirationToken: cacheExpirationToken, expirationTime: (defaultKey.ExpirationDate <= now) ? nextAutoRefreshTime : Min(defaultKey.ExpirationDate, nextAutoRefreshTime), defaultKey: defaultKey, - allKeys: allKeys, - encryptorFactories: _keyManagementOptions.AuthenticatedEncryptorFactories); + allKeys: allKeys); } public IKeyRing GetCurrentKeyRing() @@ -236,20 +234,6 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement } } - private IAuthenticatedEncryptor CreateEncryptorForKey(IKey key) - { - foreach (var factory in _keyManagementOptions.AuthenticatedEncryptorFactories) - { - var encryptor = factory.CreateEncryptorInstance(key); - if (encryptor != null) - { - return encryptor; - } - } - - return null; - } - private static TimeSpan GetRefreshPeriodWithJitter(TimeSpan refreshPeriod) { // We'll fudge the refresh period up to -20% so that multiple applications don't try to diff --git a/src/Microsoft.AspNetCore.DataProtection/KeyManagement/XmlKeyManager.cs b/src/Microsoft.AspNetCore.DataProtection/KeyManagement/XmlKeyManager.cs index b7b2911439..b68a997c63 100644 --- a/src/Microsoft.AspNetCore.DataProtection/KeyManagement/XmlKeyManager.cs +++ b/src/Microsoft.AspNetCore.DataProtection/KeyManagement/XmlKeyManager.cs @@ -12,6 +12,7 @@ using System.Xml; using System.Xml.Linq; using Microsoft.AspNetCore.Cryptography; using Microsoft.AspNetCore.Cryptography.Cng; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; using Microsoft.AspNetCore.DataProtection.Cng; using Microsoft.AspNetCore.DataProtection.Internal; @@ -50,6 +51,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement private readonly IInternalXmlKeyManager _internalKeyManager; private readonly ILoggerFactory _loggerFactory; private readonly ILogger _logger; + private readonly IEnumerable _encryptorFactories; private CancellationTokenSource _cacheExpirationTokenSource; @@ -88,6 +90,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement _activator = activator; TriggerAndResetCacheExpirationToken(suppressLogging: true); _internalKeyManager = _internalKeyManager ?? this; + _encryptorFactories = keyManagementOptions.Value.AuthenticatedEncryptorFactories; } // Internal for testing. @@ -240,7 +243,8 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement activationDate: activationDate, expirationDate: expirationDate, keyManager: this, - keyElement: keyElement); + keyElement: keyElement, + encryptorFactories: _encryptorFactories); } catch (Exception ex) { @@ -400,7 +404,8 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement creationDate: creationDate, activationDate: activationDate, expirationDate: expirationDate, - descriptor: newDescriptor); + descriptor: newDescriptor, + encryptorFactories: _encryptorFactories); } IAuthenticatedEncryptorDescriptor IInternalXmlKeyManager.DeserializeDescriptorFromKeyElement(XElement keyElement) diff --git a/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorDeserializerTests.cs b/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorDeserializerTests.cs index 9264566756..e7ef5d69c7 100644 --- a/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorDeserializerTests.cs +++ b/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorDeserializerTests.cs @@ -43,16 +43,17 @@ namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.Configurat private static IAuthenticatedEncryptor CreateEncryptorInstanceFromDescriptor(AuthenticatedEncryptorDescriptor descriptor) { + var encryptorFactory = new AuthenticatedEncryptorFactory(NullLoggerFactory.Instance); var key = new Key( Guid.NewGuid(), DateTimeOffset.Now, DateTimeOffset.Now + TimeSpan.FromHours(1), DateTimeOffset.Now + TimeSpan.FromDays(30), - descriptor); + descriptor, + new[] { encryptorFactory }); - var encryptorFactory = new AuthenticatedEncryptorFactory(NullLoggerFactory.Instance); - return encryptorFactory.CreateEncryptorInstance(key); + return key.CreateEncryptor(); } } } diff --git a/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorTests.cs b/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorTests.cs index 54b977c845..0bed1de2e4 100644 --- a/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorTests.cs +++ b/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorTests.cs @@ -171,17 +171,19 @@ namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.Configurat private static IAuthenticatedEncryptor CreateEncryptorInstanceFromDescriptor(AuthenticatedEncryptorDescriptor descriptor) { + var encryptorFactory = new AuthenticatedEncryptorFactory(NullLoggerFactory.Instance); + // Dummy key with the specified descriptor. var key = new Key( Guid.NewGuid(), DateTimeOffset.Now, DateTimeOffset.Now + TimeSpan.FromHours(1), DateTimeOffset.Now + TimeSpan.FromDays(30), - descriptor); + descriptor, + new[] { encryptorFactory }); - var encryptorFactory = new AuthenticatedEncryptorFactory(NullLoggerFactory.Instance); - return encryptorFactory.CreateEncryptorInstance(key); + return key.CreateEncryptor(); } } } diff --git a/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptorDeserializerTests.cs b/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptorDeserializerTests.cs index 51897e64e9..eb61aaa676 100644 --- a/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptorDeserializerTests.cs +++ b/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptorDeserializerTests.cs @@ -50,16 +50,17 @@ namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.Configurat private static IAuthenticatedEncryptor CreateEncryptorInstanceFromDescriptor(CngCbcAuthenticatedEncryptorDescriptor descriptor) { + var encryptorFactory = new CngCbcAuthenticatedEncryptorFactory(NullLoggerFactory.Instance); var key = new Key( Guid.NewGuid(), DateTimeOffset.Now, DateTimeOffset.Now + TimeSpan.FromHours(1), DateTimeOffset.Now + TimeSpan.FromDays(30), - descriptor); + descriptor, + new[] { encryptorFactory }); - var encryptorFactory = new CngCbcAuthenticatedEncryptorFactory(NullLoggerFactory.Instance); - return encryptorFactory.CreateEncryptorInstance(key); + return key.CreateEncryptor(); } } } diff --git a/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptorDeserializerTests.cs b/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptorDeserializerTests.cs index 6adbdcc1d3..05845dfde0 100644 --- a/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptorDeserializerTests.cs +++ b/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptorDeserializerTests.cs @@ -47,16 +47,17 @@ namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.Configurat private static IAuthenticatedEncryptor CreateEncryptorInstanceFromDescriptor(CngGcmAuthenticatedEncryptorDescriptor descriptor) { + var encryptorFactory = new CngGcmAuthenticatedEncryptorFactory(NullLoggerFactory.Instance); var key = new Key( keyId: Guid.NewGuid(), creationDate: DateTimeOffset.Now, activationDate: DateTimeOffset.Now + TimeSpan.FromHours(1), expirationDate: DateTimeOffset.Now + TimeSpan.FromDays(30), - descriptor: descriptor); + descriptor: descriptor, + encryptorFactories: new[] { encryptorFactory }); - var encryptorFactory = new CngGcmAuthenticatedEncryptorFactory(NullLoggerFactory.Instance); - return encryptorFactory.CreateEncryptorInstance(key); + return key.CreateEncryptor(); } } } diff --git a/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializerTests.cs b/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializerTests.cs index 9a5162cce1..69cc556e6b 100644 --- a/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializerTests.cs +++ b/test/Microsoft.AspNetCore.DataProtection.Test/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializerTests.cs @@ -86,16 +86,16 @@ namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.Configurat private static IAuthenticatedEncryptor CreateEncryptorInstanceFromDescriptor(ManagedAuthenticatedEncryptorDescriptor descriptor) { + var encryptorFactory = new ManagedAuthenticatedEncryptorFactory(NullLoggerFactory.Instance); var key = new Key( Guid.NewGuid(), DateTimeOffset.Now, DateTimeOffset.Now + TimeSpan.FromHours(1), DateTimeOffset.Now + TimeSpan.FromDays(30), - descriptor); + descriptor, + new[] { encryptorFactory }); - var encryptorFactory = new ManagedAuthenticatedEncryptorFactory(NullLoggerFactory.Instance); - - return encryptorFactory.CreateEncryptorInstance(key); + return key.CreateEncryptor(); } } } diff --git a/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/DefaultKeyResolverTests.cs b/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/DefaultKeyResolverTests.cs index 9aeb5ea236..46e9b5f993 100644 --- a/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/DefaultKeyResolverTests.cs +++ b/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/DefaultKeyResolverTests.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.Linq; using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; using Microsoft.Extensions.Logging.Abstractions; @@ -20,7 +19,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement public void ResolveDefaultKeyPolicy_EmptyKeyRing_ReturnsNullDefaultKey() { // Arrange - var resolver = CreateDefaultKeyResolver(new MyEncryptorFactory()); + var resolver = CreateDefaultKeyResolver(); // Act var resolution = resolver.ResolveDefaultKeyPolicy(DateTimeOffset.Now, new IKey[0]); @@ -34,7 +33,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement public void ResolveDefaultKeyPolicy_ValidExistingKey_ReturnsExistingKey() { // Arrange - var resolver = CreateDefaultKeyResolver(new MyEncryptorFactory()); + var resolver = CreateDefaultKeyResolver(); var key1 = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); var key2 = CreateKey("2016-03-01 00:00:00Z", "2017-03-01 00:00:00Z"); @@ -50,7 +49,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement public void ResolveDefaultKeyPolicy_ValidExistingKey_AllowsForClockSkew_KeysStraddleSkewLine_ReturnsExistingKey() { // Arrange - var resolver = CreateDefaultKeyResolver(new MyEncryptorFactory()); + var resolver = CreateDefaultKeyResolver(); var key1 = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); var key2 = CreateKey("2016-03-01 00:00:00Z", "2017-03-01 00:00:00Z"); @@ -66,7 +65,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement public void ResolveDefaultKeyPolicy_ValidExistingKey_AllowsForClockSkew_AllKeysInFuture_ReturnsExistingKey() { // Arrange - var resolver = CreateDefaultKeyResolver(new MyEncryptorFactory()); + var resolver = CreateDefaultKeyResolver(); var key1 = CreateKey("2016-03-01 00:00:00Z", "2017-03-01 00:00:00Z"); // Act @@ -81,7 +80,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement public void ResolveDefaultKeyPolicy_ValidExistingKey_NoSuccessor_ReturnsExistingKey_SignalsGenerateNewKey() { // Arrange - var resolver = CreateDefaultKeyResolver(new MyEncryptorFactory()); + var resolver = CreateDefaultKeyResolver(); var key1 = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); // Act @@ -96,7 +95,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement public void ResolveDefaultKeyPolicy_ValidExistingKey_NoLegitimateSuccessor_ReturnsExistingKey_SignalsGenerateNewKey() { // Arrange - var resolver = CreateDefaultKeyResolver(new MyEncryptorFactory()); + var resolver = CreateDefaultKeyResolver(); var key1 = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); var key2 = CreateKey("2016-03-01 00:00:00Z", "2017-03-01 00:00:00Z", isRevoked: true); var key3 = CreateKey("2016-03-01 00:00:00Z", "2016-03-02 00:00:00Z"); // key expires too soon @@ -113,7 +112,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement public void ResolveDefaultKeyPolicy_MostRecentKeyIsInvalid_BecauseOfRevocation_ReturnsNull() { // Arrange - var resolver = CreateDefaultKeyResolver(new MyEncryptorFactory()); + var resolver = CreateDefaultKeyResolver(); var key1 = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); var key2 = CreateKey("2015-03-02 00:00:00Z", "2016-03-01 00:00:00Z", isRevoked: true); @@ -130,8 +129,8 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement { // Arrange var key1 = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); - var key2 = CreateKey("2015-03-02 00:00:00Z", "2016-03-01 00:00:00Z"); - var resolver = CreateDefaultKeyResolver(new MyEncryptorFactory(throwForKeys: key2)); + var key2 = CreateKey("2015-03-02 00:00:00Z", "2016-03-01 00:00:00Z", createEncryptorThrows: true); + var resolver = CreateDefaultKeyResolver(); // Act var resolution = resolver.ResolveDefaultKeyPolicy("2015-04-01 00:00:00Z", key1, key2); @@ -145,7 +144,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement public void ResolveDefaultKeyPolicy_FutureKeyIsValidAndWithinClockSkew_ReturnsFutureKey() { // Arrange - var resolver = CreateDefaultKeyResolver(new MyEncryptorFactory()); + var resolver = CreateDefaultKeyResolver(); var key1 = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); // Act @@ -160,7 +159,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement public void ResolveDefaultKeyPolicy_FutureKeyIsValidButNotWithinClockSkew_ReturnsNull() { // Arrange - var resolver = CreateDefaultKeyResolver(new MyEncryptorFactory()); + var resolver = CreateDefaultKeyResolver(); var key1 = CreateKey("2015-03-01 00:00:00Z", "2016-03-01 00:00:00Z"); // Act @@ -175,7 +174,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement public void ResolveDefaultKeyPolicy_IgnoresExpiredOrRevokedFutureKeys() { // Arrange - var resolver = CreateDefaultKeyResolver(new MyEncryptorFactory()); + var resolver = CreateDefaultKeyResolver(); var key1 = CreateKey("2015-03-01 00:00:00Z", "2014-03-01 00:00:00Z"); // expiration before activation should never occur var key2 = CreateKey("2015-03-01 00:01:00Z", "2015-04-01 00:00:00Z", isRevoked: true); var key3 = CreateKey("2015-03-01 00:02:00Z", "2015-04-01 00:00:00Z"); @@ -192,7 +191,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement public void ResolveDefaultKeyPolicy_FallbackKey_SelectsLatestBeforePriorPropagationWindow_IgnoresRevokedKeys() { // Arrange - var resolver = CreateDefaultKeyResolver(new MyEncryptorFactory()); + var resolver = CreateDefaultKeyResolver(); var key1 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-01 00:00:00Z"); var key2 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-02 00:00:00Z"); var key3 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-03 00:00:00Z", isRevoked: true); @@ -212,9 +211,9 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement // Arrange var key1 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-01 00:00:00Z"); var key2 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-02 00:00:00Z"); - var key3 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-03 00:00:00Z"); + var key3 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-03 00:00:00Z", createEncryptorThrows: true); var key4 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-04 00:00:00Z"); - var resolver = CreateDefaultKeyResolver(new MyEncryptorFactory(throwForKeys: key3)); + var resolver = CreateDefaultKeyResolver(); // Act var resolution = resolver.ResolveDefaultKeyPolicy("2000-01-05 00:00:00Z", key1, key2, key3, key4); @@ -228,7 +227,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement public void ResolveDefaultKeyPolicy_FallbackKey_NoNonRevokedKeysBeforePriorPropagationWindow_SelectsEarliestNonRevokedKey() { // Arrange - var resolver = CreateDefaultKeyResolver(new MyEncryptorFactory()); + var resolver = CreateDefaultKeyResolver(); var key1 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-03 00:00:00Z", isRevoked: true); var key2 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-04 00:00:00Z"); var key3 = CreateKey("2010-01-01 00:00:00Z", "2010-01-01 00:00:00Z", creationDate: "2000-01-05 00:00:00Z"); @@ -241,14 +240,13 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement Assert.True(resolution.ShouldGenerateNewKey); } - private static IDefaultKeyResolver CreateDefaultKeyResolver(IAuthenticatedEncryptorFactory encryptorFactory) + private static IDefaultKeyResolver CreateDefaultKeyResolver() { var options = Options.Create(new KeyManagementOptions()); - options.Value.AuthenticatedEncryptorFactories.Add(encryptorFactory); return new DefaultKeyResolver(options, NullLoggerFactory.Instance); } - private static IKey CreateKey(string activationDate, string expirationDate, string creationDate = null, bool isRevoked = false) + private static IKey CreateKey(string activationDate, string expirationDate, string creationDate = null, bool isRevoked = false, bool createEncryptorThrows = false) { var mockKey = new Mock(); mockKey.Setup(o => o.KeyId).Returns(Guid.NewGuid()); @@ -256,31 +254,17 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement mockKey.Setup(o => o.ActivationDate).Returns(DateTimeOffset.ParseExact(activationDate, "u", CultureInfo.InvariantCulture)); mockKey.Setup(o => o.ExpirationDate).Returns(DateTimeOffset.ParseExact(expirationDate, "u", CultureInfo.InvariantCulture)); mockKey.Setup(o => o.IsRevoked).Returns(isRevoked); + if (createEncryptorThrows) + { + mockKey.Setup(o => o.CreateEncryptor()).Throws(new Exception("This method fails.")); + } + else + { + mockKey.Setup(o => o.CreateEncryptor()).Returns(Mock.Of()); + } return mockKey.Object; } - - private class MyEncryptorFactory : IAuthenticatedEncryptorFactory - { - private IReadOnlyList _throwForKeys; - - public MyEncryptorFactory(params IKey[] throwForKeys) - { - _throwForKeys = throwForKeys; - } - - public IAuthenticatedEncryptor CreateEncryptorInstance(IKey key) - { - if (_throwForKeys.Contains(key)) - { - throw new Exception("This method fails."); - } - else - { - return new Mock().Object; - } - } - } } internal static class DefaultKeyResolverExtensions diff --git a/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/DeferredKeyTests.cs b/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/DeferredKeyTests.cs index 90cf63c073..2a166564d0 100644 --- a/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/DeferredKeyTests.cs +++ b/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/DeferredKeyTests.cs @@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.Options; using Moq; using Xunit; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; namespace Microsoft.AspNetCore.DataProtection.KeyManagement { @@ -30,10 +31,10 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement XmlAssert.Equal(@"", element); return mockDescriptor; }); - var options = Options.Create(new KeyManagementOptions()); + var encryptorFactory = Mock.Of(); // Act - var key = new DeferredKey(keyId, creationDate, activationDate, expirationDate, mockInternalKeyManager.Object, XElement.Parse(@"")); + var key = new DeferredKey(keyId, creationDate, activationDate, expirationDate, mockInternalKeyManager.Object, XElement.Parse(@""), new[] { encryptorFactory }); // Assert Assert.Equal(keyId, key.KeyId); @@ -48,8 +49,8 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement { // Arrange var now = DateTimeOffset.UtcNow; - var options = Options.Create(new KeyManagementOptions()); - var key = new DeferredKey(Guid.Empty, now, now, now, new Mock().Object, XElement.Parse(@"")); + var encryptorFactory = Mock.Of(); + var key = new DeferredKey(Guid.Empty, now, now, now, new Mock().Object, XElement.Parse(@""), new[] { encryptorFactory }); // Act & assert Assert.False(key.IsRevoked); @@ -71,7 +72,8 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement }); var now = DateTimeOffset.UtcNow; - var key = new DeferredKey(Guid.Empty, now, now, now, mockKeyManager.Object, XElement.Parse(@"")); + var encryptorFactory = Mock.Of(); + var key = new DeferredKey(Guid.Empty, now, now, now, mockKeyManager.Object, XElement.Parse(@""), new[] { encryptorFactory }); // Act & assert ExceptionAssert.Throws(() => key.Descriptor, "How exceptional."); diff --git a/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyRingBasedDataProtectorTests.cs b/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyRingBasedDataProtectorTests.cs index 42b5153c5f..eb8d35fef0 100644 --- a/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyRingBasedDataProtectorTests.cs +++ b/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyRingBasedDataProtectorTests.cs @@ -208,8 +208,8 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement var encryptorFactory = new AuthenticatedEncryptorFactory(NullLoggerFactory.Instance); // the keyring has only one key - Key key = new Key(Guid.Empty, DateTimeOffset.Now, DateTimeOffset.Now, DateTimeOffset.Now, mockDescriptor.Object); - var keyRing = new KeyRing(key, new[] { key }, new[] { mockEncryptorFactory.Object }); + Key key = new Key(Guid.Empty, DateTimeOffset.Now, DateTimeOffset.Now, DateTimeOffset.Now, mockDescriptor.Object, new[] { mockEncryptorFactory.Object }); + var keyRing = new KeyRing(key, new[] { key }); var mockKeyRingProvider = new Mock(); mockKeyRingProvider.Setup(o => o.GetCurrentKeyRing()).Returns(keyRing); @@ -238,9 +238,9 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement mockEncryptorFactory.Setup(o => o.CreateEncryptorInstance(It.IsAny())).Returns(new Mock().Object); // the keyring has only one key - Key key = new Key(keyId, DateTimeOffset.Now, DateTimeOffset.Now, DateTimeOffset.Now, mockDescriptor.Object); + Key key = new Key(keyId, DateTimeOffset.Now, DateTimeOffset.Now, DateTimeOffset.Now, mockDescriptor.Object, new[] { mockEncryptorFactory.Object }); key.SetRevoked(); - var keyRing = new KeyRing(key, new[] { key }, new[] { mockEncryptorFactory.Object }); + var keyRing = new KeyRing(key, new[] { key }); var mockKeyRingProvider = new Mock(); mockKeyRingProvider.Setup(o => o.GetCurrentKeyRing()).Returns(keyRing); @@ -278,9 +278,9 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement var mockEncryptorFactory = new Mock(); mockEncryptorFactory.Setup(o => o.CreateEncryptorInstance(It.IsAny())).Returns(mockEncryptor.Object); - Key defaultKey = new Key(defaultKeyId, DateTimeOffset.Now, DateTimeOffset.Now, DateTimeOffset.Now, mockDescriptor.Object); + Key defaultKey = new Key(defaultKeyId, DateTimeOffset.Now, DateTimeOffset.Now, DateTimeOffset.Now, mockDescriptor.Object, new[] { mockEncryptorFactory.Object }); defaultKey.SetRevoked(); - var keyRing = new KeyRing(defaultKey, new[] { defaultKey }, new[] { mockEncryptorFactory.Object }); + var keyRing = new KeyRing(defaultKey, new[] { defaultKey }); var mockKeyRingProvider = new Mock(); mockKeyRingProvider.Setup(o => o.GetCurrentKeyRing()).Returns(keyRing); @@ -326,8 +326,8 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement var mockEncryptorFactory = new Mock(); mockEncryptorFactory.Setup(o => o.CreateEncryptorInstance(It.IsAny())).Returns(mockEncryptor.Object); - Key defaultKey = new Key(defaultKeyId, DateTimeOffset.Now, DateTimeOffset.Now, DateTimeOffset.Now, mockDescriptor.Object); - var keyRing = new KeyRing(defaultKey, new[] { defaultKey }, new[] { mockEncryptorFactory.Object }); + Key defaultKey = new Key(defaultKeyId, DateTimeOffset.Now, DateTimeOffset.Now, DateTimeOffset.Now, mockDescriptor.Object, new[] { mockEncryptorFactory.Object }); + var keyRing = new KeyRing(defaultKey, new[] { defaultKey }); var mockKeyRingProvider = new Mock(); mockKeyRingProvider.Setup(o => o.GetCurrentKeyRing()).Returns(keyRing); @@ -376,9 +376,9 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement var mockEncryptorFactory = new Mock(); mockEncryptorFactory.Setup(o => o.CreateEncryptorInstance(It.IsAny())).Returns(mockEncryptor.Object); - Key defaultKey = new Key(defaultKeyId, DateTimeOffset.Now, DateTimeOffset.Now, DateTimeOffset.Now, new Mock().Object); - Key embeddedKey = new Key(embeddedKeyId, DateTimeOffset.Now, DateTimeOffset.Now, DateTimeOffset.Now, mockDescriptor.Object); - var keyRing = new KeyRing(defaultKey, new[] { defaultKey, embeddedKey }, new[] { mockEncryptorFactory.Object }); + Key defaultKey = new Key(defaultKeyId, DateTimeOffset.Now, DateTimeOffset.Now, DateTimeOffset.Now, new Mock().Object, new[] { mockEncryptorFactory.Object }); + Key embeddedKey = new Key(embeddedKeyId, DateTimeOffset.Now, DateTimeOffset.Now, DateTimeOffset.Now, mockDescriptor.Object, new[] { mockEncryptorFactory.Object }); + var keyRing = new KeyRing(defaultKey, new[] { defaultKey, embeddedKey }); var mockKeyRingProvider = new Mock(); mockKeyRingProvider.Setup(o => o.GetCurrentKeyRing()).Returns(keyRing); @@ -408,9 +408,9 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement { // Arrange byte[] plaintext = new byte[] { 0x10, 0x20, 0x30, 0x40, 0x50 }; - Key key = new Key(Guid.NewGuid(), DateTimeOffset.Now, DateTimeOffset.Now, DateTimeOffset.Now, new AuthenticatedEncryptorConfiguration().CreateNewDescriptor()); var encryptorFactory = new AuthenticatedEncryptorFactory(NullLoggerFactory.Instance); - var keyRing = new KeyRing(key, new[] { key }, new[] { encryptorFactory }); + Key key = new Key(Guid.NewGuid(), DateTimeOffset.Now, DateTimeOffset.Now, DateTimeOffset.Now, new AuthenticatedEncryptorConfiguration().CreateNewDescriptor(), new[] { encryptorFactory }); + var keyRing = new KeyRing(key, new[] { key }); var mockKeyRingProvider = new Mock(); mockKeyRingProvider.Setup(o => o.GetCurrentKeyRing()).Returns(keyRing); diff --git a/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyRingProviderTests.cs b/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyRingProviderTests.cs index 7337c779f1..5654943820 100644 --- a/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyRingProviderTests.cs +++ b/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyRingProviderTests.cs @@ -644,6 +644,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement mockKey.Setup(o => o.ExpirationDate).Returns(DateTimeOffset.ParseExact(expirationDate, "u", CultureInfo.InvariantCulture)); mockKey.Setup(o => o.IsRevoked).Returns(isRevoked); mockKey.Setup(o => o.Descriptor).Returns(new Mock().Object); + mockKey.Setup(o => o.CreateEncryptor()).Returns(new Mock().Object); return mockKey.Object; } } diff --git a/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyRingTests.cs b/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyRingTests.cs index 915b4704cc..4d137986fa 100644 --- a/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyRingTests.cs +++ b/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyRingTests.cs @@ -16,20 +16,19 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement { // Arrange var expectedEncryptorInstance = new Mock().Object; - var encryptorFactory = new MyEncryptorFactory(expectedEncryptorInstance); - var key1 = new MyKey(); + var key1 = new MyKey(expectedEncryptorInstance: expectedEncryptorInstance); var key2 = new MyKey(); // Act - var keyRing = new KeyRing(key1, new[] { key1, key2 }, new[] { encryptorFactory }); + var keyRing = new KeyRing(key1, new[] { key1, key2 }); // Assert - Assert.Equal(0, encryptorFactory.NumTimesCreateEncryptorInstanceCalled); + Assert.Equal(0, key1.NumTimesCreateEncryptorInstanceCalled); Assert.Same(expectedEncryptorInstance, keyRing.DefaultAuthenticatedEncryptor); - Assert.Equal(1, encryptorFactory.NumTimesCreateEncryptorInstanceCalled); + Assert.Equal(1, key1.NumTimesCreateEncryptorInstanceCalled); Assert.Same(expectedEncryptorInstance, keyRing.DefaultAuthenticatedEncryptor); - Assert.Equal(1, encryptorFactory.NumTimesCreateEncryptorInstanceCalled); // should've been cached + Assert.Equal(1, key1.NumTimesCreateEncryptorInstanceCalled); // should've been cached } [Fact] @@ -38,10 +37,9 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement // Arrange var key1 = new MyKey(); var key2 = new MyKey(); - var encryptorFactory = new MyEncryptorFactory(); // Act - var keyRing = new KeyRing(key2, new[] { key1, key2 }, new[] { encryptorFactory }); + var keyRing = new KeyRing(key2, new[] { key1, key2 }); // Assert Assert.Equal(key2.KeyId, keyRing.DefaultKeyId); @@ -53,16 +51,15 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement // Arrange var key1 = new MyKey(); var key2 = new MyKey(); - var key3 = new MyKey(); - var encryptorFactory = new MyEncryptorFactory(expectedEncryptorInstance: new Mock().Object); + var key3 = new MyKey(expectedEncryptorInstance: new Mock().Object); // Act - var keyRing = new KeyRing(key3, new[] { key1, key2 }, new[] { encryptorFactory }); + var keyRing = new KeyRing(key3, new[] { key1, key2 }); // Assert bool unused; Assert.Equal(key3.KeyId, keyRing.DefaultKeyId); - Assert.Equal(encryptorFactory.CreateEncryptorInstance(key3), keyRing.GetAuthenticatedEncryptorByKeyId(key3.KeyId, out unused)); + Assert.Equal(key3.CreateEncryptor(), keyRing.GetAuthenticatedEncryptorByKeyId(key3.KeyId, out unused)); } [Fact] @@ -72,44 +69,46 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement var expectedEncryptorInstance1 = new Mock().Object; var expectedEncryptorInstance2 = new Mock().Object; - var key1 = new MyKey(isRevoked: true); - var key2 = new MyKey(); + var key1 = new MyKey(expectedEncryptorInstance: expectedEncryptorInstance1, isRevoked: true); + var key2 = new MyKey(expectedEncryptorInstance: expectedEncryptorInstance2); - var encryptorFactory1 = new MyEncryptorFactory(expectedEncryptorInstance: expectedEncryptorInstance1, associatedKey: key1); - var encryptorFactory2 = new MyEncryptorFactory(expectedEncryptorInstance: expectedEncryptorInstance2, associatedKey: key2); // Act - var keyRing = new KeyRing(key2, new[] { key1, key2 }, new[] { encryptorFactory1, encryptorFactory2 }); + var keyRing = new KeyRing(key2, new[] { key1, key2 }); // Assert bool isRevoked; - Assert.Equal(0, encryptorFactory1.NumTimesCreateEncryptorInstanceCalled); + Assert.Equal(0, key1.NumTimesCreateEncryptorInstanceCalled); Assert.Same(expectedEncryptorInstance1, keyRing.GetAuthenticatedEncryptorByKeyId(key1.KeyId, out isRevoked)); Assert.True(isRevoked); - Assert.Equal(1, encryptorFactory1.NumTimesCreateEncryptorInstanceCalled); + Assert.Equal(1, key1.NumTimesCreateEncryptorInstanceCalled); Assert.Same(expectedEncryptorInstance1, keyRing.GetAuthenticatedEncryptorByKeyId(key1.KeyId, out isRevoked)); Assert.True(isRevoked); - Assert.Equal(1, encryptorFactory1.NumTimesCreateEncryptorInstanceCalled); - Assert.Equal(0, encryptorFactory2.NumTimesCreateEncryptorInstanceCalled); + Assert.Equal(1, key1.NumTimesCreateEncryptorInstanceCalled); + Assert.Equal(0, key2.NumTimesCreateEncryptorInstanceCalled); Assert.Same(expectedEncryptorInstance2, keyRing.GetAuthenticatedEncryptorByKeyId(key2.KeyId, out isRevoked)); Assert.False(isRevoked); - Assert.Equal(1, encryptorFactory2.NumTimesCreateEncryptorInstanceCalled); + Assert.Equal(1, key2.NumTimesCreateEncryptorInstanceCalled); Assert.Same(expectedEncryptorInstance2, keyRing.GetAuthenticatedEncryptorByKeyId(key2.KeyId, out isRevoked)); Assert.False(isRevoked); - Assert.Equal(1, encryptorFactory2.NumTimesCreateEncryptorInstanceCalled); + Assert.Equal(1, key2.NumTimesCreateEncryptorInstanceCalled); Assert.Same(expectedEncryptorInstance2, keyRing.DefaultAuthenticatedEncryptor); - Assert.Equal(1, encryptorFactory2.NumTimesCreateEncryptorInstanceCalled); + Assert.Equal(1, key2.NumTimesCreateEncryptorInstanceCalled); } private sealed class MyKey : IKey { - public MyKey(bool isRevoked = false) + public int NumTimesCreateEncryptorInstanceCalled; + private readonly Func _encryptorFactory; + + public MyKey(bool isRevoked = false, IAuthenticatedEncryptor expectedEncryptorInstance = null) { CreationDate = DateTimeOffset.Now; ActivationDate = CreationDate + TimeSpan.FromHours(1); ExpirationDate = CreationDate + TimeSpan.FromDays(30); IsRevoked = isRevoked; KeyId = Guid.NewGuid(); + _encryptorFactory = () => expectedEncryptorInstance ?? new Mock().Object; } public DateTimeOffset ActivationDate { get; } @@ -118,30 +117,11 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement public bool IsRevoked { get; } public Guid KeyId { get; } public IAuthenticatedEncryptorDescriptor Descriptor => throw new NotImplementedException(); - } - private sealed class MyEncryptorFactory : IAuthenticatedEncryptorFactory - { - public int NumTimesCreateEncryptorInstanceCalled; - private IAuthenticatedEncryptor _expectedEncryptorInstance; - private IKey _associatedKey; - - public MyEncryptorFactory(IAuthenticatedEncryptor expectedEncryptorInstance = null, IKey associatedKey = null) + public IAuthenticatedEncryptor CreateEncryptor() { - _expectedEncryptorInstance = expectedEncryptorInstance; - _associatedKey = associatedKey; - } - - public IAuthenticatedEncryptor CreateEncryptorInstance(IKey key) - { - if (_associatedKey != null && key != _associatedKey) - { - return null; - } - NumTimesCreateEncryptorInstanceCalled++; - - return _expectedEncryptorInstance ?? new Mock().Object; + return _encryptorFactory(); } } } diff --git a/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyTests.cs b/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyTests.cs index 5a2053737e..6aa691723d 100644 --- a/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyTests.cs +++ b/test/Microsoft.AspNetCore.DataProtection.Test/KeyManagement/KeyTests.cs @@ -5,6 +5,7 @@ using System; using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; using Moq; using Xunit; +using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; namespace Microsoft.AspNetCore.DataProtection.KeyManagement { @@ -19,9 +20,10 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement var activationDate = creationDate.AddDays(2); var expirationDate = creationDate.AddDays(90); var descriptor = Mock.Of(); + var encryptorFactory = Mock.Of(); // Act - var key = new Key(keyId, creationDate, activationDate, expirationDate, descriptor); + var key = new Key(keyId, creationDate, activationDate, expirationDate, descriptor, new[] { encryptorFactory }); // Assert Assert.Equal(keyId, key.KeyId); @@ -36,7 +38,8 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement { // Arrange var now = DateTimeOffset.UtcNow; - var key = new Key(Guid.Empty, now, now, now, new Mock().Object); + var encryptorFactory = Mock.Of(); + var key = new Key(Guid.Empty, now, now, now, new Mock().Object, new[] { encryptorFactory }); // Act & assert Assert.False(key.IsRevoked);