我正在尝试签署一个看起来像这样的小xml:
<?xml version="1.0" encoding="UTF-8"?><test/>
我必须有这样的东西:
<soapenv:Envelope xmlns:elc="http://schemas.datacontract.org/2004/07/Arise.and.shine" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="X509-F86143B2B1BBA025BF144915430086958">MYCERTIFICAT</wsse:BinarySecurityToken>
<ds:Signature Id="SIG-F86143B2B1BBA025BF144915430086961" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces PrefixList="elc soapenv tem" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#id-C412303BE3B390B3D114265182390669">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces PrefixList="elc tem" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>dx3Bq2k18snVIR+CzEoyLZ3/jRc=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>KSvaK2EneWvtLXFMmynnBFd0h9PPnuipBa3Lib2pchGOtt8K3g8GsHAT5Vg6nGsNpo1e8SeikrNK4KRtUDne3CjvMh+LOajCpfWwl3u7W1yjp52HUODy+uZOfjL+B+9/kcDLyeJTdbB6KLVCwmD3TDuVA7tApR92VFXKTDT8X8DXrKaEl5a7fPLeb6mYfdAWsxY6Ua5KLZN+IGZAJsWi2SdOEhfHtMzbBvFOXokwysmLaYTmcY0GAkMq74Khna36SVUgxpSDDZoeDiHFGyu5CT9ClbJy8WTEAcJzlok1tvtikGzU//Md0ky0u4fuFiKeQlF+Qw/AxRG7SDqbdcLWrA==</ds:SignatureValue>
<ds:KeyInfo Id="KI-F86143B2B1BBA025BF144915430086959">
<wsse:SecurityTokenReference wsu:Id="STR-F86143B2B1BBA025BF144915430086960">
<wsse:Reference URI="#X509-F86143B2B1BBA025BF144915430086958" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
</wsse:Security>
</soapenv:Header>
<soapenv:Body wsu:Id="id-C412303BE3B390B3D114265182390669" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<tem:SendMessage>
<tem:request>
<elc:XmlData>
<![CDATA[<?xml version="1.0" encoding="UTF-8"?><test/>]]></elc:XmlData>
</tem:request>
</tem:SendMessage>
</soapenv:Body>
</soapenv:Envelope>
您可以看到要在标题中放入大量信息,并且签名与要发送的真实消息分开。这是我的代码:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.InvalidAlgorithmParameterException;
import java.security.Key;
import java.security.KeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.UnrecoverableKeyException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import javax.security.cert.X509Certificate;
import javax.xml.crypto.MarshalException;
import javax.xml.crypto.XMLStructure;
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.XMLSignatureException;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.KeyValue;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
public class Sign {
public static void main(String[] args) throws
KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, CertificateException, IOException,
InvalidAlgorithmParameterException, InstantiationException, IllegalAccessException, ClassNotFoundException,
KeyException, SAXException, ParserConfigurationException, MarshalException, XMLSignatureException, TransformerException {
String providerName = System.getProperty("jsr105Provider", "org.jcp.xml.dsig.internal.dom.XMLDSigRI");
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM",(Provider) Class.forName(providerName).newInstance());
Reference ref = fac.newReference("",fac.newDigestMethod(DigestMethod.SHA1, null),Collections.singletonList( fac.newTransform(Transform.ENVELOPED, (XMLStructure) null)),null, null);
SignedInfo si = fac.newSignedInfo(
fac.newCanonicalizationMethod(
CanonicalizationMethod.EXCLUSIVE,
(XMLStructure) null
),
fac.newSignatureMethod(
SignatureMethod.RSA_SHA1,
null
),
Collections.singletonList(ref)
);
FileInputStream is = new FileInputStream("D:\\Step 1\\mock\\NewJKS.jks");
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(is, null);
//Enumeration<String> myEnum = keystore.aliases();
for (Enumeration<String> e = keystore.aliases(); e.hasMoreElements();){
System.out.println(e.nextElement());
}
String alias = "toto";
Key key = keystore.getKey(alias, null);
System.out.println(key);
KeyPair kp = null;
if (key instanceof PrivateKey) {
// Get certificate of public key
Certificate cert = keystore.getCertificate(alias);
// Get public key
PublicKey publicKey = cert.getPublicKey();
// Return a key pair
kp = new KeyPair(publicKey, (PrivateKey) key);
// System.out.println(kp);
}
KeyInfoFactory kif = fac.getKeyInfoFactory();
KeyValue kv = kif.newKeyValue(kp.getPublic());
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = dbf.newDocumentBuilder().parse(new FileInputStream("D:\\Step 1\\mock\\XMLTestData.xml"));
DOMSignContext dsc = new DOMSignContext(kp.getPrivate(), doc.getDocumentElement());
XMLSignature signature = fac.newXMLSignature(si, ki);
signature.sign(dsc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer trans = tf.newTransformer();
trans.transform(new DOMSource(doc),new StreamResult(new FileOutputStream("D:\\Step 1\\mock\\mySignedFile2.xml")));
}
}
我得到的是这样的:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<test>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<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>iUqbN+l20aP00zS0qltBAv2oDbc=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>NiLEgObJbPot9kUJQ3kHi2z/1e6SGCqiZbrbAtc1snZp8MxoMothOA3dyqi6sDOBiLfdz7hRdEj+
gMwvkxci+KaqBtK2Rv9l9eE+/X5rjJz0aQM2Dq9kxB3BFwCSLdK0uMoO7YKAr6e6QirRI70npERt
gzAu4mriUpSkm5gbtWg=</SignatureValue>
<KeyInfo>
<KeyValue>
<RSAKeyValue>
<Modulus>tDcB3pWauMi0lZl7U/1g6Zj2dmeaokXJkbnytLtWCC1tyPsiWGNPxlKygVF+Pm+w4jciJxDzSxex
XY4jKTZz3a7qnq9EE/qo1ESzXpp+tus83iZFpPH+VpqBmcf1eutzSyEAqyYybAWm5p5q+2IqW+9H
UXIjgJczkCX/5nU7M6s=</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
</KeyValue>
</KeyInfo>
</Signature>
</test>
我的第一个问题是如何修改我的源代码以获得包络签名?
答案 0 :(得分:0)
有很多方法可以做。你的<test>
应该是正文。
我最喜欢的是下面的。
祝你好运。
它可能会有所帮助。
Element headerElement = null;
NodeList nodes = doc.getElementsByTagNameNS ("http://schemas.xmlsoap.org/soap/envelope/","Header");
headerElement = (Element)nodes.item(0);
// Create an XMLSignature instance
Element soapsec = doc.createElementNS("", "SOAP-SEC:Signature");
soapsec.setAttributeNS("", "mustUnderstand", "1");
soapsec.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:SOAP-SEC", "http://www.schemas.xmlsoap.org/soap/security/2000-10");
Transforms transforms = new Transforms(doc);
transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
transforms.addTransform(Transforms.TRANSFORM_C14N_WITH_COMMENTS);
XMLSignature sig = new XMLSignature(doc,"",XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1);
soapsec.appendChild(sig.getElement());
headerElement.appendChild(soapsec);
// Specify the transforms
sig.addDocument("#Body", transforms, org.apache.xml.security.utils.Constants.ALGO_ID_DIGEST_SHA1);
// Get the certificate and send for signing it will do what you required.
sig.sign(privateKey);