// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Linq; using System.Xml.Linq; using Microsoft.AspNet.Security.DataProtection.XmlEncryption; using Microsoft.Framework.DependencyInjection; namespace Microsoft.AspNet.Security.DataProtection.AuthenticatedEncryption { internal sealed class CngCbcAuthenticatedEncryptorConfigurationXmlReader : IAuthenticatedEncryptorConfigurationXmlReader { private readonly IServiceProvider _serviceProvider; private readonly ITypeActivator _typeActivator; public CngCbcAuthenticatedEncryptorConfigurationXmlReader( [NotNull] IServiceProvider serviceProvider, [NotNull] ITypeActivator typeActivator) { _serviceProvider = serviceProvider; _typeActivator = typeActivator; } public IAuthenticatedEncryptorConfiguration FromXml([NotNull] XElement element) { // // // // ... // CryptoUtil.Assert(element.Name == CngCbcAuthenticatedEncryptorConfiguration.CbcEncryptorElementName, @"TODO: Bad element."); var options = new CngCbcAuthenticatedEncryptorConfigurationOptions(); // read element var encryptionElement = element.Element(CngCbcAuthenticatedEncryptorConfiguration.EncryptionElementName); options.EncryptionAlgorithm = (string)encryptionElement.Attribute("algorithm"); options.EncryptionAlgorithmProvider = (string)encryptionElement.Attribute("provider"); options.EncryptionAlgorithmKeySize = (int)encryptionElement.Attribute("keyLength"); // read element var validationElement = element.Element(CngCbcAuthenticatedEncryptorConfiguration.ValidationElementName); options.HashAlgorithm = (string)validationElement.Attribute("algorithm"); options.HashAlgorithmProvider = (string)validationElement.Attribute("provider"); // read the child of the element, then decrypt it var encryptedSecretElement = element.Element(CngCbcAuthenticatedEncryptorConfiguration.SecretElementName).Elements().Single(); var secretElementDecryptorTypeName = (string)encryptedSecretElement.Attribute("decryptor"); var secretElementDecryptorType = Type.GetType(secretElementDecryptorTypeName, throwOnError: true); var secretElementDecryptor = (IXmlDecryptor)_typeActivator.CreateInstance(_serviceProvider, secretElementDecryptorType); var decryptedSecretElement = secretElementDecryptor.Decrypt(encryptedSecretElement); CryptoUtil.Assert(decryptedSecretElement.Name == CngCbcAuthenticatedEncryptorConfiguration.SecretElementName, @"TODO: Bad element."); byte[] decryptedSecretBytes = Convert.FromBase64String((string)decryptedSecretElement); try { var protectedMemoryBlob = new ProtectedMemoryBlob(decryptedSecretBytes); return new CngCbcAuthenticatedEncryptorConfiguration(options, protectedMemoryBlob); } finally { Array.Clear(decryptedSecretBytes, 0, decryptedSecretBytes.Length); } } } }