// 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);
}
}
}
}