package test.xml.signature;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.EncodedKeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Collections;
import java.util.List; import javax.xml.crypto.dom.DOMStructure;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.crypto.dsig.SignedInfo;
import javax.xml.crypto.dsig.Transform;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.KeyValue;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList; public class SignatureXML { public void saveKey(PublicKey publicKey, PrivateKey privateKey) throws Exception{
X509EncodedKeySpec ksp = new X509EncodedKeySpec(publicKey.getEncoded());
FileOutputStream fos = new FileOutputStream("C:\\public.key");
fos.write(ksp.getEncoded());
fos.close(); PKCS8EncodedKeySpec pks = new PKCS8EncodedKeySpec(privateKey.getEncoded());
fos = new FileOutputStream("C:\\private.key");
fos.write(pks.getEncoded());
fos.close();
  }   public Key LoadKeyFromFile(boolean ispk, String keyFile) {
Key key = null;
FileInputStream is = null;
try {
is = new FileInputStream(keyFile);
byte[] buf = new byte[is.available()];
KeyFactory keyFactory = KeyFactory.getInstance("DSA");
is.read(buf);
EncodedKeySpec keySpec;
if (ispk) {
keySpec = new PKCS8EncodedKeySpec(buf);
} else {
keySpec = new X509EncodedKeySpec(buf);
}
key = (!ispk ? (Key) keyFactory.generatePublic(keySpec) : (Key) keyFactory.generatePrivate(keySpec));
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException iex) {
iex.printStackTrace();
}
}
return key;
} public void SignatureXMLDocument(String docPath) throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = dbf.newDocumentBuilder().parse(new FileInputStream(docPath));
this.SignatureXMLDocument(doc);
} public void SignatureXMLDocument(Document doc) throws Exception { XMLSignatureFactory fac = XMLSignatureFactory.getInstance();
/*创建 <Reference> 元素,引用整个 XML 文档:
*创建 Reference 的时候将 URI 参数指定为 "" 表示对整个 XML 文档进行引用;
*摘要算法指定为 SHA1;这里将转换方式指定为 ENVELOPED ,
*这样在对整个文档进行引用并生成摘要值的时候,<Signature> 元素不会被计算在内。*/
Transform envelopedTransform = fac.newTransform(Transform.ENVELOPED,(TransformParameterSpec) null);
DigestMethod sha1DigMethod = fac.newDigestMethod(DigestMethod.SHA1, null);
Reference refToRootDoc = fac.newReference("", sha1DigMethod,Collections.singletonList(envelopedTransform), null, null); /*创建 <SignedInfo> 元素
*因为最终的数字签名是针对 <SignedInfo> 元素而生成的,所以需要指定该 XML 元素的规范化方法,
* 以确定最终被处理的数据。这里指定为 INCLUSIVE_WITH_COMMENTS ,
* 表示在规范化 XML 内容的时候会将 XML 注释也包含在内。
* 至此,待签名的内容(<SignedInfo> 元素)已指定好,再只需要签名所使用的密钥就可以创建数字签名了。*/
CanonicalizationMethod c14nWithCommentMethod =
fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS,(C14NMethodParameterSpec) null);
SignatureMethod dsa_sha1SigMethod = fac.newSignatureMethod(SignatureMethod.DSA_SHA1, null);
SignedInfo signedInfo = fac.newSignedInfo(c14nWithCommentMethod,dsa_sha1SigMethod,Collections.singletonList(refToRootDoc)); /*XML 数字签名规范规定了多种在 <KeyInfo> 中指定验证密钥的方式,比如 <KeyName>,<KeyValue>,<X509Data>,<PGPData> 等等。
* 这里使用 XML 数字签名规范规定必须实现的 <DSAKeyValue> 来指定验证签名所需的公共密钥。
* 在程序中使用 java.security 包生成 DSA 密钥对。*/
//创建密钥对
KeyPairGenerator kpGen = KeyPairGenerator.getInstance("DSA");
kpGen.initialize(512);
KeyPair keyPair = kpGen.generateKeyPair(); PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate(); this.saveKey(publicKey, privateKey); //以公钥为参数创建 <KeyValue> 元素
KeyInfoFactory keyInfoFac = fac.getKeyInfoFactory();
KeyValue keyValue = keyInfoFac.newKeyValue(publicKey);
//根据创建好的 <KeyValue> 元素创建 <KeyInfo> 元素:
KeyInfo keyInfo = keyInfoFac.newKeyInfo(Collections.singletonList(keyValue));
/*这里创建的密钥对,其中的公钥已经用于创建 <KeyInfo> 元素并存放在其中,供签名验证使用,而其中的私钥则会在下一步被用于生成签名。*/ //创建 <Signature> 元素
/*前面已经创建好 <SignedInfo> 和 <KeyInfo> 元素,为了生成最终的数字签名,
* 需要根据这两个元素先创建 <Signature> 元素,然后进行签名,
* 创建出 <SignatureValue> 元素。*/
XMLSignature signature = fac.newXMLSignature(signedInfo, keyInfo); /*XMLSignature 类中的 sign 方法用于对文档进行签名,在调用 sign 方法之前,
* 还需要创建 DOMSignContext 对象,为方法调用提供上下文信息,
* 包括签名所使用的私钥和最后生成的 <Signature> 元素所在的目标父元素:*/ DOMSignContext dsc = new DOMSignContext(privateKey, doc.getDocumentElement()); //生成签名
/*sign 方法会生成签名值,并作为元素值创建 <SignatureValue> 元素,然后将整个 <Signature> 元素加入为待签名文档根元素的直接子元素。*/
signature.sign(dsc); TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
DOMSource source=new DOMSource(doc);
transformer.transform(source, new StreamResult(System.out));
StreamResult result = new StreamResult(new File("C:\\old.xml"));
transformer.transform(source,result); } private void validate(String signedFile) throws Exception {
//Parse the signed XML document to unmarshal <Signature> object.
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = dbf.newDocumentBuilder().parse(new FileInputStream(signedFile));
this.validate(doc);
} private void validate(Document doc) throws Exception { // Search the Signature element
NodeList nl = doc.getElementsByTagNameNS(XMLSignature.XMLNS,"Signature");
if (nl.getLength() == 0) {
throw new Exception("Cannot find Signature element");
} Node signatureNode = nl.item(0); XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
XMLSignature signature = fac.unmarshalXMLSignature(new DOMStructure(signatureNode)); // Get the public key for signature validation
KeyValue keyValue = (KeyValue) signature.getKeyInfo().getContent().get(0);
PublicKey pubKey = keyValue.getPublicKey(); // Create ValidateContext
DOMValidateContext valCtx = new DOMValidateContext(pubKey,signatureNode); // Validate the XMLSignature
boolean coreValidity = signature.validate(valCtx); // Check core validation status
if (coreValidity == false) {
System.err.println("Core validation failed");
// Check the signature validation status
boolean sv = signature.getSignatureValue().validate(valCtx);
System.out.println("Signature validation status: " + sv);
// check the validation status of each Reference
List refs = signature.getSignedInfo().getReferences();
for (int i = 0; i < refs.size(); i++) {
Reference ref = (Reference) refs.get(i);
boolean refValid = ref.validate(valCtx);
System.out.println("Reference[" + i + "] validity status: " + refValid);
}
} else {
System.out.println("Signature passed core validation");
}
} public static void main(String[] args) {
SignatureXML signatureXML=new SignatureXML();
try {
// signatureXML.SignatureXMLDocument("C:\\new.xml");
signatureXML.validate("C:\\old.xml");
} catch (Exception e) {
e.printStackTrace();
}
} }

【Java密码学】Java SE 6中XML数字签名的实现的更多相关文章

  1. 【Java密码学】使用Bouncy Castle生成数字签名、数字信封

    Bouncy Castle(轻量级密码术包)是一种用于 Java 平台的开放源码的轻量级密码术包,它支持大量的密码术算法,并提供 JCE 1.2.1 的实现.最近项目上正好用到了Bouncy Cast ...

  2. 【Java】Java XML 技术专题

    XML 基础教程 XML 和 Java 技术 Java XML文档模型 JAXP(Java API for XML Parsing) StAX(Streaming API for XML) XJ(XM ...

  3. 【Java密码学】用Java数字签名提供XML安全

    简介 众所周知,XML在产品和项目开发中起着非常重要的作用.通过XML文档可以获取很多信息,还可以使用XML文件进行CRUD(增加.查询.更新和删除)操作.然而值得注意的是,我们如何确保XML中的数据 ...

  4. Java中XML格式的字符串4读取方式的简单比较

    Java中XML格式的字符串4读取方式的简单比较 1.java自带的DOM解析. import java.io.StringReader; import javax.xml.parsers.Docum ...

  5. spring 的 PropertyPlaceholderConfigurer读取的属性怎么访问 (java访问方式,不是xml中的占位符哦)及此类的应用

    一.1.占位符的应用:(@Autowired注解方式,不需要建立set与get方法了,xml注入也不需要写了) http://www.cnblogs.com/susuyu/archive/2012/0 ...

  6. 第70节:Java中xml和tomcat

    第70节:Java中xml和tomcat 前言: 哭着也要看完,字数: jdbc crud - statement dao java.sql.Driver The interface that eve ...

  7. JAVA中 XML与数据库互转 学习笔记三

    要求 必备知识 JAVA基础知识,XML基础知识,数据库的基本操作. 开发环境 MyEclipse10/MySql5.5 资料下载 源码下载   数据库在数据查询,修改,保存,安全等方面与其他数据处理 ...

  8. 在 Java SE 6 中监视和诊断性能问题

    Java™ Platform, Standard Edition 6 (Java SE) 专注于提升性能,提供的增强工具可以管理和监视应用程序以及诊断常见的问题.本文将介绍 Java SE 平台中监视 ...

  9. Java中XML数据

    Java中XML数据 XML解析——Java中XML的四种解析方式 XML是一种通用的数据交换格式,它的平台无关性.语言无关性.系统无关性.给数据集成与交互带来了极大的方便.XML在不同的语言环境中解 ...

随机推荐

  1. 【转】 Pro Android学习笔记(七五):HTTP服务(9):DownloadManager

    目录(?)[-] 小例子 保存在哪里下载文件信息设置和读取 查看下载状态和取消下载 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件,转载须注明出处:http://blog.csd ...

  2. MongoDB之二基础入门(window/linux安装启动)

    mongodb中有三元素:数据库,集合,文档,其中“集合”就是对应关系数据库中的“表”,“文档”对应“行”. 一window安装与启动 一. 下载 上MongoDB官网 ,下载页面:https://w ...

  3. lvs-nat搭建httpd

    拓扑图: #172.16.252.10 [root@~ localhost]#route -n Kernel IP routing table Destination Gateway Genmask ...

  4. 十道海量数据处理面试题 - 数据分析与数据挖掘技术-炼数成金-Dataguru专业数据分析社区

    1.海量日志数据,提取出某日访问百度次数最多的那个IP. 首先是这一天,并且是访问百度的日志中的IP取出来,逐个写入到一个大文件中.注意到IP是32位的,最多有个2^32个IP.同样可以采用映射的方法 ...

  5. /*透明度设置的两种方式,以及hover的用法,fixed,(relative,absolute)这两个一起用*/

    <!DOCTYPE html> /*透明度设置的两种方式,以及hover的用法,fixed,(relative,absolute)这两个一起用*/ <html lang=" ...

  6. Python版的数据库查询构造器、ORM及动态迁移数据表。

    Orator Orator提供一个简单和方便的数据库数据处理库. 它的灵感来源于PHP的Laravel框架,借助其思想实现了python版的查询构造器和ORM. 这是完整的文档:http://orat ...

  7. Protocol Buffers官方文档(开发指南)

    本文是对官方文档的翻译,然后截取了一篇非常优秀的文章片段来帮助理解,本人英文水平有限,基本都是直译,如果有不理解的地方请参考英文官方文档,参考的文章链接在文章末尾 protocol buffers简介 ...

  8. 管理时间TED语录

    When people find out I write about time management, They assume two things. One is that I'm always o ...

  9. Environment Perception: 3D Truss Environment Mapping and Parametric Expression Extraction

    Experiments Preparation roscore rosrun pcl_ros pcd_to_pointcloud ~/.ros/wh2_lg707070_1ms0.01_filtere ...

  10. HELLO---MVC

    前言 很荣幸有机会参加BS的项目,这个图书馆系统这个项目,需要用到ITOO框架,其中涉及到好多小框架的学习,MVC就是其中的一个学习知识点,像大家一样,刚刚接触一个新鲜的知识,心里除了恐惧还有就是茫然 ...