// // EncryptedXml.cs - EncryptedXml implementation for XML Encryption // // Author: // Tim Coleman (tim@timcoleman.com) // // Copyright (C) Tim Coleman, 2004 // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // #if NET_2_0 using System.Collections; using System.IO; using System.Security.Cryptography; using System.Security.Policy; using System.Text; using System.Xml; namespace System.Security.Cryptography.Xml { public class EncryptedXml { #region Fields public const string XmlEncAES128KeyWrapUrl = XmlEncNamespaceUrl + "kw-aes128"; public const string XmlEncAES128Url = XmlEncNamespaceUrl + "aes128-cbc"; public const string XmlEncAES192KeyWrapUrl = XmlEncNamespaceUrl + "kw-aes192"; public const string XmlEncAES192Url = XmlEncNamespaceUrl + "aes192-cbc"; public const string XmlEncAES256KeyWrapUrl = XmlEncNamespaceUrl + "kw-aes256"; public const string XmlEncAES256Url = XmlEncNamespaceUrl + "aes256-cbc"; public const string XmlEncDESUrl = XmlEncNamespaceUrl + "des-cbc"; public const string XmlEncElementContentUrl = XmlEncNamespaceUrl + "ElementContent"; public const string XmlEncElementUrl = XmlEncNamespaceUrl + "element"; public const string XmlEncEncryptedKeyUrl = XmlEncNamespaceUrl + "EncryptedKey"; public const string XmlEncNamespaceUrl = "http://www.w3.org/2001/04/xmlenc#"; public const string XmlEncRSA1_5Url = XmlEncNamespaceUrl + "rsa-1_5"; public const string XmlEncRSAOAEPUrl = XmlEncNamespaceUrl + "rsa-oaep-mgf1p"; public const string XmlEncSHA256Url = XmlEncNamespaceUrl + "sha256"; public const string XmlEncSHA512Url = XmlEncNamespaceUrl + "sha512"; public const string XmlEncTripleDESKeyWrapUrl = XmlEncNamespaceUrl + "kw-tripledes"; public const string XmlEncTripleDESUrl = XmlEncNamespaceUrl + "tripledes-cbc"; Evidence documentEvidence; Encoding encoding = Encoding.UTF8; Hashtable keyNameMapping = new Hashtable (); CipherMode mode = CipherMode.CBC; PaddingMode padding = PaddingMode.ISO10126; string recipient; XmlResolver resolver; #endregion // Fields #region Constructors [MonoTODO] public EncryptedXml () { } [MonoTODO] public EncryptedXml (XmlDocument document) { } [MonoTODO] public EncryptedXml (XmlDocument document, Evidence evidence) { DocumentEvidence = evidence; } #endregion // Constructors #region Properties public Evidence DocumentEvidence { get { return documentEvidence; } set { documentEvidence = value; } } public Encoding Encoding { get { return encoding; } set { encoding = value; } } public CipherMode Mode { get { return mode; } set { mode = value; } } public PaddingMode Padding { get { return padding; } set { padding = value; } } public string Recipient { get { return recipient; } set { recipient = value; } } public XmlResolver Resolver { get { return resolver; } set { resolver = value; } } #endregion // Properties #region Methods public void AddKeyNameMapping (string keyName, object keyObject) { keyNameMapping [keyName] = keyObject; } public void ClearKeyNameMappings () { keyNameMapping.Clear (); } public byte[] DecryptData (EncryptedData encryptedData, SymmetricAlgorithm symAlg) { return Transform (encryptedData.CipherData.CipherValue, symAlg.CreateDecryptor ()); } [MonoTODO] public void DecryptDocument () { throw new NotImplementedException (); } [MonoTODO] public virtual byte[] DecryptEncryptedKey (EncryptedKey encryptedKey) { throw new NotImplementedException (); } [MonoTODO] public static byte[] DecryptKey (byte[] keyData, SymmetricAlgorithm symAlg) { if (symAlg is TripleDES) return SymmetricKeyWrap.TripleDESKeyWrapDecrypt (symAlg.Key, keyData); if (symAlg is Rijndael) return SymmetricKeyWrap.TripleDESKeyWrapDecrypt (symAlg.Key, keyData); throw new CryptographicException ("The specified cryptographic transform is not supported."); } [MonoTODO] public static byte[] DecryptKey (byte[] keyData, RSA rsa, bool fOAEP) { throw new NotImplementedException (); } public byte[] EncryptData (XmlElement inputElement, SymmetricAlgorithm symAlg, bool content) { if (content) return Transform (Encoding.GetBytes (inputElement.InnerXml), symAlg.CreateEncryptor ()); else return Transform (Encoding.GetBytes (inputElement.OuterXml), symAlg.CreateEncryptor ()); } [MonoTODO ("Do we need to support more algorithms?")] public static byte[] EncryptKey (byte[] keyData, SymmetricAlgorithm symAlg) { if (symAlg is TripleDES) return SymmetricKeyWrap.TripleDESKeyWrapEncrypt (symAlg.Key, keyData); if (symAlg is Rijndael) return SymmetricKeyWrap.AESKeyWrapEncrypt (symAlg.Key, keyData); throw new CryptographicException ("The specified cryptographic transform is not supported."); } [MonoTODO ("Not sure what this is for.")] public static byte[] EncryptKey (byte[] keyData, RSA rsa, bool fOAEP) { throw new NotImplementedException (); } private static SymmetricAlgorithm GetAlgorithm (string symAlgUri) { SymmetricAlgorithm symAlg = null; switch (symAlgUri) { case XmlEncAES128Url: symAlg = SymmetricAlgorithm.Create ("Rijndael"); symAlg.KeySize = 128; break; case XmlEncAES192Url: symAlg = SymmetricAlgorithm.Create ("Rijndael"); symAlg.KeySize = 192; break; case XmlEncAES256Url: symAlg = SymmetricAlgorithm.Create ("Rijndael"); symAlg.KeySize = 256; break; case XmlEncDESUrl: symAlg = SymmetricAlgorithm.Create ("DES"); break; case XmlEncTripleDESUrl: symAlg = SymmetricAlgorithm.Create ("TripleDES"); break; default: throw new ArgumentException ("symAlgUri"); } return symAlg; } [MonoTODO] public virtual byte[] GetDecryptionIV (EncryptedData encryptedData, string symAlgUri) { SymmetricAlgorithm symAlg = GetAlgorithm (symAlgUri); throw new NotImplementedException (); } [MonoTODO] public virtual SymmetricAlgorithm GetDecryptionKey (EncryptedData encryptedData, string symAlgUri) { SymmetricAlgorithm symAlg = GetAlgorithm (symAlgUri); throw new NotImplementedException (); } public virtual XmlElement GetIdElement (XmlDocument document, string idValue) { // this works only if there's a DTD or XSD available to define the ID XmlElement xel = document.GetElementById (idValue); if (xel == null) { // search an "undefined" ID xel = (XmlElement) document.SelectSingleNode ("//*[@Id='" + idValue + "']"); } return xel; } [MonoTODO] public static void ReplaceElement (XmlElement inputElement, EncryptedData encryptedData, bool content) { throw new NotImplementedException (); } private byte[] Transform (byte[] data, ICryptoTransform transform) { MemoryStream output = new MemoryStream (); CryptoStream crypto = new CryptoStream (output, transform, CryptoStreamMode.Write); crypto.Write (data, 0, data.Length); crypto.Close (); output.Close (); return output.ToArray (); } #endregion // Methods } } #endif