// 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.Xml.Linq; using Microsoft.AspNet.Cryptography; using Microsoft.AspNet.DataProtection.Cng; using Microsoft.Framework.Internal; using Microsoft.Framework.Logging; namespace Microsoft.AspNet.DataProtection.XmlEncryption { /// /// An that decrypts XML elements that were encrypted with . /// /// /// This API is only supported on Windows 8 / Windows Server 2012 and higher. /// public sealed class DpapiNGXmlDecryptor : IXmlDecryptor { private readonly ILogger _logger; /// /// Creates a new instance of a . /// public DpapiNGXmlDecryptor() : this(services: null) { } /// /// Creates a new instance of a . /// /// An optional to provide ancillary services. public DpapiNGXmlDecryptor(IServiceProvider services) { CryptoUtil.AssertPlatformIsWindows8OrLater(); _logger = services.GetLogger(); } /// /// Decrypts the specified XML element. /// /// An encrypted XML element. /// The decrypted form of . /// public XElement Decrypt([NotNull] XElement encryptedElement) { try { // // // // {base64} // byte[] protectedSecret = Convert.FromBase64String((string)encryptedElement.Element("value")); if (_logger.IsVerboseLevelEnabled()) { string protectionDescriptorRule; try { protectionDescriptorRule = DpapiSecretSerializerHelper.GetRuleFromDpapiNGProtectedPayload(protectedSecret); } catch { // swallow all errors - it's just a log protectionDescriptorRule = null; } _logger.LogVerbose("Decrypting secret element using Windows DPAPI-NG with protection descriptor '{0}'.", protectionDescriptorRule); } using (Secret secret = DpapiSecretSerializerHelper.UnprotectWithDpapiNG(protectedSecret)) { return secret.ToXElement(); } } catch (Exception ex) { // It's OK for us to log the error, as we control the exception, and it doesn't contain // sensitive information. if (_logger.IsErrorLevelEnabled()) { _logger.LogError(ex, "An exception occurred while trying to decrypt the element."); } throw; } } } }