1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System;
6 using System.Collections;
7 using System.Xml;
8 
9 namespace System.Security.Cryptography.Xml
10 {
11     public sealed class EncryptedKey : EncryptedType
12     {
13         private string _recipient;
14         private string _carriedKeyName;
15         private ReferenceList _referenceList;
16 
EncryptedKey()17         public EncryptedKey() { }
18 
19         public string Recipient
20         {
21             get
22             {
23                 // an unspecified value for an XmlAttribute is string.Empty
24                 if (_recipient == null)
25                     _recipient = string.Empty;
26                 return _recipient;
27             }
28             set
29             {
30                 _recipient = value;
31                 _cachedXml = null;
32             }
33         }
34 
35         public string CarriedKeyName
36         {
37             get { return _carriedKeyName; }
38             set
39             {
40                 _carriedKeyName = value;
41                 _cachedXml = null;
42             }
43         }
44 
45         public ReferenceList ReferenceList
46         {
47             get
48             {
49                 if (_referenceList == null)
50                     _referenceList = new ReferenceList();
51                 return _referenceList;
52             }
53         }
54 
AddReference(DataReference dataReference)55         public void AddReference(DataReference dataReference)
56         {
57             ReferenceList.Add(dataReference);
58         }
59 
AddReference(KeyReference keyReference)60         public void AddReference(KeyReference keyReference)
61         {
62             ReferenceList.Add(keyReference);
63         }
64 
LoadXml(XmlElement value)65         public override void LoadXml(XmlElement value)
66         {
67             if (value == null)
68                 throw new ArgumentNullException(nameof(value));
69 
70             XmlNamespaceManager nsm = new XmlNamespaceManager(value.OwnerDocument.NameTable);
71             nsm.AddNamespace("enc", EncryptedXml.XmlEncNamespaceUrl);
72             nsm.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
73 
74             Id = Utils.GetAttribute(value, "Id", EncryptedXml.XmlEncNamespaceUrl);
75             Type = Utils.GetAttribute(value, "Type", EncryptedXml.XmlEncNamespaceUrl);
76             MimeType = Utils.GetAttribute(value, "MimeType", EncryptedXml.XmlEncNamespaceUrl);
77             Encoding = Utils.GetAttribute(value, "Encoding", EncryptedXml.XmlEncNamespaceUrl);
78             Recipient = Utils.GetAttribute(value, "Recipient", EncryptedXml.XmlEncNamespaceUrl);
79 
80             XmlNode encryptionMethodNode = value.SelectSingleNode("enc:EncryptionMethod", nsm);
81 
82             // EncryptionMethod
83             EncryptionMethod = new EncryptionMethod();
84             if (encryptionMethodNode != null)
85                 EncryptionMethod.LoadXml(encryptionMethodNode as XmlElement);
86 
87             // Key Info
88             KeyInfo = new KeyInfo();
89             XmlNode keyInfoNode = value.SelectSingleNode("ds:KeyInfo", nsm);
90             if (keyInfoNode != null)
91                 KeyInfo.LoadXml(keyInfoNode as XmlElement);
92 
93             // CipherData
94             XmlNode cipherDataNode = value.SelectSingleNode("enc:CipherData", nsm);
95             if (cipherDataNode == null)
96                 throw new CryptographicException(SR.Cryptography_Xml_MissingCipherData);
97 
98             CipherData = new CipherData();
99             CipherData.LoadXml(cipherDataNode as XmlElement);
100 
101             // EncryptionProperties
102             XmlNode encryptionPropertiesNode = value.SelectSingleNode("enc:EncryptionProperties", nsm);
103             if (encryptionPropertiesNode != null)
104             {
105                 // Select the EncryptionProperty elements inside the EncryptionProperties element
106                 XmlNodeList encryptionPropertyNodes = encryptionPropertiesNode.SelectNodes("enc:EncryptionProperty", nsm);
107                 if (encryptionPropertyNodes != null)
108                 {
109                     foreach (XmlNode node in encryptionPropertyNodes)
110                     {
111                         EncryptionProperty ep = new EncryptionProperty();
112                         ep.LoadXml(node as XmlElement);
113                         EncryptionProperties.Add(ep);
114                     }
115                 }
116             }
117 
118             // CarriedKeyName
119             XmlNode carriedKeyNameNode = value.SelectSingleNode("enc:CarriedKeyName", nsm);
120             if (carriedKeyNameNode != null)
121             {
122                 CarriedKeyName = carriedKeyNameNode.InnerText;
123             }
124 
125             // ReferenceList
126             XmlNode referenceListNode = value.SelectSingleNode("enc:ReferenceList", nsm);
127             if (referenceListNode != null)
128             {
129                 // Select the DataReference elements inside the ReferenceList element
130                 XmlNodeList dataReferenceNodes = referenceListNode.SelectNodes("enc:DataReference", nsm);
131                 if (dataReferenceNodes != null)
132                 {
133                     foreach (XmlNode node in dataReferenceNodes)
134                     {
135                         DataReference dr = new DataReference();
136                         dr.LoadXml(node as XmlElement);
137                         ReferenceList.Add(dr);
138                     }
139                 }
140                 // Select the KeyReference elements inside the ReferenceList element
141                 XmlNodeList keyReferenceNodes = referenceListNode.SelectNodes("enc:KeyReference", nsm);
142                 if (keyReferenceNodes != null)
143                 {
144                     foreach (XmlNode node in keyReferenceNodes)
145                     {
146                         KeyReference kr = new KeyReference();
147                         kr.LoadXml(node as XmlElement);
148                         ReferenceList.Add(kr);
149                     }
150                 }
151             }
152 
153             // Save away the cached value
154             _cachedXml = value;
155         }
156 
GetXml()157         public override XmlElement GetXml()
158         {
159             if (CacheValid) return _cachedXml;
160 
161             XmlDocument document = new XmlDocument();
162             document.PreserveWhitespace = true;
163             return GetXml(document);
164         }
165 
GetXml(XmlDocument document)166         internal XmlElement GetXml(XmlDocument document)
167         {
168             // Create the EncryptedKey element
169             XmlElement encryptedKeyElement = (XmlElement)document.CreateElement("EncryptedKey", EncryptedXml.XmlEncNamespaceUrl);
170 
171             // Deal with attributes
172             if (!string.IsNullOrEmpty(Id))
173                 encryptedKeyElement.SetAttribute("Id", Id);
174             if (!string.IsNullOrEmpty(Type))
175                 encryptedKeyElement.SetAttribute("Type", Type);
176             if (!string.IsNullOrEmpty(MimeType))
177                 encryptedKeyElement.SetAttribute("MimeType", MimeType);
178             if (!string.IsNullOrEmpty(Encoding))
179                 encryptedKeyElement.SetAttribute("Encoding", Encoding);
180             if (!string.IsNullOrEmpty(Recipient))
181                 encryptedKeyElement.SetAttribute("Recipient", Recipient);
182 
183             // EncryptionMethod
184             if (EncryptionMethod != null)
185                 encryptedKeyElement.AppendChild(EncryptionMethod.GetXml(document));
186 
187             // KeyInfo
188             if (KeyInfo.Count > 0)
189                 encryptedKeyElement.AppendChild(KeyInfo.GetXml(document));
190 
191             // CipherData
192             if (CipherData == null)
193                 throw new CryptographicException(SR.Cryptography_Xml_MissingCipherData);
194             encryptedKeyElement.AppendChild(CipherData.GetXml(document));
195 
196             // EncryptionProperties
197             if (EncryptionProperties.Count > 0)
198             {
199                 XmlElement encryptionPropertiesElement = document.CreateElement("EncryptionProperties", EncryptedXml.XmlEncNamespaceUrl);
200                 for (int index = 0; index < EncryptionProperties.Count; index++)
201                 {
202                     EncryptionProperty ep = EncryptionProperties.Item(index);
203                     encryptionPropertiesElement.AppendChild(ep.GetXml(document));
204                 }
205                 encryptedKeyElement.AppendChild(encryptionPropertiesElement);
206             }
207 
208             // ReferenceList
209             if (ReferenceList.Count > 0)
210             {
211                 XmlElement referenceListElement = document.CreateElement("ReferenceList", EncryptedXml.XmlEncNamespaceUrl);
212                 for (int index = 0; index < ReferenceList.Count; index++)
213                 {
214                     referenceListElement.AppendChild(ReferenceList[index].GetXml(document));
215                 }
216                 encryptedKeyElement.AppendChild(referenceListElement);
217             }
218 
219             // CarriedKeyName
220             if (CarriedKeyName != null)
221             {
222                 XmlElement carriedKeyNameElement = (XmlElement)document.CreateElement("CarriedKeyName", EncryptedXml.XmlEncNamespaceUrl);
223                 XmlText carriedKeyNameText = document.CreateTextNode(CarriedKeyName);
224                 carriedKeyNameElement.AppendChild(carriedKeyNameText);
225                 encryptedKeyElement.AppendChild(carriedKeyNameElement);
226             }
227 
228             return encryptedKeyElement;
229         }
230     }
231 }
232