asp.net下XML的加密和解密實(shí)現(xiàn)方法
介紹
我們有3個(gè)加密xml的方法
1、僅僅使用對(duì)稱加密的方法加密xml
這種加密方法只使用一個(gè)密鑰,也就是說無論是加密xml還是解密xml都使用一個(gè)相同的密鑰。因?yàn)檫@個(gè)密鑰不會(huì)在被加密的xml中保存,所以我們需要在加密和解密的過程中加載這個(gè)密鑰并保護(hù)它不被竊取。
2、使用對(duì)稱加密和非對(duì)稱加密相結(jié)合的方法來加密xml
這種方法需要一個(gè)用于加密數(shù)據(jù)的對(duì)稱密鑰和一個(gè)用于保護(hù)這個(gè)對(duì)稱密鑰的非對(duì)稱密鑰。被加密的對(duì)稱密鑰和被加密的數(shù)據(jù)一起保存在xml文檔中。當(dāng)用私有非對(duì)稱密鑰解密密鑰的時(shí)候要用公開非對(duì)稱密鑰對(duì)密鑰進(jìn)行加密。
本文就將使用這種方法。想學(xué)到其他更多的方法請(qǐng)參看MSDN等到更多的信息。
(譯者注:非對(duì)稱加密算法需要兩個(gè)密鑰:公開密鑰(publickey)和私有密鑰(privatekey)。公開密鑰與私有密鑰是一對(duì),如果用公開密鑰對(duì)數(shù)據(jù)進(jìn)行加密,只有用對(duì)應(yīng)的私有密鑰才能解密;如果用私有密鑰對(duì)數(shù)據(jù)進(jìn)行加密,那么只有用對(duì)應(yīng)的公開密鑰才能解密。因?yàn)榧用芎徒饷苁褂玫氖莾蓚€(gè)不同的密鑰,所以這種算法叫作非對(duì)稱加密算法。)
3、使用X.509加密xml,這種方法是用X.509作為非對(duì)稱密鑰,它由諸如VeriSign之類的第三方提供。
方法
不管xml加密是如何完成的,保存加密數(shù)據(jù)總是用兩種方法之一。
1、加密后所有的元素都被命名為<EncryptedData>
2、加密后只有數(shù)據(jù)被替換,而元素名稱仍然是可讀的,不會(huì)發(fā)生變化。
這種微妙的變化是非常重要的。例如:
如果你的xml文檔中包括被稱為<employee>的根元素,該根元素有一個(gè)下存儲(chǔ)了一段詳細(xì)信息的被稱做<WrittenWarning>的子元素。如果你發(fā)送這個(gè)xml,并且想<WrittenWarning>這個(gè)元素被保護(hù)起來,那么使用第1中方法的話<WrittenWarning>將被替換為<EncryptedData>,你不會(huì)從加密后的文檔中獲取到任何可讀的信息。
如果使用第2種方法,那么<WrittenWarning>元素仍然被保留,只用數(shù)據(jù)會(huì)被加密。任何得到這個(gè)文檔的人雖然不能知道該元素下的詳細(xì)信息,但仍然知道有一些事情發(fā)生在這個(gè)雇員身上。另外,<WrittenWarning>元素的所有屬性也不會(huì)被加密。
所以,如果沒有特殊需求,我們一般都用第1種方法。在.net 2.0中你可以通過修改一個(gè)Boolean值的屬性,便可以非常簡(jiǎn)單的選擇使用哪種方法。
xml加密的例子
下面這個(gè)xml加密的例子使用的是非對(duì)稱加密法,把xml文檔的author元素下的內(nèi)容加密并把a(bǔ)uthor元素用<EncryptedData>給替換掉。
XML文檔:
| <?xml version="1.0" standalone="no"?> <article> <articleinfo> <title>XPath Queries on XmlDocument objects in .NET 1.1</title> <abstract> <para>This article covers the basics.</para> </abstract> <author> <honorific>Mr.</honorific> <firstname>George</firstname> <surname>James</surname> <email>gjames@doman.com</email> </author> </articleinfo> </article> |
XPath表達(dá)式為/article/articleinfo/author
被加密后的xml文檔:
| <?xml version="1.0" standalone="no"?> <article> <articleinfo> <title>XPath Queries on XmlDocument objects in .NET 1.1</title> <abstract> <para>This article covers the basics.</para> <para>This article does not cover.</para> </abstract> <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#aes256-cbc" /> <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#"> <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" /> <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> <KeyName>session</KeyName> </KeyInfo> <CipherData> <CipherValue>r4f7SI1aZKSvibb…</CipherValue> </CipherData> </EncryptedKey> </KeyInfo> <CipherData> <CipherValue>sGNhKqcSovipJdOFCFKYEEMRFd…</CipherValue> </CipherData> </EncryptedData> </articleinfo> </article> |
author元素及其子元素都將被<EncryptedData>給替換掉,另外還包括其他一些元素,如加密算法,密鑰等。
<EncryptedData>元素
仔細(xì)看看<EncryptedData>元素的樹形結(jié)構(gòu),你會(huì)發(fā)現(xiàn)<EncryptedData>元素下分解出了很多子元素。其中<KeyInfo>元素與xml數(shù)字簽名中的<KeyInfo>元素是相同的。

EncryptedData元素被包含在“http://www.w3.org/2001/04/xmlenc#”命名空間中。它是被加密數(shù)據(jù)的根元素。
EncryptionMethod元素指定加密數(shù)據(jù)的對(duì)稱方法。做這件事需要使用一個(gè)包含了w3 url的算法屬性 - “http://www.w3.org/2001/04/xmlenc#aes256-cbc”,它指出數(shù)據(jù)是用AES(Rijndael)以256k的密鑰加密的。
KeyInfo元素來自xml數(shù)字簽名,它保存著對(duì)稱密鑰的信息,除此之外該元素還能保存更多的信息。
KeyInfo元素下的EncryptedKey元素及其子元素包含著關(guān)于被保存的密鑰的信息。
KeyInfo下的EncryptionMethod元素包含的非對(duì)稱加密方法用來加密對(duì)稱密鑰。做這件事需要把一個(gè)算法屬性設(shè)置給w3 url。例如:“http://www.w3.org/2001/04/xmlenc#rsa-1_5”說明使用了RSA非對(duì)稱算法來加密對(duì)稱密鑰。
KeyName元素是一個(gè)標(biāo)識(shí)符,用來發(fā)現(xiàn)密鑰。稍后在我們編程的時(shí)候你將會(huì)發(fā)現(xiàn)它的重要性。
CipherData元素和CipherValue元素出現(xiàn)在EncryptedKey元素和EncryptedData元素下,它們包含著密碼數(shù)據(jù)。事實(shí)上密碼數(shù)據(jù)保存在CipherValue元素下的。EncryptedKey元素下保存的是被加密的密鑰,EncryptedData元素下的CipherValue保存的是被加密的數(shù)據(jù)。
非對(duì)稱xml加密步驟
xml加密的過程可以概括為以下五步:
1、選擇xml文檔中的一個(gè)元素(選擇根元素的話將加密整個(gè)文檔)
2、使用一個(gè)對(duì)稱密鑰加密元素
3、使用非對(duì)稱加密來加密上面那個(gè)對(duì)稱密鑰(使用公開密鑰)
4、創(chuàng)建一個(gè)EncryptedData元素,該元素下將包含被加密的數(shù)據(jù)和被加密的密鑰
5、用加密后的元素替換掉初始元素。
這些步驟的大部分都可以使用.net 2.0中的類自動(dòng)完成。
非對(duì)稱xml解密步驟
xml解密的過程可以概括為以下四步:
1、在xml文檔中選擇一個(gè)EncryptedData元素
2、使用一個(gè)非對(duì)稱密鑰來解密密鑰(使用私有密鑰)
3、使用未加密的密鑰來解密數(shù)據(jù)
4、把EncryptedData元素替換成未加密的元素
這些步驟的大部分都可以使用.net 2.0中的類自動(dòng)完成。
命名空間
完成xml的加密,我們需要引入三個(gè)命名空間
System.Xml - 包含操作xml的類
System.Security.Cryptography - 包含生成加密密鑰的類
System.Security.Cryptography.Xml - 包含完成加密任務(wù)的類
使用.net加密xml
本文提供了一個(gè)簡(jiǎn)單的加密、解密xml的應(yīng)用程序,下面我們一起來看一看相關(guān)的代碼。這個(gè)示例只有一些基本功能,你可以再額外加一些如選擇節(jié)點(diǎn)之類的功能
首先加載非對(duì)稱公開密鑰來加密密鑰
| // 創(chuàng)建一個(gè)用于加密密鑰的非對(duì)稱密鑰 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); // 加載一個(gè)公開密鑰 XmlDocument pubKeys = new XmlDocument(); pubKeys.Load(Application.StartupPath + "\\xml.dev.keys.public"); // 使用公開密鑰加密密鑰 rsa.FromXmlString(pubKeys.OuterXml); |
接下來加載xml文檔并選擇一個(gè)需要加密的節(jié)點(diǎn)。下面的代碼示例了如何使用一個(gè)XPath表達(dá)式來選擇節(jié)點(diǎn)。如果不選擇節(jié)點(diǎn),則整個(gè)xml文檔都將被加密。
| // xml文檔 this.xmlEncDoc = new XmlDocument(); // 給xml文檔加載一些節(jié)點(diǎn)和數(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); // 增加一個(gè)“session”密鑰,使用rsa編碼 xmlEnc.AddKeyNameMapping("session", rsa); // 使用“session”密鑰來加密數(shù)據(jù) // 這些信息被保存在KeyInfo元素下 EncryptedData encData = xmlEnc.Encrypt(encElement, "session"); |
用加密后的元素替換初始元素
| // 用加密后的元素替換初始元素 EncryptedXml.ReplaceElement(encElement, encData, false); |
使用.net解密xml
首先加載私有非對(duì)稱密鑰來解密密鑰
| // 創(chuàng)建一個(gè)用于解密密鑰的非對(duì)稱密鑰 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); // 加載私有密鑰 XmlDocument privKeys = new XmlDocument(); privKeys.Load(Application.StartupPath + "\\xml.dev.keys.private"); // 使用私有密鑰來解密密鑰 rsa.FromXmlString(privKeys.OuterXml); 增加一個(gè)密鑰名稱并映射到被加密的文檔中 // 增加一個(gè)密鑰名稱并映射到被加密的文檔中 EncryptedXml encXml = new EncryptedXml(xmlEncDoc); encXml.AddKeyNameMapping("session", rsa); 通過指定的密鑰來解密文檔的每一個(gè)EncryptedData元素 // 解密所有<EncryptedData>元素 encXml.DecryptDocument(); |
總結(jié)
xml加密(XML Encryption)是w3c加密xml的標(biāo)準(zhǔn)。加密后的文檔仍然是xml格式。我們使用非對(duì)稱和對(duì)稱算法來加密xml,對(duì)稱算法用于加密數(shù)據(jù),非對(duì)稱算法用于加密對(duì)稱算法中的密鑰,加密后的數(shù)據(jù)被保存在EncryptedData元素下。EncryptedData元素包含著一些列用于描述算法的子元素,同時(shí)也包含著密鑰信息。
相關(guān)文章
asp.net(c#)獲取內(nèi)容第一張圖片地址的函數(shù)
C#獲取文章類第一張圖片的地址的函數(shù)(留著以后用),先說一下思路2009-11-11
Visual Studio 2017創(chuàng)建.net standard類庫(kù)編譯出錯(cuò)原因及解決方法
這篇文章主要為大家詳細(xì)介紹了Visual Studio 2017創(chuàng)建.net standard類庫(kù)編譯出錯(cuò)原因及解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04
Asp.Net Core使用SignalR進(jìn)行服務(wù)間調(diào)用方法示例
這篇文章主要介紹了Asp.Net Core使用SignalR進(jìn)行服務(wù)間調(diào)用方法示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-12-12
asp.net中實(shí)體類對(duì)象賦值到表單的實(shí)現(xiàn)代碼
昨天在網(wǎng)上看到了一個(gè)利用反射表單賦值到實(shí)體類對(duì)象的一個(gè)方法,自己就在加了個(gè)方法,從實(shí)體對(duì)象到表單,覺的很不錯(cuò)非常省事,所以把他寫成了一個(gè)類,供以后使用2010-11-11
使用SNK密鑰文件保護(hù)你的DLL和代碼不被反編譯教程
這篇文章主要介紹了使用SNK密鑰文件保護(hù)你的DLL和代碼不被反編譯教程, SNK,作為程序后綴的時(shí)候,是.net中的強(qiáng)密匙加密文件,需要的朋友可以參考下2014-09-09
微信公眾平臺(tái)開發(fā)教程(八)Session處理問題
本篇文章主要介紹了微信公眾平臺(tái)開發(fā)教程(八)Session處理 ,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。2016-12-12
關(guān)于前臺(tái)調(diào)用后臺(tái)事件__doPostBack函數(shù)
關(guān)于前臺(tái)調(diào)用后臺(tái)事件__doPostBack函數(shù)...2007-04-04

