EncryptedXmlDecryptor.cs 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. // Copyright (c) .NET Foundation. All rights reserved.
  2. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
  3. using System;
  4. using System.Security.Cryptography.Xml;
  5. using System.Xml;
  6. using System.Xml.Linq;
  7. using Microsoft.Extensions.DependencyInjection;
  8. namespace Microsoft.AspNetCore.DataProtection.XmlEncryption
  9. {
  10. /// <summary>
  11. /// An <see cref="IXmlDecryptor"/> that decrypts XML elements by using the <see cref="EncryptedXml"/> class.
  12. /// </summary>
  13. public sealed class EncryptedXmlDecryptor : IInternalEncryptedXmlDecryptor, IXmlDecryptor
  14. {
  15. private readonly IInternalEncryptedXmlDecryptor _decryptor;
  16. /// <summary>
  17. /// Creates a new instance of an <see cref="EncryptedXmlDecryptor"/>.
  18. /// </summary>
  19. public EncryptedXmlDecryptor()
  20. : this(services: null)
  21. {
  22. }
  23. /// <summary>
  24. /// Creates a new instance of an <see cref="EncryptedXmlDecryptor"/>.
  25. /// </summary>
  26. /// <param name="services">An optional <see cref="IServiceProvider"/> to provide ancillary services.</param>
  27. public EncryptedXmlDecryptor(IServiceProvider services)
  28. {
  29. _decryptor = services?.GetService<IInternalEncryptedXmlDecryptor>() ?? this;
  30. }
  31. /// <summary>
  32. /// Decrypts the specified XML element.
  33. /// </summary>
  34. /// <param name="encryptedElement">An encrypted XML element.</param>
  35. /// <returns>The decrypted form of <paramref name="encryptedElement"/>.</returns>
  36. public XElement Decrypt(XElement encryptedElement)
  37. {
  38. if (encryptedElement == null)
  39. {
  40. throw new ArgumentNullException(nameof(encryptedElement));
  41. }
  42. // <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns="http://www.w3.org/2001/04/xmlenc#">
  43. // ...
  44. // </EncryptedData>
  45. // EncryptedXml works with XmlDocument, not XLinq. When we perform the conversion
  46. // we'll wrap the incoming element in a dummy <root /> element since encrypted XML
  47. // doesn't handle encrypting the root element all that well.
  48. var xmlDocument = new XmlDocument();
  49. xmlDocument.Load(new XElement("root", encryptedElement).CreateReader());
  50. var elementToDecrypt = (XmlElement)xmlDocument.DocumentElement.FirstChild;
  51. // Perform the decryption and update the document in-place.
  52. var encryptedXml = new EncryptedXml(xmlDocument);
  53. _decryptor.PerformPreDecryptionSetup(encryptedXml);
  54. encryptedXml.DecryptDocument();
  55. // Strip the <root /> element back off and convert the XmlDocument to an XElement.
  56. return XElement.Load(xmlDocument.DocumentElement.FirstChild.CreateNavigator().ReadSubtree());
  57. }
  58. void IInternalEncryptedXmlDecryptor.PerformPreDecryptionSetup(EncryptedXml encryptedXml)
  59. {
  60. // no-op
  61. }
  62. }
  63. }