數據加載中……
          Java SE 6中XML數字簽名的實現
          ackage 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();
                 }
             }

          }


          posted on 2008-02-24 14:05 java flex 結合 閱讀(2363) 評論(1)  編輯  收藏 所屬分類: xml

          評論

          # re: Java SE 6中XML數字簽名的實現 2014-10-31 10:41 楊燁

          怎么沒有私鑰公鑰文件
            回復  更多評論    
          主站蜘蛛池模板: 兴化市| 来安县| 辉县市| 洪湖市| 米林县| 台安县| 山西省| 阿拉善盟| 如东县| 平顶山市| 阳谷县| 泽普县| 云梦县| 兴和县| 泸定县| 兴安盟| 丰顺县| 鸡泽县| 汉寿县| 南和县| 屏南县| 定安县| 民和| 十堰市| 咸阳市| 河曲县| 洮南市| 鸡东县| 阜新市| 兰西县| 友谊县| 柏乡县| 五家渠市| 邯郸市| 民勤县| 清新县| 新沂市| 资讯 | 娱乐| 东山县| 依兰县|