以文本方式查看主题

-  中文XML论坛 - 专业的XML技术讨论区  (http://bbs.xml.org.cn/index.asp)
--  『 XML安全 』  (http://bbs.xml.org.cn/list.asp?boardid=27)
----  xml加解密示例源码  (http://bbs.xml.org.cn/dispbbs.asp?boardid=27&rootid=&id=23192)


--  作者:alee_xml
--  发布时间:10/17/2005 2:47:00 PM

--  xml加解密示例源码
原xml文件清单1:
<?xml version="1.0"?>
<PurchaseOrderRequest>
  <Order>
    <Item>
      <Code>Screw001</Code>
      <Description>Screw with half centimeter thread</Description>
    </Item>
    <Quantity>2</Quantity>
  </Order>
  <Payment>
    <CreditCard>
      <Type>MasterCard</Type>
      <Number>1234567891234567</Number>
      <ExpiryDate>20050501</ExpiryDate>
    </CreditCard>
    <PurchaseAmount>
      <Amount>30000</Amount>
      <Currency>INR</Currency>
      <Exponent>-3</Exponent>
    </PurchaseAmount>
  </Payment>
</PurchaseOrderRequest>
清单 2 示范了如何对清单 1 中的部分 XML 进行加密。在这个清单之后,我解释了加密过程中的每一个步骤。
清单 2. XML 加密
//Get the DOM document object for the XML that you
// want to encrypt.
// getDocument method that takes XML file name as input
// and returns DOM document provided in Listing 3 (Step 1)
Document doc = XmlUtil.getDocument(xmlFileName);
String xpath = "/PurchaseOrderRequest/Payment";
// Step 2. Get the shared secret. This key is used to encrypt the
// XML content
Key dataEncryptionKey = getKey();
// Algorithm type used to generate shared secret
// i.e. content encryption key
AlgorithmType dataEncryptionAlgoType =  AlgorithmType.TRIPLEDES;
// Get the key pair. You are interested in the public key
// as that is the one you will use for encrypting the
// XML content
KeyPair keyPair = getKeyPair();
// Step 3. Get the public key of the key pair
Key keyEncryptionKey = keyPair.getPublic();
// Algorithm type used to generate the public
// private key pair
AlgorithmType keyEncryptionAlgoType = AlgorithmType.RSA1_5;
KeyInfo keyInfo = new KeyInfo();
// Step 4
try {
Encryptor enc =
  new Encryptor(
   doc,
   dataEncryptionKey,
   dataEncryptionAlgoType,
   keyEncryptionKey,
   keyEncryptionAlgoType,
   keyInfo);
XPath xpath = new XPath(xPath);
// Step 5
try {
  enc.encryptInPlace(xpath);
} catch (XPathException e1) {
  System.out.println("XPAth is not correct");
  e1.printStackTrace();
}
XmlUtil.XmlOnStdOut(doc);
} catch (Exception e) {
System.out.println("Some exception");
e.printStackTrace();
}
步骤 1:将 XML 转换成 DOM 对象,如清单 3 所示:
清单 3. 根据 XML 创建 DOM 对象
public static Document getDocument(String fileName) {
Document doc = null;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
File f = new File(fileName);
DocumentBuilder builder = null;
try {
builder = factory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
System.out.println("Parse configuration exception");
e.printStackTrace();
}
try {
doc = builder.parse(f);
} catch (Exception e1) {
System.out.println("Some exception");
e1.printStackTrace();
}
return doc;
}
步骤 2:获得共享密钥(shared secret)。您要用这个密钥来加密 XML 内容。本文附带的源代码使用的 XML 加密方法只能识别三重 DES(Triple-DES)加密算法,因此我就用这种算法创建密钥。
步骤 3:参照本系列文章第 1 部分所述,获得公-私密钥对中的公钥;您需要用这个公钥给共享密钥加密。您从第 1 部分中可以看到,这个公钥是基于 RSA 算法生成的。
步骤 4:利用一个数据加密密钥、一个密钥加密密钥、与这两个密钥相关联的算法、以及将来包含在输出信息中的密钥信息,根据它们来创建一个 Encryptor 对象。创建 Encryptor 对象时指定的算法必须与密钥相符。 Encryptor 是加密过程中的主要对象。它的类在 com.verisign.xmlenc 这个包中。Encryptor 根据 W3C XML Encryption 规范进行加密。您可以指定想要使用哪种加密类型,是 Element 还是 Content。在清单 2 中,加密类型是 Element,这也是默认的类型。 Encryptor 要理解 XPath 表达式,这样才能识别出需要加密的 XML 元素。
步骤 5:最后一步,调用 Encryptor 对象的 encrypt 或者 encryptInPlace 方法,并将 XPath 作为输入参数传入。XPath 定义了 XML 内部需要进行加密的元素。这个元素的所有子元素,以及 XPath 所指向的属性也都要进行加密。在本例中,您加密的是 XML 中的 /PurchaseOrderRequest/Payment 元素。encrypt 和 encryptInPlace 两个方法都用传入的共享密钥对 XPath 指定的 XML 元素进行加密,两种方法也都用公钥对共享密钥进行加密,并将加密结果嵌入到 XML 加密后的内容之中。这两种方法的唯一区别在于,encrypt 返回一个全新的 DOM 文档,其中包含加密后的数据,而 encryptInPlace 方法对原有的文档本身进行修改,使其中包含加密后的数据。加密过的 XML 如清单 4 所示。
清单 4. 加密后的 XML
<?xml version="1.0" encoding="UTF-8"?>
  <PurchaseOrderRequest>
    <Order>
      <Item>
        <Code>Screw001</Code>
          <Description>Screw with half centimeter thread</Description>
      </Item>
      <Quantity>2</Quantity>
    </Order>
    <xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
    xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
      <xenc:EncryptionMethod Algorithm=
      "http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
        <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
          <xenc:EncryptedKey>
            <xenc:EncryptionMethod Algorithm=
            "http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
              <xenc:CipherData>
              <xenc:Ciphervalue>
       F1aIpdp3axm8nFofx/xX62VlsxildddHcxaevd7sbr+lv/fzZ7e8ovmKGQopAjclxPTybpkW
       YG8GVcOIbD4UGR24CNxeB7eZCws5/RKBTqKp+76FkVxf+G+EqgMmueRqoaF4oYOrTKquWLnR
       kiSOFmplRaJ8G7bR2j0eTFdiFRk=
              </xenc:Ciphervalue>
            </xenc:CipherData>
          </xenc:EncryptedKey>
        </ds:KeyInfo>
        <xenc:CipherData>
          <xenc:Ciphervalue>
       KMkufRUY7rs0i+4jX6VhviiUIbYWay1KbwhTQxH9SaqJ6HA+Qc2Ce7TVZUQuH0GGD4xTR8hB
       hOls+hgHA16EfmmxLd3E+YqO4sXQ+GkX9O9EcO4ULha/q1KmP2yNGNy/tavdj9a7JuZnnNGV
       /M4gxdt5fCJXT0A9bw9HwKR/Pc81rZYWa7fOrmvDvC7Q+//OCzkqcAaCmAHEySWbv2vK3T+a
       GlQOI2Wooxa9hm7Dx70BuLI8ihhSAV3moK+JAPdn1vdCpoFKdzzq2HSh/yOisYZvQOh+jIks
       MW8oUzWnVUe/DFztPtvvDKbPE/xoAasixlbDLa42gFFe9uzEeIG89XBMSkZtTio0zn9xppSf
       Dc0WFMy+UoLnCA==
          </xenc:Ciphervalue>
        </xenc:CipherData>
      </xenc:EncryptedData>
  </PurchaseOrderRequest>
清单 4 是部分加密的 XML 代码片断。只有当接收者具有与加密数据时使用的公钥相对应的私钥时,才能阅读这部分被加密的数据。
最后说一下,清单 5 中的代码可以对加密过的 XML 进行解密。
清单 5. XML 解密
// Get the DOM document object for the XML that you
// want to decrypt (The one shown in Listing 4)
// The getDocument method that takes an XML file name as input
// and returns a DOM document is provided in Listing 3 (Step 1)
Document doc = XmlUtil.getDocument(encryptedXmlFileName);
// Step 2. Get the private key of the pair whose public key was
// used to encrypt the XML
Key privateKey = keyPair.getPrivate();
// Specifying the XPath at which encrypted data is lying
// in the XML
// Step 3. Specify XPath expression
String xpath = "//xenc:EncryptedData";
// Specify the namespace that relates to the XPath
// expression
String[] ns =
{ "xenc", "http://www.w3.org/2001/04/xmlenc#" };
// Create the XPath helper with the XPath expression and a map
// of namespaces that relate to the XPath expression
XPath xpath = new XPath(xPath, ns);
// Step 4. Create the Decryptor object with decryption key and
// location of the encrypted data to be decrypted
Decryptor decrypt = null;
try {
decrypt = new Decryptor(doc, privateKey, xpath);
} catch (Exception e) {
System.out.println("Some exception");
e.printStackTrace();
}
// Step 5. Method decryptInPlace is called to decrypt the
// encrypted contents of the XML
try {
decrypt.decryptInPlace();
} catch (Exception e1) {
System.out.println("Some exception");
e1.printStackTrace();
}
清单 5 示范了当您有正确的私钥时,如何对加密的数据进行解密。下面的步骤解释了解密的过程。
步骤 1:将加密过的 XML 转换成 DOM 对象,这一步与加密过程相同。
步骤 2:根据用于加密 XML 的公钥,获取密钥对中对应的私钥。请注意,解密过程使用的是加密 XML 时使用的公钥所对应的私钥。.
步骤 3:创建 XPath 以及相关名称空间,用于表示加密过的数据在加密过的 XML 中的位置。在本例中,XPath 的值是 //xenc:EncryptedData。加密过的数据总是在加密过的 XML 中的 xenc:EncryptedData 元素下面,而与哪个元素被加密无关。XPath 为 //xenc:EncryptedData 则表示,从 XML 中可能出现加密数据的任何地方查找 EncryptedData 元素。
步骤 4:用解密密钥和需要解密的加密数据所在的位置创建 Decryptor 对象。Decryptor 是解密过程中的主要对象。它的类在 com.verisign.xmlenc 包中。 Decryptor 根据 W3C XML Encryption 规范进行解密(参阅参考资料)。解密过程支持 Element 和 Content 两种类型。为了识别需要解密的 XML 元素, Decryptor 要能理解 XPath 表达式。
步骤 5:解密过程的最后一个步骤是在 Decryptor 对象中调用 decryptInPlace 或者 decrypt 方法。这两种方法调用都使用提供的私钥来解密共享密钥(共享密钥是已加密消息中的一部分),然后用这个共享密钥来解密消息的其余部分。两种调用之间的唯一区别在于, decrypt 对 XML 解密之后创建一个新的 DOM 对象,而 decryptInPlace 在作为输入接收的同一 DOM 对象中解密消息。

--  作者:mfsll
--  发布时间:11/25/2005 4:57:00 PM

--  
支持!
--  作者:lai_gb
--  发布时间:12/8/2005 4:37:00 PM

--  
一个字,好好好!!
--  作者:hiohio
--  发布时间:12/13/2005 9:21:00 PM

--  
很好
--  作者:szxyz
--  发布时间:2/24/2006 9:07:00 AM

--  
这里会用到哪些包?
--  作者:yizhyi
--  发布时间:2/28/2006 3:43:00 PM

--  
支持!
大力的支持!
--  作者:bluehat
--  发布时间:4/18/2006 5:07:00 PM

--  
真的非常感谢
我的毕业设计正是做xml加密
谢谢了
--  作者:echaogui
--  发布时间:5/23/2006 8:48:00 AM

--  
有成形的软件没有 给我联系
麻烦发一份到echaogui@126.com
--  作者:grxu
--  发布时间:6/22/2006 9:13:00 PM

--  
用到的包有 import javax.crypto.*;
import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import java.security.*;
import java.nio.*;
--  作者:zzbzw
--  发布时间:7/3/2006 8:39:00 PM

--  
好,顶
--  作者:suetlung2
--  发布时间:11/16/2006 2:35:00 PM

--  
哦?
这个东西倒很有点意思哦
--  作者:billy2000
--  发布时间:11/20/2006 10:45:00 PM

--  
支持
--  作者:caral
--  发布时间:2/2/2007 12:33:00 PM

--  
谢谢分享
--  作者:DJ0702
--  发布时间:4/5/2007 4:30:00 PM

--  
对论文很有帮助,谢谢啊
--  作者:laipigongzi
--  发布时间:4/9/2007 11:42:00 AM

--  
我也支持.
--  作者:laipigongzi
--  发布时间:4/9/2007 11:45:00 AM

--  
谢谢,顶!
--  作者:asp.design
--  发布时间:5/12/2007 10:18:00 AM

--  
这个加密码有什么用点在哪?XML不是主要用数据据转换的吗?那又怎么解密码.
--  作者:龙藤
--  发布时间:6/24/2007 8:06:00 PM

--  
先谢了
--  作者:super211
--  发布时间:6/25/2007 9:06:00 AM

--  
编译好像通不过,缺少方法什么的,请问是不是因为Java的JDK的版本问题?

请问有谁编译通过了吗?


--  作者:haldir
--  发布时间:11/5/2007 2:49:00 PM

--  
谢谢共享。
--  作者:liwei9527
--  发布时间:6/3/2008 11:45:00 AM

--  
thank you for shareing  your programme!
--  作者:lqg629
--  发布时间:8/19/2008 5:11:00 PM

--  
我是新手,也给我发一个份。
lqg629@gmail.com
谢谢
--  作者:jxhlskyy
--  发布时间:9/24/2008 10:18:00 AM

--  
我新手,不太懂
java中要添加的包,classpath设置和源码发给我一份吧,谢谢了
我的jxhlskyy@163.com
--  作者:myendless
--  发布时间:1/13/2009 10:26:00 AM

--  
好东西!!
--  作者:myendless
--  发布时间:1/13/2009 10:27:00 AM

--  
继续发挥
W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
171.875ms