//
// (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
//
-// Licensed under MIT X11 (see LICENSE) with this specific addition:
-//
-// \93This source code may incorporate intellectual property owned by Microsoft
-// Corporation. Our provision of this source code does not include any licenses
-// or any other rights to you under any Microsoft intellectual property. If you
-// would like a license from Microsoft (e.g. rebrand, redistribute), you need
-// to contact Microsoft directly.\94
-//
using System;
+using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Xml;
+#if !WSE1
using Microsoft.Web.Services.Xml;
+#endif
namespace Microsoft.Web.Services.Security {
public class EncryptedKey : IXmlElement {
- private AsymmetricEncryptionKey aek;
- private KeyInfo ki;
+ private DecryptionKey dk;
+ private EncryptionKey ek;
private ReferenceList list;
+ private string keyex;
+ private string session;
+ private SymmetricEncryptionKey key;
+ private byte[] decdata;
- internal EncryptedKey ()
+ internal EncryptedKey ()
{
list = new ReferenceList ();
+ keyex = XmlEncryption.AlgorithmURI.RSA15;
+ session = XmlEncryption.AlgorithmURI.TripleDES;
}
+#if WSE1
public EncryptedKey (AsymmetricEncryptionKey key) : this ()
+#else
+ [Obsolete ("since WSE2 TP")]
+ public EncryptedKey (EncryptionKey key) : this ()
+#endif
{
if (key == null)
throw new ArgumentNullException ("key");
- aek = key;
- ki = new KeyInfo ();
+ if ((key.KeyInfo == null) || (key.KeyInfo.Count < 1))
+ throw new ArgumentException ("no KeyInfo");
+ ek = key;
}
public EncryptedKey (XmlElement element) : this ()
}
public string EncryptionMethod {
- get { return null; }
+ get { return keyex; }
}
public KeyInfo KeyInfo {
- get { return ki; }
+ get { return ek.KeyInfo; }
}
public ReferenceList ReferenceList {
get { return list; }
}
+ public string SessionAlgorithmURI {
+ get { return session; }
+ set {
+ switch (value) {
+ case null:
+ throw new ArgumentNullException ("value");
+ case XmlEncryption.AlgorithmURI.AES128:
+ case XmlEncryption.AlgorithmURI.AES192:
+ case XmlEncryption.AlgorithmURI.AES256:
+ case XmlEncryption.AlgorithmURI.TripleDES:
+ if (session != value)
+ key = null;
+ session = value;
+ break;
+ default:
+ throw new SecurityFault ("unsupported algorithm", null);
+ }
+ }
+ }
+
+ // note: no default key size is assumed because they could change in the future
+ private SymmetricAlgorithm GetSymmetricAlgorithm (string algorithmURI)
+ {
+ SymmetricAlgorithm sa = null;
+ switch (algorithmURI) {
+ // Reference: http://www.w3.org/2001/04/xmlenc#aes128-cbc [REQUIRED]
+ case XmlEncryption.AlgorithmURI.AES128:
+ sa = Rijndael.Create ();
+ sa.KeySize = 128;
+ break;
+ // Reference: http://www.w3.org/2001/04/xmlenc#aes192-cbc [OPTIONAL]
+ case XmlEncryption.AlgorithmURI.AES192:
+ sa = Rijndael.Create ();
+ sa.KeySize = 192;
+ break;
+ // Reference: http://www.w3.org/2001/04/xmlenc#aes256-cbc [REQUIRED]
+ case XmlEncryption.AlgorithmURI.AES256:
+ sa = Rijndael.Create ();
+ sa.KeySize = 256;
+ break;
+ // Reference: http://www.w3.org/2001/04/xmlenc#tripledes-cbc [REQUIRED]
+ case XmlEncryption.AlgorithmURI.TripleDES:
+ sa = TripleDES.Create ();
+ sa.KeySize = 192;
+ break;
+ default:
+ return null;
+ }
+ // for decryption we must use the decrypted key (from the keyexchange)
+ if ((sa != null) && (decdata != null))
+ sa.Key = decdata;
+ return sa;
+ }
+
+ internal SymmetricEncryptionKey Key {
+ get {
+ if (key == null) {
+ key = new SymmetricEncryptionKey (GetSymmetricAlgorithm (session));
+ }
+ return key;
+ }
+ }
+
+ [MonoTODO("incomplete")]
public XmlElement GetXml (XmlDocument document)
{
if (document == null)
throw new ArgumentNullException ("document");
- return ki.GetXml ();
+
+ XmlAttribute ema = document.CreateAttribute (XmlEncryption.AttributeNames.Algorithm);
+ ema.InnerText = keyex;
+ XmlElement em = document.CreateElement (XmlEncryption.Prefix, XmlEncryption.ElementNames.EncryptionMethod, XmlEncryption.NamespaceURI);
+ em.Attributes.Append (ema);
+
+ XmlElement ki = KeyInfo.GetXml ();
+
+ AsymmetricKeyExchangeFormatter fmt = null;
+ AsymmetricEncryptionKey aek = (ek as AsymmetricEncryptionKey);
+ switch (keyex) {
+ case XmlEncryption.AlgorithmURI.RSA15:
+ fmt = new RSAPKCS1KeyExchangeFormatter (aek.Algorithm);
+ break;
+ case XmlEncryption.AlgorithmURI.RSAOAEP:
+ fmt = new RSAOAEPKeyExchangeFormatter (aek.Algorithm);
+ // TODO: parameters
+ break;
+ default:
+ throw new SecurityFault ("unknown key exchange algorithm", null);
+ }
+ byte[] enckey = fmt.CreateKeyExchange (Key.Algorithm.Key);
+
+ XmlElement cv = document.CreateElement (XmlEncryption.Prefix, XmlEncryption.ElementNames.CipherValue, XmlEncryption.NamespaceURI);
+ cv.InnerText = Convert.ToBase64String (enckey);
+ XmlElement cd = document.CreateElement (XmlEncryption.Prefix, XmlEncryption.ElementNames.CipherData, XmlEncryption.NamespaceURI);
+ cd.AppendChild (cv);
+
+ XmlElement rl = list.GetXml (document);
+
+ XmlAttribute ekt = document.CreateAttribute (XmlEncryption.AttributeNames.Type);
+ ekt.InnerText = XmlEncryption.TypeURI.EncryptedKey;
+ XmlElement result = document.CreateElement (XmlEncryption.Prefix, XmlEncryption.ElementNames.EncryptedKey, XmlEncryption.NamespaceURI);
+ result.Attributes.Append (ekt);
+ result.AppendChild (em);
+ result.AppendChild (document.ImportNode (ki, true));
+ result.AppendChild (cd);
+ result.AppendChild (rl);
+ return result;
}
+ [MonoTODO("incomplete")]
public void LoadXml (XmlElement element)
{
- if ((element.LocalName != "") || (element.NamespaceURI != ""))
+ if (element == null)
+ throw new ArgumentNullException ("element");
+ if ((element.LocalName != XmlEncryption.ElementNames.EncryptedKey) || (element.NamespaceURI != XmlEncryption.NamespaceURI))
throw new System.ArgumentException ("invalid LocalName or NamespaceURI");
- ki = new KeyInfo ();
- try {
- ki.LoadXml (element);
+
+ XmlNodeList xnl = element.GetElementsByTagName (XmlEncryption.ElementNames.EncryptionMethod, XmlEncryption.NamespaceURI);
+ if ((xnl != null) && (xnl.Count > 0)) {
+ XmlAttribute ema = xnl [0].Attributes [XmlEncryption.AttributeNames.Algorithm];
+ if (ema != null)
+ keyex = ema.InnerText;
}
- catch {
- throw new ArgumentException ("element has no KeyInfo");
+
+ xnl = element.GetElementsByTagName (XmlSignature.ElementNames.KeyInfo, XmlSignature.NamespaceURI);
+ if ((xnl != null) && (xnl.Count > 0)) {
+ KeyInfo ki = new KeyInfo ();
+ ki.LoadXml ((XmlElement) xnl [0]);
+#if WSE1
+ DecryptionKeyProvider dkp = new DecryptionKeyProvider ();
+ dk = dkp.GetDecryptionKey (keyex, ki);
+#else
+ // TODO
+#endif
+ }
+
+ byte[] encdata = null;
+ xnl = element.GetElementsByTagName (XmlEncryption.ElementNames.CipherData, XmlEncryption.NamespaceURI);
+ if ((xnl != null) && (xnl.Count > 0)) {
+ XmlElement cd = (XmlElement) xnl [0];
+ foreach (XmlNode xn in cd.ChildNodes) {
+ if ((xn.LocalName == XmlEncryption.ElementNames.CipherValue) && (xn.NamespaceURI == XmlEncryption.NamespaceURI)) {
+ encdata = Convert.FromBase64String (xn.InnerText);
+ }
+ }
+ }
+
+ xnl = element.GetElementsByTagName (XmlEncryption.ElementNames.ReferenceList, XmlEncryption.NamespaceURI);
+ if ((xnl != null) && (xnl.Count > 0)) {
+ list.LoadXml ((XmlElement) xnl [0]);
+ }
+
+ AsymmetricDecryptionKey adk = (dk as AsymmetricDecryptionKey);
+ if ((adk != null) && (encdata != null)) {
+ AsymmetricKeyExchangeDeformatter def = null;
+ switch (keyex) {
+ case XmlEncryption.AlgorithmURI.RSA15:
+ def = new RSAPKCS1KeyExchangeDeformatter (adk.Algorithm);
+ decdata = def.DecryptKeyExchange (encdata);
+ break;
+ case XmlEncryption.AlgorithmURI.RSAOAEP:
+ // TODO
+ break;
+ }
}
+ // TODO
}
}
}