**** Merged from MCS ****
[mono-project.git] / mcs / class / Microsoft.Web.Services / Microsoft.Web.Services.Security / EncryptedKey.cs
blobb300151aacfce625899addb1d25acbac119dfc01
1 //
2 // EncryptedKey.cs: Handles WS-Security EncryptedKey
3 //
4 // Author:
5 // Sebastien Pouliot (spouliot@motus.com)
6 //
7 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
8 //
10 using System;
11 using System.Security.Cryptography;
12 using System.Security.Cryptography.Xml;
13 using System.Xml;
14 #if !WSE1
15 using Microsoft.Web.Services.Xml;
16 #endif
18 namespace Microsoft.Web.Services.Security {
20 public class EncryptedKey : IXmlElement {
22 private DecryptionKey dk;
23 private EncryptionKey ek;
24 private ReferenceList list;
25 private string keyex;
26 private string session;
27 private SymmetricEncryptionKey key;
28 private byte[] decdata;
30 internal EncryptedKey ()
32 list = new ReferenceList ();
33 keyex = XmlEncryption.AlgorithmURI.RSA15;
34 session = XmlEncryption.AlgorithmURI.TripleDES;
37 #if WSE1
38 public EncryptedKey (AsymmetricEncryptionKey key) : this ()
39 #else
40 [Obsolete ("since WSE2 TP")]
41 public EncryptedKey (EncryptionKey key) : this ()
42 #endif
44 if (key == null)
45 throw new ArgumentNullException ("key");
46 if ((key.KeyInfo == null) || (key.KeyInfo.Count < 1))
47 throw new ArgumentException ("no KeyInfo");
48 ek = key;
51 public EncryptedKey (XmlElement element) : this ()
53 LoadXml (element);
56 public string EncryptionMethod {
57 get { return keyex; }
60 public KeyInfo KeyInfo {
61 get { return ek.KeyInfo; }
64 public ReferenceList ReferenceList {
65 get { return list; }
68 public string SessionAlgorithmURI {
69 get { return session; }
70 set {
71 switch (value) {
72 case null:
73 throw new ArgumentNullException ("value");
74 case XmlEncryption.AlgorithmURI.AES128:
75 case XmlEncryption.AlgorithmURI.AES192:
76 case XmlEncryption.AlgorithmURI.AES256:
77 case XmlEncryption.AlgorithmURI.TripleDES:
78 if (session != value)
79 key = null;
80 session = value;
81 break;
82 default:
83 throw new SecurityFault ("unsupported algorithm", null);
88 // note: no default key size is assumed because they could change in the future
89 private SymmetricAlgorithm GetSymmetricAlgorithm (string algorithmURI)
91 SymmetricAlgorithm sa = null;
92 switch (algorithmURI) {
93 // Reference: http://www.w3.org/2001/04/xmlenc#aes128-cbc [REQUIRED]
94 case XmlEncryption.AlgorithmURI.AES128:
95 sa = Rijndael.Create ();
96 sa.KeySize = 128;
97 break;
98 // Reference: http://www.w3.org/2001/04/xmlenc#aes192-cbc [OPTIONAL]
99 case XmlEncryption.AlgorithmURI.AES192:
100 sa = Rijndael.Create ();
101 sa.KeySize = 192;
102 break;
103 // Reference: http://www.w3.org/2001/04/xmlenc#aes256-cbc [REQUIRED]
104 case XmlEncryption.AlgorithmURI.AES256:
105 sa = Rijndael.Create ();
106 sa.KeySize = 256;
107 break;
108 // Reference: http://www.w3.org/2001/04/xmlenc#tripledes-cbc [REQUIRED]
109 case XmlEncryption.AlgorithmURI.TripleDES:
110 sa = TripleDES.Create ();
111 sa.KeySize = 192;
112 break;
113 default:
114 return null;
116 // for decryption we must use the decrypted key (from the keyexchange)
117 if ((sa != null) && (decdata != null))
118 sa.Key = decdata;
119 return sa;
122 internal SymmetricEncryptionKey Key {
123 get {
124 if (key == null) {
125 key = new SymmetricEncryptionKey (GetSymmetricAlgorithm (session));
127 return key;
131 [MonoTODO("incomplete")]
132 public XmlElement GetXml (XmlDocument document)
134 if (document == null)
135 throw new ArgumentNullException ("document");
137 XmlAttribute ema = document.CreateAttribute (XmlEncryption.AttributeNames.Algorithm);
138 ema.InnerText = keyex;
139 XmlElement em = document.CreateElement (XmlEncryption.Prefix, XmlEncryption.ElementNames.EncryptionMethod, XmlEncryption.NamespaceURI);
140 em.Attributes.Append (ema);
142 XmlElement ki = KeyInfo.GetXml ();
144 AsymmetricKeyExchangeFormatter fmt = null;
145 AsymmetricEncryptionKey aek = (ek as AsymmetricEncryptionKey);
146 switch (keyex) {
147 case XmlEncryption.AlgorithmURI.RSA15:
148 fmt = new RSAPKCS1KeyExchangeFormatter (aek.Algorithm);
149 break;
150 case XmlEncryption.AlgorithmURI.RSAOAEP:
151 fmt = new RSAOAEPKeyExchangeFormatter (aek.Algorithm);
152 // TODO: parameters
153 break;
154 default:
155 throw new SecurityFault ("unknown key exchange algorithm", null);
157 byte[] enckey = fmt.CreateKeyExchange (Key.Algorithm.Key);
159 XmlElement cv = document.CreateElement (XmlEncryption.Prefix, XmlEncryption.ElementNames.CipherValue, XmlEncryption.NamespaceURI);
160 cv.InnerText = Convert.ToBase64String (enckey);
161 XmlElement cd = document.CreateElement (XmlEncryption.Prefix, XmlEncryption.ElementNames.CipherData, XmlEncryption.NamespaceURI);
162 cd.AppendChild (cv);
164 XmlElement rl = list.GetXml (document);
166 XmlAttribute ekt = document.CreateAttribute (XmlEncryption.AttributeNames.Type);
167 ekt.InnerText = XmlEncryption.TypeURI.EncryptedKey;
168 XmlElement result = document.CreateElement (XmlEncryption.Prefix, XmlEncryption.ElementNames.EncryptedKey, XmlEncryption.NamespaceURI);
169 result.Attributes.Append (ekt);
170 result.AppendChild (em);
171 result.AppendChild (document.ImportNode (ki, true));
172 result.AppendChild (cd);
173 result.AppendChild (rl);
174 return result;
177 [MonoTODO("incomplete")]
178 public void LoadXml (XmlElement element)
180 if (element == null)
181 throw new ArgumentNullException ("element");
182 if ((element.LocalName != XmlEncryption.ElementNames.EncryptedKey) || (element.NamespaceURI != XmlEncryption.NamespaceURI))
183 throw new System.ArgumentException ("invalid LocalName or NamespaceURI");
185 XmlNodeList xnl = element.GetElementsByTagName (XmlEncryption.ElementNames.EncryptionMethod, XmlEncryption.NamespaceURI);
186 if ((xnl != null) && (xnl.Count > 0)) {
187 XmlAttribute ema = xnl [0].Attributes [XmlEncryption.AttributeNames.Algorithm];
188 if (ema != null)
189 keyex = ema.InnerText;
192 xnl = element.GetElementsByTagName (XmlSignature.ElementNames.KeyInfo, XmlSignature.NamespaceURI);
193 if ((xnl != null) && (xnl.Count > 0)) {
194 KeyInfo ki = new KeyInfo ();
195 ki.LoadXml ((XmlElement) xnl [0]);
196 #if WSE1
197 DecryptionKeyProvider dkp = new DecryptionKeyProvider ();
198 dk = dkp.GetDecryptionKey (keyex, ki);
199 #else
200 // TODO
201 #endif
204 byte[] encdata = null;
205 xnl = element.GetElementsByTagName (XmlEncryption.ElementNames.CipherData, XmlEncryption.NamespaceURI);
206 if ((xnl != null) && (xnl.Count > 0)) {
207 XmlElement cd = (XmlElement) xnl [0];
208 foreach (XmlNode xn in cd.ChildNodes) {
209 if ((xn.LocalName == XmlEncryption.ElementNames.CipherValue) && (xn.NamespaceURI == XmlEncryption.NamespaceURI)) {
210 encdata = Convert.FromBase64String (xn.InnerText);
215 xnl = element.GetElementsByTagName (XmlEncryption.ElementNames.ReferenceList, XmlEncryption.NamespaceURI);
216 if ((xnl != null) && (xnl.Count > 0)) {
217 list.LoadXml ((XmlElement) xnl [0]);
220 AsymmetricDecryptionKey adk = (dk as AsymmetricDecryptionKey);
221 if ((adk != null) && (encdata != null)) {
222 AsymmetricKeyExchangeDeformatter def = null;
223 switch (keyex) {
224 case XmlEncryption.AlgorithmURI.RSA15:
225 def = new RSAPKCS1KeyExchangeDeformatter (adk.Algorithm);
226 decdata = def.DecryptKeyExchange (encdata);
227 break;
228 case XmlEncryption.AlgorithmURI.RSAOAEP:
229 // TODO
230 break;
233 // TODO