例子
test.xml
<license>
<test>hello world</test>
</license>
test_sign.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<license>
<test>hello world</test>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>YtX4fzWIPzHuoJXrIbSCCJwizPs=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>B1fRTKI1JJNqVr3vL+rrBVuTzDP/6+V9dkRp5tCoDzwhipcHVHkr2fRYDDu3tIGg7blBj+GkGTW7
ZPKjLng7I+y5LhNMZM6X6foD1bX9wp8YyI5X1uBbrdV804DRvbfZ2HuT3/BnT1IlTLsgVumxw4vf
fS1goAqgr6uoOs7yr/A=</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>(这里显示证书ASN.1信息)
</X509Certificate>
<X509SubjectName>CN=test,OU=test,OU=112222222,L=SHENZHEN,ST=GUANGDONG,C=CN</X509SubjectName>
</X509Data>
</KeyInfo>
</Signature>
</license>
代码
签名
try {
XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory.getInstance("DOM");
Transform envelopedTransform = xmlSignatureFactory.newTransform(Transform.ENVELOPED , (XMLStructure) null);
DigestMethod sha1DigestMethod = xmlSignatureFactory.newDigestMethod(DigestMethod.SHA1 , null);
//创建reference元素
Reference reference = xmlSignatureFactory.newReference("" ,
sha1DigestMethod ,
Collections.singletonList(envelopedTransform),
null , null);
SignatureMethod rsaSignatureMethod = xmlSignatureFactory.newSignatureMethod(SignatureMethod.RSA_SHA1 , null);
CanonicalizationMethod canonicalizationMethod = xmlSignatureFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE ,
(XMLStructure) null);
//创建SignedInfo元素
SignedInfo signedInfo = xmlSignatureFactory.newSignedInfo(
canonicalizationMethod ,
rsaSignatureMethod,
Collections.singletonList(reference));
//创建密钥对
KeyStore keyStore = KeyStore.getInstance("PKCS12");
File file = new File(pfxFile);
FileInputStream fis = new FileInputStream(file);
keyStore.load(fis, password);
fis.close();
//获取别名
Enumeration enumas = keyStore.aliases();
String alias = null;
while (enumas.hasMoreElements()) {
alias = (String) enumas.nextElement();
}
//准备密钥对
Key key = keyStore.getKey(alias, password);
KeyPair keyPair = null;
if (key instanceof PrivateKey) {
Certificate cert = keyStore.getCertificate(alias);
PublicKey publicKey = cert.getPublicKey();
keyPair = new KeyPair(publicKey, (PrivateKey) key);
}
X509Certificate x509 = (X509Certificate) keyStore.getCertificate(alias);
KeyInfoFactory keyInfoFactory = xmlSignatureFactory.getKeyInfoFactory();
List x509Content = new ArrayList();
x509Content.add(x509);
x509Content.add(x509.getSubjectX500Principal().getName());
X509Data x509Data = keyInfoFactory.newX509Data(x509Content);
KeyInfo keyInfo = keyInfoFactory.newKeyInfo(Collections.singletonList(x509Data));
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
Document document = documentBuilderFactory.newDocumentBuilder().
parse(new FileInputStream(srcFile));
DOMSignContext domSignContext = new DOMSignContext(keyPair.getPrivate() , document.getDocumentElement());
//创建Signature元素
XMLSignature xmlSignature = xmlSignatureFactory.newXMLSignature(signedInfo , keyInfo);
xmlSignature.sign(domSignContext);
//输出处理后的文件
OutputStream outputStream = new FileOutputStream(dstFile);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document) , new StreamResult(outputStream));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (XMLSignatureException e) {
e.printStackTrace();
} catch (MarshalException e) {
e.printStackTrace();
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
验签
try {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
Document document = documentBuilderFactory.newDocumentBuilder().
parse(new FileInputStream(dstFile));
NodeList nodeList = document.getElementsByTagNameNS(XMLSignature.XMLNS , "Signature");
if(nodeList.getLength() == 0){
throw new Exception("Cannot find Signature element");
}
DOMValidateContext validateContext = new DOMValidateContext(new X509KeySelector() , nodeList.item(0));
XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory.getInstance("DOM");
XMLSignature xmlSignature = xmlSignatureFactory.unmarshalXMLSignature(validateContext);
boolean result = xmlSignature.validate(validateContext);
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
public class X509KeySelector extends KeySelector {
@Override
public KeySelectorResult select(KeyInfo keyInfo, Purpose purpose, AlgorithmMethod method, XMLCryptoContext context)
throws KeySelectorException {
Iterator keyInfos = keyInfo.getContent().iterator();
while (keyInfos.hasNext()) {
XMLStructure xmlStructure = (XMLStructure) keyInfos.next();
if (!(xmlStructure instanceof X509Data)) {
continue;
}
X509Data x509Data = (X509Data) xmlStructure;
Iterator x509s = x509Data.getContent().iterator();
while (x509s.hasNext()) {
Object object = x509s.next();
if (!(object instanceof X509Certificate)) {
continue;
}
final PublicKey publicKey = ((X509Certificate) object).getPublicKey();
if (algEquals(method.getAlgorithm() , publicKey.getAlgorithm())) {
return new KeySelectorResult() {
@Override
public Key getKey() {
return publicKey;
}
};
}
}
}
throw new KeySelectorException("No key found");
}
static boolean algEquals(String algURI , String algName){
if (algName.equalsIgnoreCase("DSA") && algURI.equalsIgnoreCase(SignatureMethod.DSA_SHA1)
|| algName.equalsIgnoreCase("RSA") && algURI.equalsIgnoreCase(SignatureMethod.RSA_SHA1)) {
return true;
}
return false;
}
}
参考
Programming With the Java XML Digital Signature API