예제 #1
0
        public void RevokeKey_CallsInternalManager()
        {
            // Arrange - mocks
            var            keyToRevoke            = new Guid("a11f35fc-1fed-4bd4-b727-056a63b70932");
            DateTimeOffset minRevocationDate      = DateTimeOffset.UtcNow;
            DateTimeOffset?actualRevocationDate   = null;
            var            mockInternalKeyManager = new Mock <IInternalXmlKeyManager>();

            mockInternalKeyManager
            .Setup(o => o.RevokeSingleKey(keyToRevoke, It.IsAny <DateTimeOffset>(), "Here's some reason text."))
            .Callback <Guid, DateTimeOffset, string>((innerKeyId, innerRevocationDate, innerReason) =>
            {
                actualRevocationDate = innerRevocationDate;
            });

            // Arrange - services
            var serviceCollection = new ServiceCollection();

            serviceCollection.AddInstance <IXmlRepository>(new Mock <IXmlRepository>().Object);
            serviceCollection.AddInstance <IAuthenticatedEncryptorConfiguration>(new Mock <IAuthenticatedEncryptorConfiguration>().Object);
            serviceCollection.AddInstance <IInternalXmlKeyManager>(mockInternalKeyManager.Object);
            var services   = serviceCollection.BuildServiceProvider();
            var keyManager = new XmlKeyManager(services);

            // Act
            keyManager.RevokeKey(keyToRevoke, "Here's some reason text.");

            // Assert
            Assert.InRange(actualRevocationDate.Value, minRevocationDate, DateTimeOffset.UtcNow);
        }
예제 #2
0
        public void CreateNewKey_CallsInternalManager()
        {
            // Arrange - mocks
            DateTimeOffset minCreationDate        = DateTimeOffset.UtcNow;
            DateTimeOffset?actualCreationDate     = null;
            DateTimeOffset activationDate         = minCreationDate + TimeSpan.FromDays(7);
            DateTimeOffset expirationDate         = activationDate.AddMonths(1);
            var            mockInternalKeyManager = new Mock <IInternalXmlKeyManager>();

            mockInternalKeyManager
            .Setup(o => o.CreateNewKey(It.IsAny <Guid>(), It.IsAny <DateTimeOffset>(), activationDate, expirationDate))
            .Callback <Guid, DateTimeOffset, DateTimeOffset, DateTimeOffset>((innerKeyId, innerCreationDate, innerActivationDate, innerExpirationDate) =>
            {
                actualCreationDate = innerCreationDate;
            });

            // Arrange - services
            var serviceCollection = new ServiceCollection();

            serviceCollection.AddInstance <IXmlRepository>(new Mock <IXmlRepository>().Object);
            serviceCollection.AddInstance <IAuthenticatedEncryptorConfiguration>(new Mock <IAuthenticatedEncryptorConfiguration>().Object);
            serviceCollection.AddInstance <IInternalXmlKeyManager>(mockInternalKeyManager.Object);
            var services   = serviceCollection.BuildServiceProvider();
            var keyManager = new XmlKeyManager(services);

            // Act
            keyManager.CreateNewKey(activationDate, expirationDate);

            // Assert
            Assert.InRange(actualCreationDate.Value, minCreationDate, DateTimeOffset.UtcNow);
        }
예제 #3
0
        public void RevokeSingleKey_Internal()
        {
            // Arrange - mocks
            XElement elementStoredInRepository      = null;
            string   friendlyNameStoredInRepository = null;
            var      mockXmlRepository = new Mock <IXmlRepository>();

            mockXmlRepository
            .Setup(o => o.StoreElement(It.IsAny <XElement>(), It.IsAny <string>()))
            .Callback <XElement, string>((el, friendlyName) =>
            {
                elementStoredInRepository      = el;
                friendlyNameStoredInRepository = friendlyName;
            });

            // Arrange - services
            var serviceCollection = new ServiceCollection();

            serviceCollection.AddInstance <IXmlRepository>(mockXmlRepository.Object);
            serviceCollection.AddInstance <IAuthenticatedEncryptorConfiguration>(new Mock <IAuthenticatedEncryptorConfiguration>().Object);
            var services   = serviceCollection.BuildServiceProvider();
            var keyManager = new XmlKeyManager(services);

            var revocationDate = new DateTimeOffset(2014, 01, 01, 0, 0, 0, TimeSpan.Zero);

            // Act & assert

            // The cancellation token should not already be fired
            var firstCancellationToken = keyManager.GetCacheExpirationToken();

            Assert.False(firstCancellationToken.IsCancellationRequested);

            // After the call to RevokeKey, the first CT should be fired,
            // and we should've gotten a new CT.
            ((IInternalXmlKeyManager)keyManager).RevokeSingleKey(
                keyId: new Guid("a11f35fc-1fed-4bd4-b727-056a63b70932"),
                revocationDate: revocationDate,
                reason: "Here's some reason text.");
            var secondCancellationToken = keyManager.GetCacheExpirationToken();

            Assert.True(firstCancellationToken.IsCancellationRequested);
            Assert.False(secondCancellationToken.IsCancellationRequested);

            // Was the correct element stored in the repository?
            var expectedRepositoryXml = string.Format(@"
                <revocation version='1'>
                  {0}
                  <key id='a11f35fc-1fed-4bd4-b727-056a63b70932' />
                  <reason>Here's some reason text.</reason>
                </revocation>",
                                                      new XElement("revocationDate", revocationDate));

            XmlAssert.Equal(expectedRepositoryXml, elementStoredInRepository);
            Assert.Equal("revocation-a11f35fc-1fed-4bd4-b727-056a63b70932", friendlyNameStoredInRepository);
        }
예제 #4
0
        public void RevokeAllKeys()
        {
            // Arrange - mocks
            XElement elementStoredInRepository      = null;
            string   friendlyNameStoredInRepository = null;
            var      mockXmlRepository = new Mock <IXmlRepository>();

            mockXmlRepository
            .Setup(o => o.StoreElement(It.IsAny <XElement>(), It.IsAny <string>()))
            .Callback <XElement, string>((el, friendlyName) =>
            {
                elementStoredInRepository      = el;
                friendlyNameStoredInRepository = friendlyName;
            });

            // Arrange - services
            var serviceCollection = new ServiceCollection();

            serviceCollection.AddInstance <IXmlRepository>(mockXmlRepository.Object);
            serviceCollection.AddInstance <IAuthenticatedEncryptorConfiguration>(new Mock <IAuthenticatedEncryptorConfiguration>().Object);
            var services   = serviceCollection.BuildServiceProvider();
            var keyManager = new XmlKeyManager(services);

            var revocationDate = XmlConvert.ToDateTimeOffset("2015-03-01T19:13:19.7573854-08:00");

            // Act & assert

            // The cancellation token should not already be fired
            var firstCancellationToken = keyManager.GetCacheExpirationToken();

            Assert.False(firstCancellationToken.IsCancellationRequested);

            // After the call to RevokeAllKeys, the first CT should be fired,
            // and we should've gotten a new CT.
            keyManager.RevokeAllKeys(revocationDate, "Here's some reason text.");
            var secondCancellationToken = keyManager.GetCacheExpirationToken();

            Assert.True(firstCancellationToken.IsCancellationRequested);
            Assert.False(secondCancellationToken.IsCancellationRequested);

            // Was the correct element stored in the repository?
            const string expectedRepositoryXml = @"
                <revocation version='1'>
                  <revocationDate>2015-03-01T19:13:19.7573854-08:00</revocationDate>
                  <!--All keys created before the revocation date are revoked.-->
                  <key id='*' />
                  <reason>Here's some reason text.</reason>
                </revocation>";

            XmlAssert.Equal(expectedRepositoryXml, elementStoredInRepository);
            Assert.Equal("revocation-20150302T0313197573854Z", friendlyNameStoredInRepository);
        }
        public void Ctor_WithoutEncryptorOrRepository_UsesFallback()
        {
            // Arrange
            var expectedEncryptor = new Mock<IXmlEncryptor>().Object;
            var expectedRepository = new Mock<IXmlRepository>().Object;
            var mockFallback = new Mock<IDefaultKeyServices>();
            mockFallback.Setup(o => o.GetKeyEncryptor()).Returns(expectedEncryptor);
            mockFallback.Setup(o => o.GetKeyRepository()).Returns(expectedRepository);

            var serviceCollection = new ServiceCollection();
            serviceCollection.AddSingleton<IDefaultKeyServices>(mockFallback.Object);
            serviceCollection.AddSingleton<IAuthenticatedEncryptorConfiguration>(new Mock<IAuthenticatedEncryptorConfiguration>().Object);
            var services = serviceCollection.BuildServiceProvider();

            // Act
            var keyManager = new XmlKeyManager(services);

            // Assert
            Assert.Same(expectedEncryptor, keyManager.KeyEncryptor);
            Assert.Same(expectedRepository, keyManager.KeyRepository);
        }
예제 #6
0
        private static IReadOnlyCollection <IKey> RunGetAllKeysCore(string xml, IActivator activator, ILoggerFactory loggerFactory = null)
        {
            // Arrange - mocks
            var mockXmlRepository = new Mock <IXmlRepository>();

            mockXmlRepository.Setup(o => o.GetAllElements()).Returns(XElement.Parse(xml).Elements().ToArray());

            // Arrange - services
            var serviceCollection = new ServiceCollection();

            serviceCollection.AddInstance <IXmlRepository>(mockXmlRepository.Object);
            serviceCollection.AddInstance <IActivator>(activator);
            serviceCollection.AddInstance <IAuthenticatedEncryptorConfiguration>(new Mock <IAuthenticatedEncryptorConfiguration>().Object);
            if (loggerFactory != null)
            {
                serviceCollection.AddInstance <ILoggerFactory>(loggerFactory);
            }
            var services   = serviceCollection.BuildServiceProvider();
            var keyManager = new XmlKeyManager(services);

            // Act
            return(keyManager.GetAllKeys());
        }
예제 #7
0
        public void Ctor_WithoutEncryptorOrRepository_UsesFallback()
        {
            // Arrange
            var expectedEncryptor  = new Mock <IXmlEncryptor>().Object;
            var expectedRepository = new Mock <IXmlRepository>().Object;
            var mockFallback       = new Mock <IDefaultKeyServices>();

            mockFallback.Setup(o => o.GetKeyEncryptor()).Returns(expectedEncryptor);
            mockFallback.Setup(o => o.GetKeyRepository()).Returns(expectedRepository);

            var serviceCollection = new ServiceCollection();

            serviceCollection.AddInstance <IDefaultKeyServices>(mockFallback.Object);
            serviceCollection.AddInstance <IAuthenticatedEncryptorConfiguration>(new Mock <IAuthenticatedEncryptorConfiguration>().Object);
            var services = serviceCollection.BuildServiceProvider();

            // Act
            var keyManager = new XmlKeyManager(services);

            // Assert
            Assert.Same(expectedEncryptor, keyManager.KeyEncryptor);
            Assert.Same(expectedRepository, keyManager.KeyRepository);
        }
        public void CreateNewKey_Internal_NoEscrowOrEncryption()
        {
            // Constants
            var creationDate = new DateTimeOffset(2014, 01, 01, 0, 0, 0, TimeSpan.Zero);
            var activationDate = new DateTimeOffset(2014, 02, 01, 0, 0, 0, TimeSpan.Zero);
            var expirationDate = new DateTimeOffset(2014, 03, 01, 0, 0, 0, TimeSpan.Zero);
            var keyId = new Guid("3d6d01fd-c0e7-44ae-82dd-013b996b4093");

            // Arrange - mocks
            XElement elementStoredInRepository = null;
            string friendlyNameStoredInRepository = null;
            var expectedAuthenticatedEncryptor = new Mock<IAuthenticatedEncryptor>().Object;
            var mockDescriptor = new Mock<IAuthenticatedEncryptorDescriptor>();
            mockDescriptor.Setup(o => o.ExportToXml()).Returns(new XmlSerializedDescriptorInfo(serializedDescriptor, typeof(MyDeserializer)));
            mockDescriptor.Setup(o => o.CreateEncryptorInstance()).Returns(expectedAuthenticatedEncryptor);
            var mockConfiguration = new Mock<IAuthenticatedEncryptorConfiguration>();
            mockConfiguration.Setup(o => o.CreateNewDescriptor()).Returns(mockDescriptor.Object);
            var mockXmlRepository = new Mock<IXmlRepository>();
            mockXmlRepository
                .Setup(o => o.StoreElement(It.IsAny<XElement>(), It.IsAny<string>()))
                .Callback<XElement, string>((el, friendlyName) =>
                {
                    elementStoredInRepository = el;
                    friendlyNameStoredInRepository = friendlyName;
                });

            // Arrange - services
            var serviceCollection = new ServiceCollection();
            serviceCollection.AddSingleton<IXmlRepository>(mockXmlRepository.Object);
            serviceCollection.AddSingleton<IAuthenticatedEncryptorConfiguration>(mockConfiguration.Object);
            var services = serviceCollection.BuildServiceProvider();
            var keyManager = new XmlKeyManager(services);

            // Act & assert

            // The cancellation token should not already be fired
            var firstCancellationToken = keyManager.GetCacheExpirationToken();
            Assert.False(firstCancellationToken.IsCancellationRequested);

            // After the call to CreateNewKey, the first CT should be fired,
            // and we should've gotten a new CT.
            var newKey = ((IInternalXmlKeyManager)keyManager).CreateNewKey(
                keyId: keyId,
                creationDate: creationDate,
                activationDate: activationDate,
                expirationDate: expirationDate);
            var secondCancellationToken = keyManager.GetCacheExpirationToken();
            Assert.True(firstCancellationToken.IsCancellationRequested);
            Assert.False(secondCancellationToken.IsCancellationRequested);

            // Does the IKey have the properties we requested?
            Assert.Equal(keyId, newKey.KeyId);
            Assert.Equal(creationDate, newKey.CreationDate);
            Assert.Equal(activationDate, newKey.ActivationDate);
            Assert.Equal(expirationDate, newKey.ExpirationDate);
            Assert.False(newKey.IsRevoked);
            Assert.Same(expectedAuthenticatedEncryptor, newKey.CreateEncryptorInstance());

            // Finally, was the correct element stored in the repository?
            string expectedXml = String.Format(@"
                <key id='3d6d01fd-c0e7-44ae-82dd-013b996b4093' version='1' xmlns:enc='http://schemas.asp.net/2015/03/dataProtection'>
                  {1}
                  {2}
                  {3}
                  <descriptor deserializerType='{0}'>
                    <theElement>
                      <secret enc:requiresEncryption='true'>
                        <![CDATA[This is a secret value.]]>
                      </secret>
                    </theElement>
                  </descriptor>
                </key>",
                typeof(MyDeserializer).AssemblyQualifiedName,
                new XElement("creationDate", creationDate),
                new XElement("activationDate", activationDate),
                new XElement("expirationDate", expirationDate));
            XmlAssert.Equal(expectedXml, elementStoredInRepository);
            Assert.Equal("key-3d6d01fd-c0e7-44ae-82dd-013b996b4093", friendlyNameStoredInRepository);
        }
        public void RevokeKey_CallsInternalManager()
        {
            // Arrange - mocks
            var keyToRevoke = new Guid("a11f35fc-1fed-4bd4-b727-056a63b70932");
            DateTimeOffset minRevocationDate = DateTimeOffset.UtcNow;
            DateTimeOffset? actualRevocationDate = null;
            var mockInternalKeyManager = new Mock<IInternalXmlKeyManager>();
            mockInternalKeyManager
                .Setup(o => o.RevokeSingleKey(keyToRevoke, It.IsAny<DateTimeOffset>(), "Here's some reason text."))
                .Callback<Guid, DateTimeOffset, string>((innerKeyId, innerRevocationDate, innerReason) =>
                {
                    actualRevocationDate = innerRevocationDate;
                });

            // Arrange - services
            var serviceCollection = new ServiceCollection();
            serviceCollection.AddSingleton<IXmlRepository>(new Mock<IXmlRepository>().Object);
            serviceCollection.AddSingleton<IAuthenticatedEncryptorConfiguration>(new Mock<IAuthenticatedEncryptorConfiguration>().Object);
            serviceCollection.AddSingleton<IInternalXmlKeyManager>(mockInternalKeyManager.Object);
            var services = serviceCollection.BuildServiceProvider();
            var keyManager = new XmlKeyManager(services);

            // Act
            keyManager.RevokeKey(keyToRevoke, "Here's some reason text.");

            // Assert
            Assert.InRange(actualRevocationDate.Value, minRevocationDate, DateTimeOffset.UtcNow);
        }
        public void RevokeSingleKey_Internal()
        {
            // Arrange - mocks
            XElement elementStoredInRepository = null;
            string friendlyNameStoredInRepository = null;
            var mockXmlRepository = new Mock<IXmlRepository>();
            mockXmlRepository
                .Setup(o => o.StoreElement(It.IsAny<XElement>(), It.IsAny<string>()))
                .Callback<XElement, string>((el, friendlyName) =>
                {
                    elementStoredInRepository = el;
                    friendlyNameStoredInRepository = friendlyName;
                });

            // Arrange - services
            var serviceCollection = new ServiceCollection();
            serviceCollection.AddSingleton<IXmlRepository>(mockXmlRepository.Object);
            serviceCollection.AddSingleton<IAuthenticatedEncryptorConfiguration>(new Mock<IAuthenticatedEncryptorConfiguration>().Object);
            var services = serviceCollection.BuildServiceProvider();
            var keyManager = new XmlKeyManager(services);

            var revocationDate = new DateTimeOffset(2014, 01, 01, 0, 0, 0, TimeSpan.Zero);

            // Act & assert

            // The cancellation token should not already be fired
            var firstCancellationToken = keyManager.GetCacheExpirationToken();
            Assert.False(firstCancellationToken.IsCancellationRequested);

            // After the call to RevokeKey, the first CT should be fired,
            // and we should've gotten a new CT.
            ((IInternalXmlKeyManager)keyManager).RevokeSingleKey(
                keyId: new Guid("a11f35fc-1fed-4bd4-b727-056a63b70932"),
                revocationDate: revocationDate,
                reason: "Here's some reason text.");
            var secondCancellationToken = keyManager.GetCacheExpirationToken();
            Assert.True(firstCancellationToken.IsCancellationRequested);
            Assert.False(secondCancellationToken.IsCancellationRequested);

            // Was the correct element stored in the repository?
            var expectedRepositoryXml = string.Format(@"
                <revocation version='1'>
                  {0}
                  <key id='a11f35fc-1fed-4bd4-b727-056a63b70932' />
                  <reason>Here's some reason text.</reason>
                </revocation>",
                new XElement("revocationDate", revocationDate));
            XmlAssert.Equal(expectedRepositoryXml, elementStoredInRepository);
            Assert.Equal("revocation-a11f35fc-1fed-4bd4-b727-056a63b70932", friendlyNameStoredInRepository);
        }
        public void RevokeAllKeys()
        {
            // Arrange - mocks
            XElement elementStoredInRepository = null;
            string friendlyNameStoredInRepository = null;
            var mockXmlRepository = new Mock<IXmlRepository>();
            mockXmlRepository
                .Setup(o => o.StoreElement(It.IsAny<XElement>(), It.IsAny<string>()))
                .Callback<XElement, string>((el, friendlyName) =>
                {
                    elementStoredInRepository = el;
                    friendlyNameStoredInRepository = friendlyName;
                });

            // Arrange - services
            var serviceCollection = new ServiceCollection();
            serviceCollection.AddSingleton<IXmlRepository>(mockXmlRepository.Object);
            serviceCollection.AddSingleton<IAuthenticatedEncryptorConfiguration>(new Mock<IAuthenticatedEncryptorConfiguration>().Object);
            var services = serviceCollection.BuildServiceProvider();
            var keyManager = new XmlKeyManager(services);

            var revocationDate = XmlConvert.ToDateTimeOffset("2015-03-01T19:13:19.7573854-08:00");

            // Act & assert

            // The cancellation token should not already be fired
            var firstCancellationToken = keyManager.GetCacheExpirationToken();
            Assert.False(firstCancellationToken.IsCancellationRequested);

            // After the call to RevokeAllKeys, the first CT should be fired,
            // and we should've gotten a new CT.
            keyManager.RevokeAllKeys(revocationDate, "Here's some reason text.");
            var secondCancellationToken = keyManager.GetCacheExpirationToken();
            Assert.True(firstCancellationToken.IsCancellationRequested);
            Assert.False(secondCancellationToken.IsCancellationRequested);

            // Was the correct element stored in the repository?
            const string expectedRepositoryXml = @"
                <revocation version='1'>
                  <revocationDate>2015-03-01T19:13:19.7573854-08:00</revocationDate>
                  <!--All keys created before the revocation date are revoked.-->
                  <key id='*' />
                  <reason>Here's some reason text.</reason>
                </revocation>";
            XmlAssert.Equal(expectedRepositoryXml, elementStoredInRepository);
            Assert.Equal("revocation-20150302T0313197573854Z", friendlyNameStoredInRepository);
        }
        private static IReadOnlyCollection<IKey> RunGetAllKeysCore(string xml, IActivator activator, ILoggerFactory loggerFactory = null)
        {
            // Arrange - mocks
            var mockXmlRepository = new Mock<IXmlRepository>();
            mockXmlRepository.Setup(o => o.GetAllElements()).Returns(XElement.Parse(xml).Elements().ToArray());

            // Arrange - services
            var serviceCollection = new ServiceCollection();
            serviceCollection.AddSingleton<IXmlRepository>(mockXmlRepository.Object);
            serviceCollection.AddSingleton<IActivator>(activator);
            serviceCollection.AddSingleton<IAuthenticatedEncryptorConfiguration>(new Mock<IAuthenticatedEncryptorConfiguration>().Object);
            if (loggerFactory != null)
            {
                serviceCollection.AddSingleton<ILoggerFactory>(loggerFactory);
            }
            var services = serviceCollection.BuildServiceProvider();
            var keyManager = new XmlKeyManager(services);

            // Act
            return keyManager.GetAllKeys();
        }
        public void CreateNewKey_CallsInternalManager()
        {
            // Arrange - mocks
            DateTimeOffset minCreationDate = DateTimeOffset.UtcNow;
            DateTimeOffset? actualCreationDate = null;
            DateTimeOffset activationDate = minCreationDate + TimeSpan.FromDays(7);
            DateTimeOffset expirationDate = activationDate.AddMonths(1);
            var mockInternalKeyManager = new Mock<IInternalXmlKeyManager>();
            mockInternalKeyManager
                .Setup(o => o.CreateNewKey(It.IsAny<Guid>(), It.IsAny<DateTimeOffset>(), activationDate, expirationDate))
                .Callback<Guid, DateTimeOffset, DateTimeOffset, DateTimeOffset>((innerKeyId, innerCreationDate, innerActivationDate, innerExpirationDate) =>
                {
                    actualCreationDate = innerCreationDate;
                });

            // Arrange - services
            var serviceCollection = new ServiceCollection();
            serviceCollection.AddSingleton<IXmlRepository>(new Mock<IXmlRepository>().Object);
            serviceCollection.AddSingleton<IAuthenticatedEncryptorConfiguration>(new Mock<IAuthenticatedEncryptorConfiguration>().Object);
            serviceCollection.AddSingleton<IInternalXmlKeyManager>(mockInternalKeyManager.Object);
            var services = serviceCollection.BuildServiceProvider();
            var keyManager = new XmlKeyManager(services);

            // Act
            keyManager.CreateNewKey(activationDate, expirationDate);

            // Assert
            Assert.InRange(actualCreationDate.Value, minCreationDate, DateTimeOffset.UtcNow);
        }
예제 #14
0
        public void CreateNewKey_Internal_NoEscrowOrEncryption()
        {
            // Constants
            var creationDate   = new DateTimeOffset(2014, 01, 01, 0, 0, 0, TimeSpan.Zero);
            var activationDate = new DateTimeOffset(2014, 02, 01, 0, 0, 0, TimeSpan.Zero);
            var expirationDate = new DateTimeOffset(2014, 03, 01, 0, 0, 0, TimeSpan.Zero);
            var keyId          = new Guid("3d6d01fd-c0e7-44ae-82dd-013b996b4093");

            // Arrange - mocks
            XElement elementStoredInRepository      = null;
            string   friendlyNameStoredInRepository = null;
            var      expectedAuthenticatedEncryptor = new Mock <IAuthenticatedEncryptor>().Object;
            var      mockDescriptor = new Mock <IAuthenticatedEncryptorDescriptor>();

            mockDescriptor.Setup(o => o.ExportToXml()).Returns(new XmlSerializedDescriptorInfo(serializedDescriptor, typeof(MyDeserializer)));
            mockDescriptor.Setup(o => o.CreateEncryptorInstance()).Returns(expectedAuthenticatedEncryptor);
            var mockConfiguration = new Mock <IAuthenticatedEncryptorConfiguration>();

            mockConfiguration.Setup(o => o.CreateNewDescriptor()).Returns(mockDescriptor.Object);
            var mockXmlRepository = new Mock <IXmlRepository>();

            mockXmlRepository
            .Setup(o => o.StoreElement(It.IsAny <XElement>(), It.IsAny <string>()))
            .Callback <XElement, string>((el, friendlyName) =>
            {
                elementStoredInRepository      = el;
                friendlyNameStoredInRepository = friendlyName;
            });

            // Arrange - services
            var serviceCollection = new ServiceCollection();

            serviceCollection.AddInstance <IXmlRepository>(mockXmlRepository.Object);
            serviceCollection.AddInstance <IAuthenticatedEncryptorConfiguration>(mockConfiguration.Object);
            var services   = serviceCollection.BuildServiceProvider();
            var keyManager = new XmlKeyManager(services);

            // Act & assert

            // The cancellation token should not already be fired
            var firstCancellationToken = keyManager.GetCacheExpirationToken();

            Assert.False(firstCancellationToken.IsCancellationRequested);

            // After the call to CreateNewKey, the first CT should be fired,
            // and we should've gotten a new CT.
            var newKey = ((IInternalXmlKeyManager)keyManager).CreateNewKey(
                keyId: keyId,
                creationDate: creationDate,
                activationDate: activationDate,
                expirationDate: expirationDate);
            var secondCancellationToken = keyManager.GetCacheExpirationToken();

            Assert.True(firstCancellationToken.IsCancellationRequested);
            Assert.False(secondCancellationToken.IsCancellationRequested);

            // Does the IKey have the properties we requested?
            Assert.Equal(keyId, newKey.KeyId);
            Assert.Equal(creationDate, newKey.CreationDate);
            Assert.Equal(activationDate, newKey.ActivationDate);
            Assert.Equal(expirationDate, newKey.ExpirationDate);
            Assert.False(newKey.IsRevoked);
            Assert.Same(expectedAuthenticatedEncryptor, newKey.CreateEncryptorInstance());

            // Finally, was the correct element stored in the repository?
            string expectedXml = String.Format(@"
                <key id='3d6d01fd-c0e7-44ae-82dd-013b996b4093' version='1' xmlns:enc='http://schemas.asp.net/2015/03/dataProtection'>
                  {1}
                  {2}
                  {3}
                  <descriptor deserializerType='{0}'>
                    <theElement>
                      <secret enc:requiresEncryption='true'>
                        <![CDATA[This is a secret value.]]>
                      </secret>
                    </theElement>
                  </descriptor>
                </key>",
                                               typeof(MyDeserializer).AssemblyQualifiedName,
                                               new XElement("creationDate", creationDate),
                                               new XElement("activationDate", activationDate),
                                               new XElement("expirationDate", expirationDate));

            XmlAssert.Equal(expectedXml, elementStoredInRepository);
            Assert.Equal("key-3d6d01fd-c0e7-44ae-82dd-013b996b4093", friendlyNameStoredInRepository);
        }