淺析XML的數(shù)據(jù)加密算法
xml加密(XML Encryption)是w3c加密xml的標準。這個加密過程包括加密xml文檔的元素及其子元素,通過加密,xml的初始內(nèi)容將被替換,但其xml格式仍然被完好的保留。

我們有3個加密xml的方法:
1、僅僅使用對稱加密的方法加密xml
這種加密方法只使用一個密鑰,也就是說無論是加密xml還是解密xml都使用一個相同的密鑰。因為這個密鑰不會在被加密的xml中保存,所以我們需要在加密和解密的過程中加載這個密鑰并保護它不被竊取。
2、使用對稱加密和非對稱加密相結(jié)合的方法來加密xml
這種方法需要一個用于加密數(shù)據(jù)的對稱密鑰和一個用于保護這個對稱密鑰的非對稱密鑰。被加密的對稱密鑰和被加密的數(shù)據(jù)一起保存在xml文檔中。當(dāng)用私有非對稱密鑰解密密鑰的時候要用公開非對稱密鑰對密鑰進行加密。
3、使用X.509加密xml,這種方法是用X.509作為非對稱密鑰,它由諸如VeriSign之類的第三方提供。
不管xml加密是如何完成的,保存加密數(shù)據(jù)總是用兩種方法之一。
1、加密后所有的元素都被命名為<EncryptedData>
2、加密后只有數(shù)據(jù)被替換,而元素名稱仍然是可讀的,不會發(fā)生變化。
這種微妙的變化是非常重要的。例如:
如果你的xml文檔中包括被稱為<employee>的根元素,該根元素有一個下存儲了一段詳細信息的被稱做<WrittenWarning>的子元素。如果你發(fā)送這個xml,并且想<WrittenWarning>這個元素被保護起來,那么使用第1中方法的話<WrittenWarning>將被替換為<EncryptedData>,你不會從加密后的文檔中獲取到任何可讀的信息。
如果使用第2種方法,那么<WrittenWarning>元素仍然被保留,只用數(shù)據(jù)會被加密。任何得到這個文檔的人雖然不能知道該元素下的詳細信息,但仍然知道有一些事情發(fā)生在這個雇員身上。另外,<WrittenWarning>元素的所有屬性也不會被加密。
所以,如果沒有特殊需求,我們一般都用第1種方法。在.net 2.0中你可以通過修改一個Boolean值的屬性,便可以非常簡單的選擇使用哪種方法。
author元素及其子元素都將被<EncryptedData>給替換掉,另外還包括其他一些元素,如加密算法,密鑰等。
<EncryptedData>元素
仔細看看<EncryptedData>元素的樹形結(jié)構(gòu),你會發(fā)現(xiàn)<EncryptedData>元素下分解出了很多子元素。其中<KeyInfo>元素與xml數(shù)字簽名中的<KeyInfo>元素是相同的。
EncryptedData元素被包含在“http://www.w3.org/2001/04/xmlenc#”命名空間中。它是被加密數(shù)據(jù)的根元素。
EncryptionMethod元素指定加密數(shù)據(jù)的對稱方法。做這件事需要使用一個包含了w3 url的算法屬性 - “http://www.w3.org/2001/04/xmlenc#aes256-cbc”,它指出數(shù)據(jù)是用AES(Rijndael)以256k的密鑰加密的。
KeyInfo元素來自xml數(shù)字簽名,它保存著對稱密鑰的信息,除此之外該元素還能保存更多的信息。
KeyInfo元素下的EncryptedKey元素及其子元素包含著關(guān)于被保存的密鑰的信息。
KeyInfo下的EncryptionMethod元素包含的非對稱加密方法用來加密對稱密鑰。做這件事需要把一個算法屬性設(shè)置給w3 url。例如:“http://www.w3.org/2001/04/xmlenc#rsa-1_5”說明使用了RSA非對稱算法來加密對稱密鑰。
KeyName元素是一個標識符,用來發(fā)現(xiàn)密鑰。稍后在我們編程的時候你將會發(fā)現(xiàn)它的重要性。
CipherData元素和CipherValue元素出現(xiàn)在EncryptedKey元素和EncryptedData元素下,它們包含著密碼數(shù)據(jù)。事實上密碼數(shù)據(jù)保存在CipherValue元素下的。EncryptedKey元素下保存的是被加密的密鑰,EncryptedData元素下的CipherValue保存的是被加密的數(shù)據(jù)。
使用.net加密xml
本文提供了一個簡單的加密、解密xml的應(yīng)用程序,下面我們一起來看一看相關(guān)的代碼。這個示例只有一些基本功能,你可以再額外加一些如選擇節(jié)點之類的功能
首先加載非對稱公開密鑰來加密密鑰
// 創(chuàng)建一個用于加密密鑰的非對稱密鑰
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
// 加載一個公開密鑰
XmlDocument pubKeys = new XmlDocument();
pubKeys.Load(Application.StartupPath + "\\xml.dev.keys.public");
// 使用公開密鑰加密密鑰
rsa.FromXmlString(pubKeys.OuterXml);
接下來加載xml文檔并選擇一個需要加密的節(jié)點。下面的代碼示例了如何使用一個XPath表達式來選擇節(jié)點。如果不選擇節(jié)點,則整個xml文檔都將被加密。
// xml文檔
this.xmlEncDoc = new XmlDocument();
// 給xml文檔加載一些節(jié)點和數(shù)據(jù)(省略)
XmlElement encElement;
// 如果沒有xpath則
if (xpath == string.Empty)
{
encElement = this.xmlEncDoc.DocumentElement;
}
else
{
XmlNamespaceManager xmlns = this.xmlCntrlr.xmlnsManager;
// 通過xpath選擇出需要加密的元素
encElement = this.xmlEncDoc.SelectSingleNode(xpath, xmlns) as XmlElement;
}
使用EncryptedXml類去加密數(shù)據(jù)和密鑰
// 完成加密xml的類
EncryptedXml xmlEnc = new EncryptedXml(this.xmlEncDoc);
// 增加一個“session”密鑰,使用rsa編碼
xmlEnc.AddKeyNameMapping("session", rsa);
// 使用“session”密鑰來加密數(shù)據(jù)
// 這些信息被保存在KeyInfo元素下
EncryptedData encData = xmlEnc.Encrypt(encElement, "session");
用加密后的元素替換初始元素
// 用加密后的元素替換初始元素
EncryptedXml.ReplaceElement(encElement, encData, false);
使用.net解密xml
首先加載私有非對稱密鑰來解密密鑰
// 創(chuàng)建一個用于解密密鑰的非對稱密鑰
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
// 加載私有密鑰
XmlDocument privKeys = new XmlDocument();
privKeys.Load(Application.StartupPath + "\\xml.dev.keys.private");
// 使用私有密鑰來解密密鑰
rsa.FromXmlString(privKeys.OuterXml);
增加一個密鑰名稱并映射到被加密的文檔中
// 增加一個密鑰名稱并映射到被加密的文檔中
EncryptedXml encXml = new EncryptedXml(xmlEncDoc);
encXml.AddKeyNameMapping("session", rsa);
通過指定的密鑰來解密文檔的每一個EncryptedData元素
// 解密所有<EncryptedData>元素
encXml.DecryptDocument();
總結(jié)
xml加密(XML Encryption)是w3c加密xml的標準。加密后的文檔仍然是xml格式。我們使用非對稱算法和對稱算法來加密xml,對稱算法用于加密數(shù)據(jù),非對稱算法用于加密對稱算法中的密鑰,加密后的數(shù)據(jù)被保存在EncryptedData元素下。EncryptedData元素包含著一些列用于描述算法的子元素,同時也包含著密鑰信息。







