| 
				 针对清单3-1的XML病历文档,病人的个人信息是不希望其他人看见的,所以对这些信息进行加密,加密后用<EncryptedData>元素替换<PersonalInfo>元素得到加密后的XML文档,清单4-1给出加密后的XML片段。 
<PersonalInfo> 
<EncrytpedData Type=http://www.w3.org/2001/04/xmlenc#Content xmlns="http://www.w3.org/2001/04/xmlenc#"> 
<EncryptionMethod Algorithm=http://www.w3.org/2001/04/xmlenc#tripledes-cbc xmlns="" />  
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmlsig#"> 
<EncryptedKey xmlns=""> 
<ds:KeyInfo> 
<ds:KeyName>RSAKey</ds:KeyName>  
</ds:KeyInfo> 
<CipherData> 
<CipherValue> 
<EncryptedSymmetricKey>Nb4A43dH6…</EncryptedSymmetricKey> 
<EncryptedSymmetricIV>RQsK1jlEBtV…</EncryptedSymmetricIV>  
</CipherValue> 
</CipherData> 
</EncryptedKey> 
</ds:KeyInfo> 
<CipherData xmlns=""> 
<CipherValue>Hfrd1Pd0yVSGo6k…</CipherValue>  
</CipherData> 
</EncrytpedData> 
</PersonalInfo> 
清单4-1<PersonalInfo>加密后的文档片段 
在清单中<EncryptionMethod>元素指定了加密的算法,< KeyInfo >元素指定的是密钥信息,其中< KeyName >元素是指RSA非对称密钥的名称,第一个<CipherData>下的<. CipherValue >元素指使用RSA的公钥加密3DES密钥后的密文。第二个<CipherData>下的<. CipherValue >元素指使用3DES算法加密原文档<PersonalInfo>元素后的密文。 
  
五、NET环境下的程序实现 
自从XML数字签名的规范发布以来,许多机构都对其进行深入研究并提供了解决方案,同时XML加密的规范也已经成型。但大多数签名与加密是基于Java平台的,包括IBM和NEC的签名库。为了打破Java“一统天下”的局面,本文采用C#语言在Visual Studio.Net 2003环境下实现XML电子病历的加密与签名。 
微软公司在其.NET 2003平台中改进了XML的内核结构,对XML实现了完全的内部支持,可以使用其类库来编程。 
1.XML Schema 检验的实现 
在.NET Framework中,与XML Schema相关的类在 System.Xml.Schema下。 
XmlTextReader reader = new XmlTextReader(flieName); 
XmlValidatingReader objXValRead = new  
XmlValidatingReader(reader); 
objXValRead.ValidationType = ValidationType.Schema; 
while(objXValRead.Read()){} 
return true; 
如果While语句为真,说明XML文档的结构符合Shema的描述。 
2.XML加密的实现 
在.NET Framework 中,与XML 加密相关的类集中在和System.Security.Cryptography 和System.xml命名空间下,所以程序必须包含这两个命名空间。 
步骤1: 生成RSA密钥对 
利用.NET Framework下的Cryptography.RSA类来生成RSA非对称密钥,并分别将私钥与公钥保存为XML文档: 
RSA Key = RSA.Create(); 
strPrivateKeyXML = Key.ToXmlString(true); 
srrPublicKeyXML = Key.ToXmlString(false); 
XmlDocument privateKeyXML,,publicKeyXML = new XmlDocument(); 
privateKeyXML.LoadXml(strPrivateKeyXML); 
publicKeyXML.LoadXml(srrPublicKeyXML); 
步骤2 : 通过Xpath语句判断加密次数,逐个加密: 
nodes = doc.SelectNodes(strXpath); 
nodeCount = nodes.Count; 
for(int i=0;i<nodeCount;i++) 
    { 
     XmlNode currentNode = nodes.Item(i); 
// EncrypXMLString方法是加密的具体实现 
     XmlElement xmlEncryptElement = 
EncrypXMLString(currentNode.InnerXml,strKeyName); 
    } 
通过Xpath语句可能找到多个节点,下面的步骤介绍EncrypXMLString方法的内容。 
步骤3 : 使用3DES算法对文档进行加密: 
SymmetricAlgorithm CSP = new  
TripleDESCryptoServiceProvider(); 
MemoryStream ms = new MemoryStream(); 
byte [] bty = Encoding.UTF8.GetBytes(strXmlString); 
CryptoStream cs = new  
CryptoStream(ms,CSP.CreateEncryptor(CSP.Key,CSP.IV),CryptoStreamMode.Write); 
cs.Write(bty,0,bty.Length); 
将XML文档片段读入字节数组,然后用3DES加密算法进行加密。 
步骤4 : 使用RSA算法的公钥加密KEY与IV: 
RSACryptoServiceProvider rsa = new  
RSACryptoServiceProvider(); 
//从密钥信息获取RSA的密钥信息 
rsa.FromXmlString(GetRSAPublicKey(strKeyName)); 
string strEncryptedSymmetricKey =  
Convert.ToBase64String(rsa.Encrypt(CSP.Key,false)); 
string strEncryptedSymmetricIV =  
Convert.ToBase64String(rsa.Encrypt(CSP.IV,false)); 
对3DES算法用到的KEY与IV用RSA算法加密。 
步骤5 : 构建加密节点。 
组装<EncryptedData><EncryptionMethod/><ds:KetInfo>等节点,程序较长在此省略。 
3.XML解密的实现 
解密与加密一样,也需要通过Xpath语句判断加密点的个数,然后使用循环语句逐个解密。 
步骤1 : 使用RSA算法的私钥解密KEY与IV。 
首先建立RSA和3DES的对象,并定位node元素: 
rsa.FromXmlString(GetRSAPrivateKey(node.InnerText)); 
node=root.SelectSingleNode("descendant::EncryptedKey/CipherData/CipherValue/EncryptedSymmetricKey"); 
CSP.Key= rsa.Decrypt(Convert.FromBase64String(node.InnerText),true); 
node=root.SelectSingleNode("descendant::EncryptedKey/CipherData/CipherValue/EncryptedSymmetricIV"); 
CSP.IV= rsa.Decrypt(Convert.FromBase64String(node.InnerText), true); 
步骤2 : 使用得到的KEY与IV解密XML文档: 
node=root.SelectNodes("CipherData/CipherValue").Item(0); 
byte [] byt = Convert.FromBase64String(node.InnerText); 
MemoryStream ms=new MemoryStream(byt); 
CryptoStream cs=new CryptoStream  
(ms,CSP.CreateDecryptor(CSP.Key,CSP.IV),CryptoStreamMode.Read); 
byte[] initialText = new Byte[byt.Length]; 
//解密文本将其保存为二进制数据 
cs.Read(initialText,0,initialText.Length); 
  
六、结语 
本文首先根据电子病历结构化的存储结构,提出病历的XML Schema描述,然后探讨了XML电子病历加密与数字签名的方案,并详细说明了其实现步骤。XML作为下一代Web开发的主要技术,在信息交换与存储方面有明显的优势,将其运用到电子病历系统中,可以有效的加强病历的安全性。随着医院信息化的普及,电子病历的加密与签名将十分重要。不过要得到广大患者用户的认可,除技术上的防范措施外,还要在管理上采取严格的控制方法,从而进一步发展以电子病历为核心的医院信息系统。 
  
参考文献 
  
[1]W3C. XML Schema[EB/OL]http://www.w3.org/XML/Schema. 
[2]W3C Recommendation.XML Path Language(XPath) [EB/OL]Vl.0.http://www.w3.org/TR/xpath,2003. 
[3] Microsoft.net framework[R]. http: //msdn.microsoft.com/netframework/security/,2004. 
[4] BoyerJ.Canonical XML Version 1.0[S].RFC 3076,March 2001. 
[5]马永恒, 熊前兴, 杨金娥. W3C XML Schema模式的设计方法研究[J]. 计算机应用研究,2006,0. 
[6]肖 林. 浅谈电子病历[J]. 档案管理, 2000,04(1). 
[7]严维良,于津. XML在电子病历中的应用[J]. 汕头大学学报,2003,15(3). 
[8]李浩,孙统风,孟现飞等.基于面向对象思想构建XML Schema[J].微机发展,2003,13(6):59-64. 			
				 |