2 // EncryptedKey.cs: Handles WS-Security EncryptedKey
5 // Sebastien Pouliot (spouliot@motus.com)
7 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
11 using System
.Security
.Cryptography
;
12 using System
.Security
.Cryptography
.Xml
;
15 using Microsoft
.Web
.Services
.Xml
;
18 namespace Microsoft
.Web
.Services
.Security
{
20 public class EncryptedKey
: IXmlElement
{
22 private DecryptionKey dk
;
23 private EncryptionKey ek
;
24 private ReferenceList list
;
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
;
38 public EncryptedKey (AsymmetricEncryptionKey key
) : this ()
40 [Obsolete ("since WSE2 TP")]
41 public EncryptedKey (EncryptionKey key
) : this ()
45 throw new ArgumentNullException ("key");
46 if ((key
.KeyInfo
== null) || (key
.KeyInfo
.Count
< 1))
47 throw new ArgumentException ("no KeyInfo");
51 public EncryptedKey (XmlElement element
) : this ()
56 public string EncryptionMethod
{
60 public KeyInfo KeyInfo
{
61 get { return ek.KeyInfo; }
64 public ReferenceList ReferenceList
{
68 public string SessionAlgorithmURI
{
69 get { return session; }
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
:
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 ();
98 // Reference: http://www.w3.org/2001/04/xmlenc#aes192-cbc [OPTIONAL]
99 case XmlEncryption
.AlgorithmURI
.AES192
:
100 sa
= Rijndael
.Create ();
103 // Reference: http://www.w3.org/2001/04/xmlenc#aes256-cbc [REQUIRED]
104 case XmlEncryption
.AlgorithmURI
.AES256
:
105 sa
= Rijndael
.Create ();
108 // Reference: http://www.w3.org/2001/04/xmlenc#tripledes-cbc [REQUIRED]
109 case XmlEncryption
.AlgorithmURI
.TripleDES
:
110 sa
= TripleDES
.Create ();
116 // for decryption we must use the decrypted key (from the keyexchange)
117 if ((sa
!= null) && (decdata
!= null))
122 internal SymmetricEncryptionKey Key
{
125 key
= new SymmetricEncryptionKey (GetSymmetricAlgorithm (session
));
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
);
147 case XmlEncryption
.AlgorithmURI
.RSA15
:
148 fmt
= new RSAPKCS1KeyExchangeFormatter (aek
.Algorithm
);
150 case XmlEncryption
.AlgorithmURI
.RSAOAEP
:
151 fmt
= new RSAOAEPKeyExchangeFormatter (aek
.Algorithm
);
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
);
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
);
177 [MonoTODO("incomplete")]
178 public void LoadXml (XmlElement element
)
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
];
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]);
197 DecryptionKeyProvider dkp
= new DecryptionKeyProvider ();
198 dk
= dkp
.GetDecryptionKey (keyex
, ki
);
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;
224 case XmlEncryption
.AlgorithmURI
.RSA15
:
225 def
= new RSAPKCS1KeyExchangeDeformatter (adk
.Algorithm
);
226 decdata
= def
.DecryptKeyExchange (encdata
);
228 case XmlEncryption
.AlgorithmURI
.RSAOAEP
: