.NETFramework提供了几种类,可用于对 XML数据进行加密和解密,以及创建和验证 XML数字签名。这些类提供了维护 XML数据的保密性和完整性的方法。在这里,我们只涉及如何使用.NETFramework本身提供了的EncryptedXml类进行加密和解密。该类提供了一些方法,能够让用户使用不同的算法进行加密和解密XML。
要使用EncryptedXml类进行加密和解密,我们需要搞清楚两个主题。
1. 加密算法的选取。
2. 如何进行加密。
涉及到加密算法,一般分为两种类型的算法,对称加密算法(SymmetricAlgorithm)和非对称加密算法(AsymmetricAlgorithm)。两种算法的区别在于,使用对称加密算法进行加密和解密,加密过程和解密过程都是使用同一个密钥;对于非对称加密和解密,则是使用一个相互匹配密钥对----公钥和私钥进行加解密。【顺便简单的提及一下非对称加密方式和原理。对于这种类型的加密,加密密钥和解密密钥是相对的说法,如果用加密密钥加密那么只有解密密钥才能恢复,如果用解密密钥加密则只有加密密钥能解密,所以它们被称为密钥对,其中的一个可以在网络上发送、公布,叫做公钥,而另一个则只有密钥对的所有人才持有,叫做私钥,非对称公开密钥系统又叫做公钥系统。非对称加密算法的基本原理是,如果发信方想发送只有收信方才能解读的加密信息,发信方必须首先知道收信方的公钥,然后利用收信方的公钥来加密原文;收信方收到加密密文后,使用自己的私钥才能解密密文。显然,采用不对称加密算法,收发信双方在通信之前,收信方必须将自己早已随机生成的公钥送给发信方,而自己保留私钥。】另外,这两种加密在效率上有比较大的区别,前者效率高,后者效率要相对低一些。所以,加密大量数据,一般都是采用对称加密算法将数据进行加密,为了使加密更加安全,再使用非对称加密算法将加密数据的对称加密密钥进行加密,这样,在进行网络传输时,即保证了加密数据的效率,又保证了加密数据的安全性,当然,在没有将加密的数据进行网络传输时,就没有必要使用非对称加密了,普通的对称加密就可以满足需求。(大家可以仔细Google一下。)
对于这两种加密,常见对称加密算法有DES, AES(又称为Rijndael,其密钥长度分128,192,256位这三种), TripleDES等;非对称加密算法常见的有RSA算法。这几种加密算法对应的类分别是:DESCryptoServiceProvider,RijndaelManaged,TripleDESCryptoServiceProvider以及RSACryptoServiceProvider。前有三种都从SymmetricAlgorithm继承过来,最后一种从AsymmetricAlgorithm继承过来。
好了,基本上关于加密解密,我们已以有一个大致的了解,那么,下面详细的描述一下如何进行加密和解密。
在下面的描述中,我参考了以下文档:
XMLEncryption Syntax and Processing(W3C XML加解密标准文档)
XML加密和数字签名(该主题下含有XML各种类型的加解密)
假定现在有如下XML文档(test.xml),我们要对其进行加密/解密:
- <root>
- <creditcard>
- <number>19834209</number>
- <expiry>02/02/2002</expiry>
- </creditcard>
- </root>
加密的大致流程如下:
1. 通过从磁盘加载 XML文件创建 XmlDocument对象。XmlDocument对象包含要加密的 XML 元素。
2. 在 XmlDocument对象中找到指定的元素,然后创建一个新的XmlElement 对象来表示要加密的元素。
3. 创建 EncryptedXml类的新实例,并使用它通过指定的加密算法对XmlElement进行加密。
4. 构造一个 EncryptedData对象,用XML加密元素的 URL 标识符、EncryptedKey信息等填充它,并将加密数据填充到该结构体里面去。(很重要,很繁琐的步骤)
5. 用 EncryptedData元素替换原始 XmlDocument对象中的元素。
我们直接拿test.xml来加密,要加密的元素是<number>,加密粒度是该结点,加密数据采用最简单的DES加密,加密后的XML文档变为:
- <root>
- <creditcard>
- <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns="http://www.w3.org/2001/04/xmlenc#">
- <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#des-cbc" />
- <CipherData>
- <CipherValue>3oIDgOJMW0/Ev3duGiCvsVdDgPzP7X0399xwVKMR8MQUGO1AMTIlFA==</CipherValue>
- </CipherData>
- </EncryptedData>
- <expiry>02/02/2002</expiry>
- </creditcard>
- </root>
从该加密后的XML里面可以看得出来,<EncryptedData>这个节点里面的内容为加密后的核心内容,但这里面真正被加密的内容在哪?很明显,<CipherValue>中3oIDgOJMW0/Ev3duGiCvsVdDgPzP7X0399xwVKMR8MQUGO1AMTIlFA==这一长串就是加密后的真正数据。那其它部分都是些什么内容?这里,我们需要熟悉一下W3C关于加密的标准。可参见XMLEncryption Syntax and Processing文档。
从加密后的XML里面可以看出,<EncryptedData>节点包含了被加密后的数据和其它信息,W3C为其定义的标准结构如下:
(其中,“?”表示出现0次或1次,“+”表示出现1次或多次,“*”表示0次或多次,空元素标签表示该元素的内容为空)
- <EncryptedData Id? Type? MimeType? Encoding?>
- <EncryptionMethod/>?
- <ds:KeyInfo>
- <EncryptedKey>?
- <AgreementMethod>?
- <ds:KeyName>?
- <ds:RetrievalMethod>?
- <ds:*>?
- </ds:KeyInfo>?
- <CipherData>
- <CipherValue>?
- <CipherReference URI?>?
- </CipherData>
- <EncryptionProperties>?
- </EncryptedData>
其中:
1. <EncryptionMethod>用于描述加密方式。一般情况下,需要设置该项。
2. <ds:KeyInfo>用于描述用于加密数据的key。一般情况下,需要设置该项的<KeyName>节点。
3. <EncryptedKey>用于描述将加密数据的key①进行加密的新key②的信息。有点绕,实际上,它出现于这样的情形:当我们使用对称加密key(如:DES加密)对数据进行加密,为了加密更加安全,然后采用另外一种高级加密方式(如:RSA加密),对这个key再进行一次加密,并将这个key加密后的生成的加密数据保存到<EncryptedKey>里面的<CipherData>节点下面。解密时,需要通过给出key②,先将原始加密数据的key①解密出来,再将原始数据进行解密。要注意一点,<EncryptedKey>的数据结构实际上和<EncryptedData>的数据结构是类似的。给出一个简单的例子,如:
- <EncryptedKey Id="EK" xmlns="http://www.w3.org/2001/04/xmlenc#">
- <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
- <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
- <ds:KeyName>John Smith</ds:KeyName>
- </ds:KeyInfo>
- <CipherData>
- <CipherValue>xyzabc</CipherValue>
- </CipherData>
- <ReferenceList>
- <DataReference URI="#ED" />
- </ReferenceList>
- <CarriedKeyName>Sally Doe</CarriedKeyName>
- </EncryptedKey>
这里面<CipherValue>xyzabc</CipherValue>中的数据实际上就是被加密后的key.
MSDN上所给出的DEMO称这种方式为非对称加密方式,但我认为有些不妥,因为加密真正数据的部分并没有采用非对称加密方式,而只是将key①使用了非对称加密。
4. 元素<CipherData>代表加密数据的结构,其中的<CipherValue>代表真正加密后的数据。
对于以上所有结构,在.NET Framework的类里面都有对应的类。
……
(个人感觉,这些类实在是太多了,有点抽象过度的嫌疑。)
另外,我们需要了解一下加密粒度(Encryption Granularity)。加密粒度分两种,一是加密节点内部的数据,另一个加密整个节点。比如,我们可以选择只加密<number>的内容19834209,当然也可以选择加密<number>整个结点。
实际上,通过上面的内容可以看出,加密XML最核心的东西实际上只有两个部分,第一是将原始数据进行加密,第二是构建<EncryptedData>节点内的数据。
OK,整个加密的流程以及相关的背景知识介绍得差不多了。下面通过封装一个加解密的类(GTXXmlCrypt)来说明如何使用EncryptedXml进行加解密。
首先,需要描述我们所使用的EncryptedXml类里面几个重要的方法,这几个方法也是在这个封装类里面用到的,简单描述一下,详细请见MSDN:
1. publicbyte[]EncryptData(XmlElementinputElement,SymmetricAlgorithmsymmetricAlgorithm,boolcontent);
a) 通过给定的对称加密算法,对指定的节点进行加密,content指明是否是加密整个节点还是只加密节点内容。
b) 在该类中,用于加密节点的方法只能通过称加密算法,而不能够通过非对称加密节点,可能他们认为使用非对称加密的实际含义是:先通过对称加密将数据进行加密,再用非对称加密将前者(对称加密的key)进行加密,这种方式才叫非对称加密。
2. publicbyte[]DecryptData(EncryptedDataencryptedData,SymmetricAlgorithmsymmetricAlgorithm);
a) 通过给定的对称解密算法(加密和解密的key是一样的),将数据进行解密,同样,只能使用对称加密方式。
3. publicvoidDecryptDocument();
a) 解密整个文档,但它使用的前提是:在被加密后的文档中,<EncryptedData>节点必须含有<KeyInfo>,而且其中的<KeyName>必须有值。可以通过将要封装的类实验。
4. publicstaticvoid ReplaceElement(XmlElementinputElement,EncryptedDataencryptedData,boolcontent);
a) 当加密完后,需要用EncryptedData来替换加密的节点。
5. publicstaticbyte[] DecryptKey(byte[]keyData, SymmetricAlgorithmsymmetricAlgorithm);
a) 该方法通过对称加密算法解密“加密原数据的密钥”。
6. publicstaticbyte[] DecryptKey(byte[]keyData, RSArsa, bool useOAEP);
a) 该方法通过非对称加密算法解密“加密原数据的密钥”。
我们需要封装的GTXXmlCrypt类有以下需求:
1. 能够加载一个xml文件进行加解密;
2. 能够某个XmlDocument进行加解密;
3. 能够对单个指定的节点进行加解密;
4. 能够指定各种加解密的方式,如指定加密方式为DES,AES,RSA等;
该类的框架如下:(请原谅我只给出了一个代码的架子,也没有用类图的形式表示出来,因为我会将所有代码全部贴上来。)
- namespace GTXUtility.Security.Crypt
- {
- public class GTXXmlCrypt
- {
- // 定义对称加密类型,对于非对称加密类型,我没有给出重新定义一个结构体,
- // 原因是因为EncryptedXml类对非对称加密只支持RSA,而且RSA也不是用来加密数据的,而是用来加密key的。
- public enum SymmetricAlgTypes
- {
- DES = 1,
- AES128, // Rijndael 128
- AES192, // Rijndael 192
- AES256, // Rijndael 256
- TripleDES,
- }
- // 该类通过指定的对称加密类型,创建对应的对称加密key,
- // 实际上,对于创建加密key,完全可以另外写个类,进行操作,而不应该放在该类里面。
- public static SymmetricAlgorithm CreateSymmetricAlgorithm(SymmetricAlgTypes salType);
- // 该类用于创建RSA key,
- // 实际上,对于创建加密key,完全可以另外写个类,进行操作,而不应该放在该类里面。
- public static RSA CreateRSAAlgorithm(String containerName);
- // 加密指定的文件,该函数内部会调用EncryptXmlDoc函数。
- public static bool EncryptXmlFile(
- String filePath, // 指定需要加密的文件
- String elementName, // 需要指定加密的元素
- bool bContent, // 是否只加密元素的内容?
- object key, // 加密密钥,可以是对称的,也可以是非对称的
- String keyName); // 指定加密密钥的名称(可选)
- // 加密指定的XmlDocument对象,该函数内部会循环调用EncryptXmlNode函数
- //(该函数分为对称密钥版和非对称密钥版)加密XmlDocument内部所有符合要求的节点。
- public static bool EncryptXmlDoc(
- XmlDocument xmlDoc, // 指定需要加密的XmlDocument对象
- String elementName, // 需要指定加密的元素
- bool bContent, // 是否只加密元素的内容?
- object key, // 加密密钥,可以是对称的,也可以是非对称的
- String keyName); // 指定加密密钥的名称(可选)
- // (核心功能)加密指定的节点(对称加密方式)
- public static bool EncryptXmlNode(
- XmlElement elementToEncrypt, // 指定需要加密的XmlElement对象(节点)
- bool bContent, // 是否只加密元素的内容?
- SymmetricAlgorithm salgKey, // 对称加密密钥
- String keyName); // 指定加密密钥的名称(可选)
- // (核心功能)加密指定的节点(非对称加密方式)
- public static bool EncryptXmlNode(
- XmlElement elementToEncrypt, // 指定需要加密的XmlElement对象(节点)
- bool bContent, // 是否只加密元素的内容?
- RSA rsaKey, // 对称加密密钥,用于加密sessionKey到<EncryptedKey>节点中去
- String keyName, // 指定加密密钥的名称(可选)
- SymmetricAlgorithm sessionKey); // 用于加密原始数据的对称密钥(注:加密数据只能用对称加密)
- // 解密指定的文件,该函数内部会调用DecryptXmlDoc函数。
- public static bool DecryptXmlFile(String filePath, object key, String keyName);
- // 解密指定的XmlDocument对象,该函数内部会循环调用DecryptXmlNode函数
- public static bool DecryptXmlDoc(XmlDocument xmlDoc, object key, String keyName);
- // (核心功能)解密指定的节点(对称加密方式和非对称加密方式统统放在一个函数内)
- public static bool DecryptXmlNode(XmlElement encryptedElement, SymmetricAlgorithm salgKey);
- // 该函数用于创建<EncryptionMethod>节点对象
- private static EncryptionMethod CreateEncryptionMethod(object keyAlg, bool isKeyWrapAlgUri, bool isOaep);
- // 该类用于解密使用RSA加密时,所使用到的sessionkey,内部调用GenerateSyAlgKey函数
- private static SymmetricAlgorithm DecryptKey(XmlDocument xmlDoc, object decryptKey);
- // 该类用于解密使用RSA加密时,所使用到的sessionkey
- private static SymmetricAlgorithm GenerateSyAlgKey(byte[] decryptedKeyData, EncryptionMethod encMethod);
- }
- }
该类基本上比较简单,我们只重点分析一下加密的核心功能。
- public static bool EncryptXmlNode(
- XmlElement elementToEncrypt,
- bool bContent,
- SymmetricAlgorithm salgKey,
- String keyName)
- {
- if (null == elementToEncrypt || null == salgKey)
- {
- return false;
- }
- try
- {
- // 1. Create a new instance of the EncryptedXml class and use it
- // to encrypt the XmlElement with the symmetric key.
- EncryptedXml eXml = new EncryptedXml();
- byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, salgKey, bContent);
- // 2. Construct an EncryptedData object and populate it
- // with the desired encryption information.
- EncryptedData edElement = new EncryptedData();
- edElement.Type = EncryptedXml.XmlEncElementUrl;
- // 3. Create an EncryptionMethod element so that the receiver
- // knows which algorithm to use for decryption.
- edElement.EncryptionMethod = CreateEncryptionMethod(salgKey, false, false);
- // 4. Set the KeyInfo element to specify the name of the key.
- if (null != keyName && !keyName.Equals(String.Empty))
- {
- // Create a new KeyInfo element.
- edElement.KeyInfo = new KeyInfo();
- // Create a new KeyInfoName element.
- KeyInfoName kin = new KeyInfoName();
- // Specify a name for the key.
- kin.Value = keyName;
- // Add the KeyInfoName element.
- edElement.KeyInfo.AddClause(kin);
- }
- // 5. Add the encrypted element data to the EncryptedData object.
- edElement.CipherData.CipherValue = encryptedElement;
- // 6. Replace the element from the original XmlDocument
- // object with the EncryptedData element.
- EncryptedXml.ReplaceElement(elementToEncrypt, edElement, bContent);
- return true;
- }
- catch (System.Exception ex)
- {
- }
- return false;
- }
加密某个节点分以下步骤:
<!--[if !supportLists]-->1.<!--[endif]-->创建 EncryptedXml类的新实例,并使用它通过对称密钥对 XmlElement进行加密。EncryptData方法将加密的元素作为加密字节的数组返回。
<!--[if !supportLists]-->2.<!--[endif]-->构造一个 EncryptedData对象,然后用 XML加密元素的 URL 标识符填充它。此 URL标识符使解密方知道 XML 包含一个加密元素。可以使用 XmlEncElementUrl字段指定 URL标识符。
<!--[if !supportLists]-->3.<!--[endif]-->创建 EncryptionMethod对象,该对象被初始化为用来生成密钥的加密算法的URL标识符。将 EncryptionMethod对象传递给 EncryptionMethod属性。
<!--[if !supportLists]-->4.<!--[endif]-->如果用户给加密数据的key设置了一个名称,那就创建一个KeyInfo的对象,并通过KeyInfoName为其指定一个名称。
<!--[if !supportLists]-->5.<!--[endif]-->将加密的元素数据添加到 EncryptedData对象中。
<!--[if !supportLists]-->6.<!--[endif]-->用EncryptedData元素替换原始 XmlDocument对象中的元素。
使用RSA加密的整体流程和这个类似,只不过多了一步加密sessionkey(加密原始数据的key)的过程。在这里我就不再赘述了,请直接看源代码。
以下是解密的代码:
- public static bool DecryptXmlDoc(XmlDocument xmlDoc, object key, String keyName)
- {
- try
- {
- // First, we try to decrypt xml document with EncryptedXml.DecryptDocument() method,
- // this method decrypts all <EncryptedData> elements of the XML document, but its precondition
- // is that the <EncryptedData> elements has been specified <KeyInfo>'s <KeyName>, if this element
- // hasn't been specified, it will failed and throw a CryptographicException exception.
- // Second, if we hasn't specified key name, we can only decrypt the document with SymmetricAlgorithm
- // key, this is restricted to the API of EncryptedXml class.
- if (null != keyName && !keyName.Equals(String.Empty))
- {
- // Create a new EncryptedXml object.
- EncryptedXml exml = new EncryptedXml(xmlDoc);
- // Add a key-name mapping.
- // This method can only decrypt documents that present the specified key name.
- exml.AddKeyNameMapping(keyName, key);
- // Decrypt the element.
- exml.DecryptDocument();
- return true;
- }
- else
- {
- SymmetricAlgorithm salgKey = null;
- RSA rsaKey = null;
- if (key is SymmetricAlgorithm)
- {
- salgKey = key as SymmetricAlgorithm;
- }
- else if (key is RSA)
- {
- rsaKey = key as RSA;
- salgKey = DecryptKey(xmlDoc, key);
- }
- else
- {
- return false;
- }
- XmlNodeList nodeList = xmlDoc.GetElementsByTagName("EncryptedData");
- int nCount = nodeList.Count;
- for (int ix = 0; ix < nCount; ++ix)
- {
- XmlElement encryptedElement = nodeList[0] as XmlElement;
- if (null != salgKey)
- {
- if (!DecryptXmlNode(encryptedElement, salgKey))
- {
- return false;
- }
- }
- }
- return true;
- }
- }
- catch (System.Exception ex)
- {
- }
- return false;
解密分两步:
<!--[if !supportLists]-->1. <!--[endif]-->如果给出了keyName和解密密钥,那么直接使用EncryptedXml的DecryptDocument方法。
<!--[if !supportLists]-->2. <!--[endif]-->否则,我们就需要一个节点一个节点的解密了。对于非对称的解密,一般直接使用DecryptDocument方法就可以了。
整个代码如下:
GTXXmlCrypt代码:
- /*!
- * @file GTXXmlCrypt.cs
- *
- * @brief This file implements the class of GTXXmlCrypt.
- * This class is used to crypt or decrypt xml file.
- *
- * Copyright (C) 2011, GTX.
- *
- * @author Liu Lin
- * @date 2011/6/19
- */
- using System;
- using System.IO;
- using System.Security.AccessControl;
- using System.Security.Cryptography;
- using System.Security.Cryptography.Xml;
- using System.Security.Principal;
- using System.Xml;
- namespace GTXUtility.Security.Crypt
- {
- /// <summary>
- /// This class is used to encrypt xml file with Symmetric Encryption Algorithm (such as
- /// DES, AES, TripleDES and so on) and Asymmetric Encryption Algorithm (such as RSA).
- /// </summary>
- /// <remarks>
- /// Expressed in shorthand form, the EncryptedData element has the following structure:
- /// (where "?" denotes zero or one occurrence;
- /// "+" denotes one or more occurrences;
- /// "*" denotes zero or more occurrences;
- /// and the empty element tag means the element must be empty )
- /// <EncryptedData Id? Type? MimeType? Encoding?>
- /// <EncryptionMethod/>?
- /// <ds:KeyInfo>
- /// <EncryptedKey>?
- /// <AgreementMethod>?
- /// <ds:KeyName>?
- /// <ds:RetrievalMethod>?
- /// <ds:*>?
- /// </ds:KeyInfo>?
- /// <CipherData>
- /// <CipherValue>?
- /// <CipherReference URI?>?
- /// </CipherData>
- /// <EncryptionProperties>?
- /// </EncryptedData>
- /// The <EncryptedKey> is the same with the <EncryptedData>.
- /// To get some more informations, please attach the following references.
- /// http://www.w3.org/TR/xmlenc-core/
- /// http://msdn.microsoft.com/zh-cn/library/system.security.cryptography.xml.encryptedxml.aspx
- /// </remarks>
- public class GTXXmlCrypt
- {
- /// <summary>
- /// Defines Symmetric Encryption Algorithm types.
- /// </summary>
- public enum SymmetricAlgTypes
- {
- DES = 1,
- AES128, // Rijndael 128
- AES192, // Rijndael 192
- AES256, // Rijndael 256
- TripleDES,
- }
- /// <summary>
- /// Create a Symmetric Encryption Algorithm object.
- /// </summary>
- /// <param name="salType">Specified Symmetric Encryption Algorithm type.</param>
- /// <returns>If create success, returns the Symmetric Encryption Algorithm object.
- /// Otherwise, return null object.</returns>
- public static SymmetricAlgorithm CreateSymmetricAlgorithm(SymmetricAlgTypes salType)
- {
- SymmetricAlgorithm symAlg = null;
- switch (salType)
- {
- case SymmetricAlgTypes.DES:
- symAlg = SymmetricAlgorithm.Create("DES");
- break;
- case SymmetricAlgTypes.AES128:
- symAlg = SymmetricAlgorithm.Create("Rijndael");
- symAlg.KeySize = 128;
- break;
- case SymmetricAlgTypes.AES192:
- symAlg = SymmetricAlgorithm.Create("Rijndael");
- symAlg.KeySize = 192;
- break;
- case SymmetricAlgTypes.AES256:
- symAlg = SymmetricAlgorithm.Create("Rijndael");
- symAlg.KeySize = 256;
- break;
- case SymmetricAlgTypes.TripleDES:
- symAlg = SymmetricAlgorithm.Create("TripleDES");
- break;
- default:
- break;
- }
- return symAlg;
- }
- /// <summary>
- /// This method has two use.
- /// First, create a RSA encryption algorithm object when first use it, it'll
- /// stroe the RSA key into key container which specified by the paramter.
- /// Second, this method can get the RSA key from container when use for second time.
- /// The container name must be the same with the first.
- /// </summary>
- /// <param name="containerName">The key container name.</param>
- /// <returns>Returns the instance of RSA.</returns>
- /// <remarks>
- /// Microsoft recommends to store asymmetric keys in a key container.
- /// http://msdn.microsoft.com/zh-cn/library/tswxhw92(VS.80).aspx
- /// </remarks>
- public static RSA CreateRSAAlgorithm(String containerName)
- {
- RSACryptoServiceProvider rsaKey = null;
- try
- {
- // Create a new CspParameters object to specify a key container.
- CspParameters cspParams = new CspParameters();
- cspParams.KeyContainerName = containerName;
- cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
- // Add the key's access privilege
- CryptoKeySecurity keySecurity = new CryptoKeySecurity();
- SecurityIdentifier si = new SecurityIdentifier(WellKnownSidType.LocalSid/*WorldSid*/, null);
- keySecurity.AddAccessRule(new CryptoKeyAccessRule(si, CryptoKeyRights.FullControl, AccessControlType.Allow));
- cspParams.CryptoKeySecurity = keySecurity;
- // Create a new RSA key and save it in the container. This key will encrypt
- // a symmetric key, which will then be encrypted in the XML document.
- rsaKey = new RSACryptoServiceProvider(cspParams);
- }
- catch (System.Exception ex)
- {
- }
- return rsaKey;
- }
- /// <summary>
- /// Encrypt a xml file's elements by specified key.
- /// </summary>
- /// <param name="filePath">The path of xml file which needs to be encrypted.</param>
- /// <param name="elementName">The element (node) in xml file which needs to be encrypted.</param>
- /// <param name="bContent">Whether to encrypt the element content or not. true to
- /// encrypt only the contents of the element; false to encrypt the entire element.</param>
- /// <param name="key">The specified encryption key.</param>
- /// <param name="keyName">The key name which used to display the <KeyInfo> in encrypted xml.
- /// It can be empty or null.</param>
- /// <returns>If encrypt success, return true, otherwise, return false.</returns>
- /// <remarks>After encryption success, it'll save the new data into xml file.</remarks>
- public static bool EncryptXmlFile(
- String filePath,
- String elementName,
- bool bContent,
- object key,
- String keyName)
- {
- if (File.Exists(filePath) && Path.GetExtension(filePath).ToLower().Equals(".xml") &&
- null != elementName && !elementName.Equals(String.Empty) &&
- null != key)
- {
- XmlDocument xmlDoc = new XmlDocument();
- xmlDoc.PreserveWhitespace = true;
- xmlDoc.Load(filePath);
- if (EncryptXmlDoc(xmlDoc, elementName, bContent, key, keyName))
- {
- xmlDoc.Save(filePath);
- return true;
- }
- return false;
- }
- return false;
- }
- /// <summary>
- /// Encrypt a xml document's elements by specified key.
- /// </summary>
- /// <param name="xmlDoc">The XmlDocument object which needs to be encrypted.</param>
- /// <param name="elementName">The element (node) in xml file which needs to be encrypted.</param>
- /// <param name="bContent">Whether to encrypt the element content or not. true to
- /// encrypt only the contents of the element; false to encrypt the entire element.</param>
- /// <param name="key">The specified encryption key.</param>
- /// <param name="keyName">The key name which used to display the <KeyInfo> in encrypted xml.
- /// It can be empty or null.</param>
- /// <returns>If encrypt success, return true, otherwise, return false.</returns>
- public static bool EncryptXmlDoc(
- XmlDocument xmlDoc,
- String elementName,
- bool bContent,
- object key,
- String keyName)
- {
- SymmetricAlgorithm salgKey = null;
- RSA rsaKey = null;
- SymmetricAlgorithm sessionKey = null;
- // If currnet key is SymmetricAlgorithm, we'll use this key to encrypt elemnet.
- // Else if currnet key is RSA, we need to create a session key to encrypt elemnet,
- // and the RSA key is used to encrypt session key. Please pay more attention.
- if (key is SymmetricAlgorithm)
- {
- salgKey = key as SymmetricAlgorithm;
- }
- else if (key is RSA)
- {
- rsaKey = key as RSA;
- sessionKey = CreateSymmetricAlgorithm(SymmetricAlgTypes.DES/*AES256*/);
- }
- else
- {
- return false;
- }
- try
- {
- XmlNodeList nodeList = xmlDoc.GetElementsByTagName(elementName);
- int nCount = nodeList.Count;
- if (0 == nCount)
- {
- return false;
- }
- for (int ix = 0; ix < nCount; ++ix)
- {
- // Please pay more attention about the follows:
- // If we want to encrypt a node (XmlElement) in node list, the node will be delete
- // after we encrypt it and the count will be decremented, as a result, each time
- // we need to encrypt nodeList[0].
- // But if we want to encrypt a node's content in node list, the node will NOT be delete
- // after we encrypt it and the count will NOT be decremented, as a result, each time
- // we need to encrypt nodeList[ix].
- XmlElement elementToEncrypt = bContent ? (nodeList[ix] as XmlElement) : (nodeList[0] as XmlElement);
- if (null != salgKey)
- {
- if (!EncryptXmlNode(elementToEncrypt, bContent, salgKey, keyName))
- {
- return false;
- }
- }
- else if (null != rsaKey)
- {
- if (!EncryptXmlNode(elementToEncrypt, bContent, rsaKey, keyName, sessionKey))
- {
- return false;
- }
- }
- }
- return true;
- }
- catch (System.Exception ex)
- {
- }
- finally
- {
- // Clear session key.
- if (null != sessionKey)
- {
- sessionKey.Clear();
- }
- }
- return false;
- }
- /// <summary>
- /// Encrypt a xml element (node) by specified Symmetric Algorithm key.
- /// </summary>
- /// <param name="elementToEncrypt">The element which needs to be encrypted.</param>
- /// <param name="bContent">Whether to encrypt the element content or not. true to
- /// encrypt only the contents of the element; false to encrypt the entire element.</param>
- /// <param name="salgKey">Specified Symmetric Algorithm key.</param>
- /// <param name="keyName">The key name which used to display the <KeyInfo> in encrypted xml.
- /// It can be empty or null.</param>
- /// <returns>If encrypt success, return true, otherwise, return false.</returns>
- public static bool EncryptXmlNode(
- XmlElement elementToEncrypt,
- bool bContent,
- SymmetricAlgorithm salgKey,
- String keyName)
- {
- if (null == elementToEncrypt || null == salgKey)
- {
- return false;
- }
- try
- {
- // 1. Create a new instance of the EncryptedXml class and use it
- // to encrypt the XmlElement with the symmetric key.
- EncryptedXml eXml = new EncryptedXml();
- byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, salgKey, bContent);
- // 2. Construct an EncryptedData object and populate it
- // with the desired encryption information.
- EncryptedData edElement = new EncryptedData();
- edElement.Type = EncryptedXml.XmlEncElementUrl;
- // 3. Create an EncryptionMethod element so that the receiver
- // knows which algorithm to use for decryption.
- edElement.EncryptionMethod = CreateEncryptionMethod(salgKey, false, false);
- // 4. Set the KeyInfo element to specify the name of the key.
- if (null != keyName && !keyName.Equals(String.Empty))
- {
- // Create a new KeyInfo element.
- edElement.KeyInfo = new KeyInfo();
- // Create a new KeyInfoName element.
- KeyInfoName kin = new KeyInfoName();
- // Specify a name for the key.
- kin.Value = keyName;
- // Add the KeyInfoName element.
- edElement.KeyInfo.AddClause(kin);
- }
- // 5. Add the encrypted element data to the EncryptedData object.
- edElement.CipherData.CipherValue = encryptedElement;
- // 6. Replace the element from the original XmlDocument
- // object with the EncryptedData element.
- EncryptedXml.ReplaceElement(elementToEncrypt, edElement, bContent);
- return true;
- }
- catch (System.Exception ex)
- {
- }
- return false;
- }
- /// <summary>
- /// Encrypt a xml element (node) by specified RSA key.
- /// Actually, it w
- /// </summary>
- /// <param name="elementToEncrypt">The element which needs to be encrypted.</param>
- /// <param name="bContent">Whether to encrypt the element content or not. true to
- /// encrypt only the contents of the element; false to encrypt the entire element.</param>
- /// <param name="rsaKey">Specified RSA key, which used to encrypt the session key.</param>
- /// <param name="keyName">The key name which used to display the <KeyInfo> in encrypted xml.
- /// It can be empty or null.</param>
- /// <param name="sessionKey">The specified Symmetric Algorithm key used to encrypt xml element data.</param>
- /// <returns>If encrypt success, return true, otherwise, return false.</returns>
- /// <remarks>Actually, I don't think it's a RSA encryption, because the RSA key is only used to
- /// encrypt the session key, not used to encrypt xml element data.</remarks>
- public static bool EncryptXmlNode(
- XmlElement elementToEncrypt,
- bool bContent,
- RSA rsaKey,
- String keyName,
- SymmetricAlgorithm sessionKey)
- {
- if (null == elementToEncrypt || null == rsaKey)
- {
- return false;
- }
- try
- {
- // 1. Create a new instance of the EncryptedXml class and use it to
- // encrypt the XmlElement with the a new random symmetric key.
- // Encrypt the xml's element and get the crypted data.
- EncryptedXml eXml = new EncryptedXml();
- byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, sessionKey, bContent);
- // 2. Construct an EncryptedData object and populate
- // it with the desired encryption information.
- EncryptedData edElement = new EncryptedData();
- edElement.Type = EncryptedXml.XmlEncElementUrl;
- // 3. Create an EncryptionMethod element so that the
- // receiver knows which algorithm to use for decryption.
- edElement.EncryptionMethod = CreateEncryptionMethod(sessionKey, false, false);
- // 4. Encrypt the session key and add it to an EncryptedKey element.
- EncryptedKey ek = new EncryptedKey();
- byte[] encryptedKey = EncryptedXml.EncryptKey(sessionKey.Key, rsaKey, false);
- ek.CipherData = new CipherData(encryptedKey);
- ek.EncryptionMethod = CreateEncryptionMethod(rsaKey, false, false);
- // 5. Set the KeyInfo element to specify the name of the RSA key.
- if (null != keyName && !keyName.Equals(String.Empty))
- {
- // Create a new KeyInfo element.
- edElement.KeyInfo = new KeyInfo();
- // Create a new KeyInfoName element.
- KeyInfoName kin = new KeyInfoName();
- // Specify a name for the key.
- kin.Value = keyName;
- // Add the KeyInfoName element to the EncryptedKey object.
- ek.KeyInfo.AddClause(kin);
- }
- // 6. Add the encrypted key to the EncryptedData object.
- edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek));
- // Add the encrypted element data to the EncryptedData object.
- edElement.CipherData.CipherValue = encryptedElement;
- // 7. Replace the element from the original XmlDocument
- // object with the EncryptedData element.
- EncryptedXml.ReplaceElement(elementToEncrypt, edElement, bContent);
- return true;
- }
- catch (System.Exception ex)
- {
- }
- return false;
- }
- /// <summary>
- /// Encrypt a xml file's elements by specified key.
- /// </summary>
- /// <param name="filePath">The path of xml file which needs to be encrypted.</param>
- /// <param name="elementName">The element (node) in xml file which needs to be encrypted.</param>
- /// <param name="bContent">Whether to encrypt the element content or not. true to
- /// encrypt only the contents of the element; false to encrypt the entire element.</param>
- /// <param name="key">The specified encryption key.</param>
- /// <param name="keyName">The key name which used to display the <KeyInfo> in encrypted xml.
- /// It can be empty or null.</param>
- /// <returns>If encrypt success, return true, otherwise, return false.</returns>
- /// <remarks>After encryption success, it'll save the new data into xml file.</remarks>
- /// <summary>
- /// Decrypt a xml file's elements by specified key.
- /// </summary>
- /// <param name="filePath">The path of xml file which needs to be decrypted.</param>
- /// <param name="key">The specified decryption key which used to encrypt before.</param>
- /// <param name="keyName">The key name which used to display the <KeyInfo> in encrypted xml.
- /// It can be empty or null.</param>
- /// <returns>If decrypt success, return true, otherwise, return false.</returns>
- /// <remarks>After decryption success, it'll save the new data into xml file.</remarks>
- public static bool DecryptXmlFile(String filePath, object key, String keyName)
- {
- if (File.Exists(filePath) && Path.GetExtension(filePath).ToLower().Equals(".xml") &&
- null != key)
- {
- XmlDocument xmlDoc = new XmlDocument();
- xmlDoc.PreserveWhitespace = true;
- xmlDoc.Load(filePath);
- if (DecryptXmlDoc(xmlDoc, key, keyName))
- {
- xmlDoc.Save(filePath);
- return true;
- }
- return false;
- }
- return false;
- }
- /// <summary>
- /// Decrypt a xml document's elements by specified key.
- /// </summary>
- /// <param name="xmlDoc">The XmlDocument object which needs to be decrypted.</param>
- /// <param name="key">The specified decryption key which used to encrypt before.</param>
- /// <param name="keyName">The key name which used to display the <KeyInfo> in encrypted xml.
- /// It can be empty or null.</param>
- /// <returns>If decrypt success, return true, otherwise, return false.</returns>
- public static bool DecryptXmlDoc(XmlDocument xmlDoc, object key, String keyName)
- {
- try
- {
- // First, we try to decrypt xml document with EncryptedXml.DecryptDocument() method,
- // this method decrypts all <EncryptedData> elements of the XML document, but its precondition
- // is that the <EncryptedData> elements has been specified <KeyInfo>'s <KeyName>, if this element
- // hasn't been specified, it will failed and throw a CryptographicException exception.
- // Second, if we hasn't specified key name, we can only decrypt the document with SymmetricAlgorithm
- // key, this is restricted to the API of EncryptedXml class.
- if (null != keyName && !keyName.Equals(String.Empty))
- {
- // Create a new EncryptedXml object.
- EncryptedXml exml = new EncryptedXml(xmlDoc);
- // Add a key-name mapping.
- // This method can only decrypt documents that present the specified key name.
- exml.AddKeyNameMapping(keyName, key);
- // Decrypt the element.
- exml.DecryptDocument();
- return true;
- }
- else
- {
- SymmetricAlgorithm salgKey = null;
- RSA rsaKey = null;
- if (key is SymmetricAlgorithm)
- {
- salgKey = key as SymmetricAlgorithm;
- }
- else if (key is RSA)
- {
- rsaKey = key as RSA;
- salgKey = DecryptKey(xmlDoc, key);
- }
- else
- {
- return false;
- }
- XmlNodeList nodeList = xmlDoc.GetElementsByTagName("EncryptedData");
- int nCount = nodeList.Count;
- for (int ix = 0; ix < nCount; ++ix)
- {
- XmlElement encryptedElement = nodeList[0] as XmlElement;
- if (null != salgKey)
- {
- if (!DecryptXmlNode(encryptedElement, salgKey))
- {
- return false;
- }
- }
- }
- return true;
- }
- }
- catch (System.Exception ex)
- {
- }
- return false;
- }
- /// <summary>
- /// Decrypt xml element (node) by specified Symmetric Algorithm key.
- /// </summary>
- /// <param name="encryptedElement">The xml element which needs to be decrypted.</param>
- /// <param name="salgKey">Specified Symmetric Algorithm key.</param>
- /// <returns>If decrypt success, return true, otherwise, return false.</returns>
- /// <remarks>We can only use Symmetric Algorithm key to decrypt xml element data but RSA,
- /// because this is restricted to the API of EncryptedXml class. Please note it on MSDN.</remarks>
- public static bool DecryptXmlNode(XmlElement encryptedElement, SymmetricAlgorithm salgKey)
- {
- try
- {
- // 1. Construct an EncryptedData object and populate it
- // with the desired encryption information.
- EncryptedData edElement = new EncryptedData();
- edElement.LoadXml(encryptedElement);
- // 2. Create a new instance of the EncryptedXml class and use it
- // to encrypt the XmlElement with the symmetric key.
- EncryptedXml eXml = new EncryptedXml();
- byte[] rgbOutput = eXml.DecryptData(edElement, salgKey);
- // 3. Replace the encryptedData element with the plaintext XML element.
- eXml.ReplaceData(encryptedElement, rgbOutput);
- return true;
- }
- catch (System.Exception ex)
- {
- }
- return false;
- }
- /// <summary>
- /// Retrieve the EncryptionMethod object which contain in EncryptionData.
- /// </summary>
- /// <param name="keyAlg">Specified encryption algorithm object.</param>
- /// <param name="isKeyWrapAlgUri">Whether the namespace Uniform Resource Identifier (URI)
- /// for Wrap algorithm or not. This can be used only the keyAlg is a Symmetric Encryption Algorithm.
- /// If used this, the isOaep will be ignored.</param>
- /// <param name="isOaep">Whether to use RSA Optimal Asymmetric Encryption Padding (OAEP)
- /// encryption algorithm. This can be used only the keyAlg is a RSA Asymmetric.
- /// If used this, the isKeyWrapAlgUri will be ignored.</param>
- /// <returns>Return the EncryptionMethod object.</returns>
- private static EncryptionMethod CreateEncryptionMethod(object keyAlg, bool isKeyWrapAlgUri, bool isOaep)
- {
- EncryptionMethod encMethod = new EncryptionMethod();
- String URI = String.Empty;
- if (keyAlg is DES)
- {
- encMethod.KeyAlgorithm = EncryptedXml.XmlEncDESUrl;
- //encMethod.KeySize = 0; [exception, why?]
- }
- else if (keyAlg is Rijndael)
- {
- switch ((keyAlg as Rijndael).KeySize)
- {
- case 128:
- encMethod.KeyAlgorithm = isKeyWrapAlgUri ?
- EncryptedXml.XmlEncAES128KeyWrapUrl : EncryptedXml.XmlEncAES128Url;
- encMethod.KeySize = 128;
- break;
- case 192:
- encMethod.KeyAlgorithm = isKeyWrapAlgUri ?
- EncryptedXml.XmlEncAES192KeyWrapUrl : EncryptedXml.XmlEncAES192Url;
- encMethod.KeySize = 192;
- break;
- case 256:
- encMethod.KeyAlgorithm = isKeyWrapAlgUri ?
- EncryptedXml.XmlEncAES256KeyWrapUrl : EncryptedXml.XmlEncAES256Url;
- encMethod.KeySize = 256;
- break;
- default:
- break;
- }
- }
- else if (keyAlg is TripleDES)
- {
- encMethod.KeyAlgorithm = isKeyWrapAlgUri ?
- EncryptedXml.XmlEncTripleDESKeyWrapUrl : EncryptedXml.XmlEncTripleDESUrl;
- //encMethod.KeySize = 0; [exception, why?]
- }
- else if (keyAlg is RSA)
- {
- encMethod.KeyAlgorithm = isOaep ?
- EncryptedXml.XmlEncRSAOAEPUrl : EncryptedXml.XmlEncRSA15Url;
- }
- else
- {
- // Do nothing
- }
- return encMethod;
- }
- /// <summary>
- /// Decrypt encryption key (in node of <EncryptedKey>) which used to encrypt xml element.
- /// </summary>
- /// <param name="xmlDoc">The encrypted XmlDocument object.</param>
- /// <param name="decryptKey">The key which used to decrypt encryption key.
- /// The key must be Triple DES Key Wrap algorithm or the Advanced Encryption Standard
- /// (AES) Key Wrap algorithm (also called Rijndael) or RSA key.</param>
- /// <returns>Return Symmetric Algorithm key object whihc used to decrypt xml element.</returns>
- private static SymmetricAlgorithm DecryptKey(XmlDocument xmlDoc, object decryptKey)
- {
- XmlNodeList encKeyNodeList = xmlDoc.GetElementsByTagName("EncryptedKey");
- XmlNodeList encDataNodeList = xmlDoc.GetElementsByTagName("EncryptedData");
- if (encDataNodeList.Count > 0 && encKeyNodeList.Count > 0)
- {
- XmlElement encryptedKey = encKeyNodeList[0] as XmlElement;
- EncryptedKey ek = new EncryptedKey();
- ek.LoadXml(encryptedKey);
- byte[] decryptedData = null;
- //if (decryptKey is SymmetricAlgorithm)
- if (decryptKey is Rijndael || decryptKey is TripleDES)
- {
- decryptedData = EncryptedXml.DecryptKey(ek.CipherData.CipherValue, (SymmetricAlgorithm)decryptKey);
- }
- else if (decryptKey is RSA)
- {
- // kek is an RSA key: get fOAEP from the algorithm, default to false
- bool fOAEP = (ek.EncryptionMethod != null && ek.EncryptionMethod.KeyAlgorithm == EncryptedXml.XmlEncRSAOAEPUrl);
- decryptedData = EncryptedXml.DecryptKey(ek.CipherData.CipherValue, (RSA)decryptKey, fOAEP);
- }
- else
- {
- // The key (decryptKey) used to decrypt encryption data key is not the Triple DES Key Wrap algorithm
- // or the Advanced Encryption Standard (AES) Key Wrap algorithm (also called Rijndael).
- return null;
- }
- XmlElement encryptDataXml = encDataNodeList[0] as XmlElement;
- EncryptedData encryptData = new EncryptedData();
- encryptData.LoadXml(encryptDataXml);
- return GenerateSyAlgKey(decryptedData, encryptData.EncryptionMethod);
- }
- return null;
- }
- /// <summary>
- /// Generate a Symmetric Algorithm key by specified key data and EncryptionMethod object.
- /// </summary>
- /// <param name="decryptedKeyData">Key data.</param>
- /// <param name="encMethod">The EncryptionMethod object.</param>
- /// <returns>Return Symmetric Algorithm key object whihc used to decrypt xml element.</returns>
- private static SymmetricAlgorithm GenerateSyAlgKey(byte[] decryptedKeyData, EncryptionMethod encMethod)
- {
- if (null == encMethod || null == decryptedKeyData || 0 == decryptedKeyData.Length)
- {
- return null;
- }
- String keyAlg = encMethod.KeyAlgorithm;
- int keySize = encMethod.KeySize;
- SymmetricAlgorithm symAlg = null;
- if (keyAlg.Equals(EncryptedXml.XmlEncDESUrl))
- {
- symAlg = SymmetricAlgorithm.Create("DES");
- symAlg.Key = decryptedKeyData;
- }
- else if (keyAlg.Equals(EncryptedXml.XmlEncAES128Url) || keyAlg.Equals(EncryptedXml.XmlEncAES128KeyWrapUrl))
- {
- symAlg = SymmetricAlgorithm.Create("Rijndael");
- symAlg.KeySize = 128;
- symAlg.Key = decryptedKeyData;
- }
- else if (keyAlg.Equals(EncryptedXml.XmlEncAES192Url) || keyAlg.Equals(EncryptedXml.XmlEncAES192KeyWrapUrl))
- {
- symAlg = SymmetricAlgorithm.Create("Rijndael");
- symAlg.KeySize = 192;
- symAlg.Key = decryptedKeyData;
- }
- else if (keyAlg.Equals(EncryptedXml.XmlEncAES256Url) || keyAlg.Equals(EncryptedXml.XmlEncAES256KeyWrapUrl))
- {
- symAlg = SymmetricAlgorithm.Create("Rijndael");
- symAlg.KeySize = 256;
- symAlg.Key = decryptedKeyData;
- }
- else if (keyAlg.Equals(EncryptedXml.XmlEncTripleDESUrl) || keyAlg.Equals(EncryptedXml.XmlEncTripleDESKeyWrapUrl))
- {
- symAlg = SymmetricAlgorithm.Create("TripleDES");
- symAlg.Key = decryptedKeyData;
- }
- else
- {
- }
- return symAlg;
- }
- }
- }
测试代码:
- using System;
- using System.IO;
- using System.Security.Cryptography;
- using System.Text;
- using System.Xml;
- using GTXUtility.Security.Crypt;
- namespace TestUtility
- {
- public class TestXmlCrypt
- {
- enum PrintTypes
- {
- PrintOriginal,
- PrintEncrypt,
- PrintDecrypt
- }
- public static void UseDemo()
- {
- Console.WriteLine("Test Xml Crypt begin...");
- Console.WriteLine("Input file path: (You can drag a file into console without input file path)");
- String filePath = Console.ReadLine();
- if (File.Exists(filePath))
- {
- PrintXml(filePath, PrintTypes.PrintOriginal);
- Console.WriteLine("Select Symmetric/Asymmetric(RSA) Algorithm, 0: Symmetric, 1: Asymmetric (Default is Symmetric)");
- String alg = Console.ReadLine();
- int nAlg = alg.Equals("1") ? 1 : 0;
- switch (nAlg)
- {
- case 0:
- TestSymmetricAlgorithm(filePath);
- break;
- case 1:
- TestAsymmetricAlgorithm(filePath);
- break;
- default:
- break;
- }
- }
- Console.WriteLine("Test Xml Crypt end...");
- }
- private static void TestSymmetricAlgorithm(String filePath)
- {
- Console.WriteLine("Select the encrypt/decrypt algorithm: (Default is DES)");
- GTXXmlCrypt.SymmetricAlgTypes salTypeTemp = GTXXmlCrypt.SymmetricAlgTypes.DES;
- for (; salTypeTemp <= GTXXmlCrypt.SymmetricAlgTypes.TripleDES; ++salTypeTemp)
- {
- Console.WriteLine("{0} is {1}", (int)salTypeTemp, salTypeTemp.ToString());
- }
- // Read the symmetric algorithm command
- String algString = Console.ReadLine();
- GTXXmlCrypt.SymmetricAlgTypes salType = GTXXmlCrypt.SymmetricAlgTypes.DES;
- try
- {
- salType = (GTXXmlCrypt.SymmetricAlgTypes)Convert.ToInt32(algString);
- if (salType <= GTXXmlCrypt.SymmetricAlgTypes.DES &&
- salType >= GTXXmlCrypt.SymmetricAlgTypes.TripleDES)
- {
- salType = GTXXmlCrypt.SymmetricAlgTypes.DES;
- }
- }
- catch (System.Exception ex)
- {
- salType = GTXXmlCrypt.SymmetricAlgTypes.DES;
- }
- // Read the node which we want to encrypt/decrypt
- Console.WriteLine("Input the XML element node:");
- String elementName = Console.ReadLine();
- Console.WriteLine("Encrypt node element or its content, 0: Element, 1: Only content (Default is Element)");
- String content = Console.ReadLine();
- bool bContent = content.Equals("1") ? true : false;
- SymmetricAlgorithm sal = GTXXmlCrypt.CreateSymmetricAlgorithm(salType);
- if (GTXXmlCrypt.EncryptXmlFile(filePath, elementName, bContent, sal, "abc"))
- {
- // Print the encrypted XML to console
- Console.WriteLine("Encrypt XML with {0} algorithm Succeed!", salType);
- PrintXml(filePath, PrintTypes.PrintEncrypt);
- if (GTXXmlCrypt.DecryptXmlFile(filePath, sal, /*"abc"*/""))
- {
- // Print the decrypted XML to console
- Console.WriteLine("Decrypt XML with {0} algorithm Succeed!", salType);
- PrintXml(filePath, PrintTypes.PrintDecrypt);
- }
- else
- {
- Console.WriteLine("Decrypt with {0} algorithm Failed!", salType);
- }
- }
- else
- {
- Console.WriteLine("Encrypt with {0} algorithm Failed!", salType);
- }
- }
- private static void TestAsymmetricAlgorithm(String filePath)
- {
- String keyContainerName = "rsakey container";
- RSA rsaKey = GTXXmlCrypt.CreateRSAAlgorithm(keyContainerName);
- try
- {
- // Read the node which we want to encrypt/decrypt
- Console.WriteLine("Input the XML element node:");
- String elementName = Console.ReadLine();
- Console.WriteLine("Encrypt node element or its content, 0: Element, 1: Only content (Default is Element)");
- String content = Console.ReadLine();
- bool bContent = content.Equals("1") ? true : false;
- if (GTXXmlCrypt.EncryptXmlFile(filePath, elementName, bContent, rsaKey, ""/*"rsakey"*/))
- {
- // Print the encrypted XML to console
- Console.WriteLine("Encrypt XML with RSA algorithm Succeed!");
- PrintXml(filePath, PrintTypes.PrintEncrypt);
- if (GTXXmlCrypt.DecryptXmlFile(filePath, rsaKey, ""/*"rsakey"*/))
- {
- PrintXml(filePath, PrintTypes.PrintDecrypt);
- Console.WriteLine("Decrypt XML with RSA algorithm Succeed!");
- }
- else
- {
- Console.WriteLine("Decrypt XML with RSA algorithm Failed!");
- }
- }
- else
- {
- Console.WriteLine("Encrypt xml with RSA algorithm Failed!");
- }
- }
- catch (System.Exception ex)
- {
- Console.WriteLine(ex.Message);
- }
- finally
- {
- rsaKey.Clear();
- }
- }
- static void PrintXml(String filePath, PrintTypes printType)
- {
- String format = String.Empty;
- switch (printType)
- {
- case PrintTypes.PrintOriginal:
- format = "■ Original file:/n{0}";
- break;
- case PrintTypes.PrintEncrypt:
- format = "■ Encryptd file:/n{0}";
- break;
- case PrintTypes.PrintDecrypt:
- format = "■ Decrypted file:/n{0}";
- break;
- }
- XmlDocument doc = new XmlDocument();
- //doc.PreserveWhitespace = true;
- doc.Load(filePath);
- XmlWriterSettings xmlSetting = new XmlWriterSettings();
- xmlSetting.Indent = true;
- xmlSetting.IndentChars = "/t";
- xmlSetting.Encoding = Encoding.UTF8;
- MemoryStream stream = new MemoryStream();
- XmlWriter writer = XmlWriter.Create(stream, xmlSetting);
- doc.Save(writer);
- doc.Save(filePath);
- // Reload the file and update the doc.InnerXml property.
- doc.PreserveWhitespace = true;
- doc.Load(filePath);
- Console.WriteLine(format, doc.InnerXml);
- }
- }
- }
主函数:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace TestUtility
- {
- class Program
- {
- static void Main(string[] args)
- {
- TestXmlCrypt.UseDemo();
- }
- }
- }
如果该代码存在问题或者您有好的建议,请第一时间通知我,让我再将这份代码完善一下。
哎,CSDN的这个blog编辑器实在是太令人失望了,格式实在是太难调整了。