<?XML version="1.0" encoding="UTF-8" standalone="no"?> <invoice XMLns="http://www.company.com/accounting"> <items> <item> <desc>Applied Cryptography</desc> <type>book</type> <unitprice>44.50</unitprice> <quantity>1</quantity> </item> </items> <creditcard> <number>123456789</number> <expiry>10/20/2009</expiry> <lastname>John</lastname> <firstname>Smith</firstname> </creditcard> </invoice> |
keytool -genkey -keysize 512 -sigalg DSA -dname "cn=Young Yang, ou=Architecture, o=Company, L=New York, ST=NY, c=US" -alias biz -keypass kp1234 -keystore bizkeystore -storepass sp1234 -validity 180 |
public static KeyPair getKeyPair(String store,String sPass,String kPass,String alias) throws CertificateException, IOException, UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException{ KeyStore ks = loadKeyStore(store,sPass); KeyPair keyPair = null; Key key = null; PublicKey publicKey = null; PrivateKey privateKey = null; if (ks.containsAlias(alias)){ key = ks.getKey(alias,kPass.toCharArray()); if (key instanceof PrivateKey){ Certificate cert = ks.getCertificate(alias); publicKey = cert.getPublicKey(); privateKey = (PrivateKey)key; return new KeyPair(publicKey,privateKey); }else{ return null; } } else { return null; } } |
public static PublicKey getPublicKey(String store, String sPass, String alias) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException{ KeyStore ks = loadKeyStore(store, sPass); Certificate cert = ks.getCertificate(alias); return cert.getPublicKey(); } |
private static KeyStore loadKeyStore(String store, String sPass) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException{ KeyStore myKS = KeyStore.getInstance("JKS"); FileInputStream fis = new FileInputStream(store); myKS.load(fis,sPass.toCharArray()); fis.close(); return myKS; } |
public class Sign { public static void main(String[] args) throws Exception { String input = "./etc/invoice.xml "; String output = "./etc/signature.xml"; if (args.length > 2) { input = args[0]; output = args[1]; } //准备 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); //步骤1 String providerName = System.getProperty("jsr105Provider","org.jcp.XML.dsig.internal.dom.XMLDSigRI"); XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM",(Provider) Class.forName(providerName).newInstance()); //步骤2 Reference ref = fac.newReference("#invoice",fac.newDigestMethod(DigestMethod.SHA1, null)); //步骤3 Document XML = dbf.newDocumentBuilder().parse(new File(input)); Node invoice = XML.getDocumentElement(); XMLStructure content = new DOMStructure(invoice); XMLObject obj = fac.newXMLObject(Collections.singletonList(content),"invoice", null, null); //步骤4 SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS, (C14NMethodParameterSpec) null), fac.newSignatureMethod(SignatureMethod.DSA_SHA1, null), Collections.singletonList(ref)); //步骤5,分为情形5.0或5.1 PrivateKey privateKey = null; //情形5.0 privateKey = KeyStoreInfo.getPrivateKey("./etc/bizkeystore","sp1234","kp1234", "biz"); //情形5.1,分为情形5.1.1或5.1.2 //情形5.1.1 //KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA"); //kpg.initialize(512); //KeyPair kp = kpg.generateKeyPair(); //情形5.1.2 // KeyPair kp = KeyStoreInfo.getKeyPair("./etc/bizkeystore", "sp1234", // "kp1234","biz"); //如果针对情形5.1,请去掉下面一行中的注释 // privateKey = kp.getPrivate(); //步骤6,分为情形6.0,6.1或6.2 //情形6.0,如果针对情形6.1或6.2也使用下面这一行 KeyInfo ki = null; //如果针对情形6.1或6.2请去掉下面一行中的注释 // KeyInfoFactory kif = fac.getKeyInfoFactory(); //情形6.1 // KeyValue kv = kif.newKeyValue(kp.getPublic()); // ki = kif.newKeyInfo(Collections.singletonList(kv)); //情形6.2 // CertificateFactory cf = CertificateFactory.getInstance("X.509"); // FileInputStream fis = new FileInputStream("./etc/biz.cer"); // java.security.cert.Certificate cert = cf.generateCertificate(fis); // fis.close(); // X509Data x509d = kif.newX509Data(Collections.singletonList(cert)); // ki = kif.newKeyInfo(Collections.singletonList(x509d)); //步骤7 XMLSignature signature = fac.newXMLSignature(si, ki,Collections.singletonList(obj), null, null); //步骤8 Document doc = dbf.newDocumentBuilder().newDocument(); DOMSignContext dsc = new DOMSignContext(privateKey, doc); //步骤9 signature.sign(dsc); //转换成一个xml文档 TransformerFactory tf = TransformerFactory.newInstance(); Transformer trans = tf.newTransformer(); trans.transform(new DOMSource(doc),new StreamResult(new FileOutputStream(output))); } } |
public abstract DigestMethod newDigestMethod(String algorithm, DigestMethodParameterSpec params) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException |
public abstract Reference newReference(String uri, DigestMethod dm); public abstract Reference newReference(String uri, DigestMethod dm, List transforms, String type, String id); public abstract Reference newReference(String uri, DigestMethod dm, List transforms, String type, String id, byte[] digestValue); ...... |
<element name="Reference" type="ds:ReferenceType"/> <complexType name="ReferenceType"> <sequence> <element ref="ds:Transforms" minOccurs="0"/> <element ref="ds:DigestMethod"/> <element ref="ds:DigestValue"/> </sequence> <attribute name="Id" type="ID" use="optional"/> <attribute name="URI" type="anyURI" use="optional"/> <attribute name="Type" type="anyURI" use="optional"/> </complexType> |
<element name="Object" type="ds:ObjectType"/> <complexType name="ObjectType" mixed="true"> <sequence minOccurs="0" maxOccurs="unbounded"> <any namespace="##any" processContents="lax"/> </sequence> <attribute name="Id" type="ID" use="optional"/> <attribute name="MimeType" type="string" use="optional"/> <attribute name="Encoding" type="anyURI" use="optional"/> </complexType> |
<element name="SignedInfo" type="ds:SignedInfoType"/> <complexType name="SignedInfoType"> <sequence> <element ref="ds:CanonicalizationMethod"/> <element ref="ds:SignatureMethod"/> <element ref="ds:Reference" maxOccurs="unbounded"/> </sequence> <attribute name="Id" type="ID" use="optional"/> </complexType> |
fac.newCanonicalizationMethod(alg,null) |
public abstract SignatureMethod newSignatureMethod(String algorithm, SignatureMethodParameterSpec params) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException |
public abstract SignedInfo newSignedInfo(CanonicalizationMethod cm, SignatureMethod sm, List references); public abstract SignedInfo newSignedInfo(CanonicalizationMethod cm, SignatureMethod sm, List references, String id). |
public abstract XMLSignature newXMLSignature(SignedInfo si, KeyInfo ki); public abstract XMLSignature newXMLSignature(SignedInfo si, KeyInfo ki, List objects, String id, String signatureValueId). |
public class Validate { public static void main(String[] args) throws Exception { //第一步 String providerName = System.getProperty("jsr105Provider","org.jcp.XML.dsig.internal.dom.XMLDSigRI"); XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM",(Provider) Class.forName(providerName).newInstance()); //第二步 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); Document doc = dbf.newDocumentBuilder().parse(new FileInputStream(args[0])); //第三步 NodeList nl = doc.getElementsByTagNameNS(XMLSignature.xmlNS,"Signature"); if (nl.getLength() == 0) { throw new Exception("Cannot find Signature element!"); } //第四步,分为情形4.0,4.1,4.2或4.3 //第4.0种情形 DOMValidateContext valContext = new DOMValidateContext(new KeyStoreKeySelector(), nl.item(0)); //第4.1种情形,需要Sign.java中的第6.1种情形 // DOMValidateContext valContext = new DOMValidateContext( // new KeyValueKeySelector(), nl.item(0)); //第4.2种情形,需要Sign.java中的第6.2种情形 // KeyStore ks = KeyStore.getInstance("JKS"); // FileInputStream fis = new FileInputStream("./etc/bizkeystore"); // ks.load(fis,"sp1234".toCharArray()); // fis.close(); // X509KeySelector x509ks = new X509KeySelector(ks); // DOMValidateContext valContext = new DOMValidateContext(x509ks, nl.item(0)); //第4.3中情形 // PublicKey pKey = KeyStoreInfo.getPublicKey("./etc/bizkeystore", // "sp1234", "biz"); //第五步 XMLSignature signature = fac.unmarshalXMLSignature(valContext); //XMLSignature signature = fac.unmarshalXMLSignature(new DOMStructure(nl.item(0))); //第六步 boolean coreValidity = signature.validate(valContext); //检查核心校验状态 if (coreValidity == false) { System.err.println("Signature failed core validation!"); boolean sv = signature.getSignatureValue().validate(valContext); System.out.println("Signature validation status: " + sv); //每一个Reference的检查校验状态 Iterator i = signature.getSignedInfo().getReferences().iterator(); for (int j = 0; i.hasNext(); j++) { boolean refValid = ((Reference) i.next()).validate(valContext); System.out.println("Reference (" + j + ") validation status: "+ refValid); } } else { System.out.println("Signature passed core validation!"); } } } |
public DOMValidateContext(Key validatingKey,Node node) |
public abstract KeySelectorResult select(KeyInfo keyInfo, Purpose purpose, AlgorithmMethod method, XMLCryptoContext context) throws KeySelectorException public static KeySelector singletonKeySelector(Key key) |
public abstract XMLSignature unmarshalXMLSignature(XMLValidateContext context) throws MarshalException |
public class Tamper { public static void main(String[] args) throws Exception { String sigfile = "etc/signature.xml"; //决定要修改的标志-Reference或SignatureValue boolean tamperRef = true ; if (args.length >= 2) { sigfile = args[0]; tamperRef = Boolean.parseBoolean(args[1]); } File file = new File(sigfile); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); Document signature = dbf.newDocumentBuilder().parse(file); if (tamperRef){ //修改信用卡号 NodeList targets =signature.getDocumentElement().getElementsByTagName("number"); Node number = targets.item(0); if (!number.getTextContent().equals("987654321")){ number.setTextContent("987654321"); }else{ number.setTextContent("000000000"); } }else{ //修改SignatureValue(第一字节) BASE64Encoder en = new BASE64Encoder(); BASE64Decoder de = new BASE64Decoder(); NodeList sigValues =signature.getDocumentElement().getElementsByTagName("SignatureValue"); Node sigValue = sigValues.item(0); byte[] oldValue = de.decodeBuffer(sigValue.getTextContent()); if (oldValue[0]!= 111){ oldValue[0] = (byte)111; }else{ oldValue[0] = (byte)112; } sigValue.setTextContent(en.encode(oldValue)); } TransformerFactory tf = TransformerFactory.newInstance(); Transformer trans = tf.newTransformer(); trans.transform(new DOMSource(signature),new StreamResult(new FileOutputStream(file))); } } |
本文出自 “青峰” 博客,转载请与作者联系!