xml signature

27518 ワード

デジタル署名は、金融チャネルで働くときにある銀行が使用するW 3 Cのxml signatureを説明します.使用にはいくつかの難易度があり、通常のRSAとチェックマークを使用するよりも、w 3 c xml signatureには既存のオープンソースコードがありますが、jdkが持参したものを使用することをお勧めしません.jdkバージョンの互換性がないとだめです.署名仕様はXML-Signature Syntax and Processing,W 3 C Recommendation仕様(http://www.w3.org/TR/xmldsig-core/). Financeプロトコルは、分離署名(Detached signature)を使用します.すなわち、要素と署名された要素(例えば、CSReq/SResなど)はそれぞれ独立して存在します.署名された要素と要素は同じドキュメントに含まれます.署名要素は、'#CSReq 1234'などのローカル参照によって参照される.署名された要素の内容は、CSReq/SRes等の開始ラベルの開始括弧からCSReq/SRes等の終了ラベルの終了括弧までの内容を含む.署名構造図xml signature_第1张图片署名要求要素はSignatureにKeyInfoインスタンスがないことを要求する.ObjectインスタンスCanonicalizationMethod要素は空ではありませんが、Algorithm属性SignatureMethod要素は空ですが、Algorithm属性Transformsが存在し、いずれも1つのTransformを含むインスタンスTransform要素は空ですが、Algorithm属性DigestMethod要素は空ですが、Algorithm属性KeyInfoは表示されません.Canonicalization http://www.w3.org/TR/2001/REC-xml-cl4n-20010315 Digest http://www.w3.org/2000/09/xmldsig#shal Encoding http://www.w3.org/2000/09/xmldsig#base64 Signature http://www.w3.org/2000/09/xmldsig#rsa-sha1 Transform http://www.w3.org/2000/09/xmldsig#enveloped-signature
署名ネーミングスペースメッセージの署名は、デフォルトのネーミングスペースに宣言する必要があります.http://www.w3.org/2000/09/xmldsig#に表示されます.
署名例
< Finance>
    <Message id="111">
        <CSReq id="CSReq">
            <version>1.0.1version>
            <date>20070625 11:51:39date>
            <instId>WZCBinstId>
            <certId>123456certId>
            <signNo>200705131234567890signNo>
            <cardNo>123456cardNo>
            <cardType>DcardType>
            <name>  name>
            <gender>Mgender>
            <certType>1certType>
            <certNo>111111111111111certNo>
            <email>[email protected]email>
            <cell>13588888888cell>
            <address>      address>
            <memo>  memo>
        CSReq>
        <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
            <SignedInfo>
                <CanonicalizationMethod                 Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315">
                    CanonicalizationMethod>
                <SignatureMethod
                    Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1">
                    SignatureMethod>
                <Reference URI="#CSReq">
                    <Transforms>
                        <Transform                          Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature">
                            Transform>
                    Transforms>
                    <DigestMethod
                        Algorithm="http://www.w3.org/2000/09/xmldsig#sha1">
                        DigestMethod> <DigestValue>4t79dXZ7/BQqgiBdkziaKTUslVU=DigestValue>
                Reference>
            SignedInfo>           <SignatureValue>RyWMXvxlhmLuOIOvGSIkpV1iRV400F1B2W0zmW9nc5qfvfNMtpyp+uNwksBUjcO8H//NW4GvxcDdKMuuc6k5MDMH1E4OUg+624FUY23qs3R2ztubtD3MU7xk4f0iq9L16GK4ZBeID/Lyj6CxjaCcp3FuK1CznNj4Kr+qRLtxx+s= SignatureValue>
        Signature>
    Message>
 Finance>

コード実装
  • jarパッケージは、sun jdkが持参したものを推奨せず、IBMjdk環境ではxmlsec xercesImplをコンパイルできない
  • コード1 OfflineResolver
  • import org.apache.xerces.util.URI;
    import org.apache.xml.security.Init;
    import org.apache.xml.security.signature.XMLSignatureInput;
    import org.apache.xml.security.utils.resolver.ResourceResolverException;
    import org.apache.xml.security.utils.resolver.ResourceResolverSpi;
    import org.w3c.dom.Attr;
    
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.HashMap;
    import java.util.Map;
    
    public class OfflineResolver extends ResourceResolverSpi
    {
    
        public OfflineResolver()
        {
        }
    
        public XMLSignatureInput engineResolve(Attr uri, String BaseURI)
            throws ResourceResolverException
        {
            try
            {
                String URI = uri.getNodeValue();
                if(_uriMap.containsKey(URI))
                {
                    String newURI = (String)_uriMap.get(URI);
                    InputStream is = new FileInputStream(newURI);
                    XMLSignatureInput result = new XMLSignatureInput(is);
                    result.setSourceURI(URI);
                    result.setMIMEType((String)_mimeMap.get(URI));
                    return result;
                } else
                {
                    Object exArgs[] = {
                        "The URI " + URI + " is not configured for offline work"
                    };
                    throw new ResourceResolverException("generic.EmptyMessage", exArgs, uri, BaseURI);
                }
            }
            catch(IOException ex)
            {
                throw new ResourceResolverException("generic.EmptyMessage", ex, uri, BaseURI);
            }
        }
    
        public boolean engineCanResolve(Attr uri, String BaseURI)
        {
            String uriNodeValue = uri.getNodeValue();
            if(uriNodeValue.equals("") || uriNodeValue.startsWith("#"))
                return false;
            try
            {
                URI uriNew = new URI(new URI(BaseURI), uri.getNodeValue());
                if(uriNew.getScheme().equals("http"))
                {
                    return true;
                }
            }
            catch(URI.MalformedURIException malformeduriexception) { }
            return false;
        }
    
        private static void register(String URI, String filename, String MIME)
        {
            _uriMap.put(URI, filename);
            _mimeMap.put(URI, MIME);
        }
    
        static Map _uriMap = null;
        static Map _mimeMap = null;
    
        static 
        {
            // TODO :           !  ,           //    
            Init.init();
            _uriMap = new HashMap();
            _mimeMap = new HashMap();
            register("http://www.w3.org/TR/xml-stylesheet", "data/org/w3c/www/TR/xml-stylesheet.html", "text/html");
            register("http://www.w3.org/TR/2000/REC-xml-20001006", "data/org/w3c/www/TR/2000/REC-xml-20001006", "text/xml");
            register("http://www.nue.et-inf.uni-siegen.de/index.html", "data/org/apache/xml/security/temp/nuehomepage", "text/html");
            register("http://www.nue.et-inf.uni-siegen.de/~geuer-pollmann/id2.xml", "data/org/apache/xml/security/temp/id2.xml", "text/xml");
            register("http://xmldsig.pothole.com/xml-stylesheet.txt", "data/com/pothole/xmldsig/xml-stylesheet.txt", "text/xml");
            register("http://www.w3.org/Signature/2002/04/xml-stylesheet.b64", "data/ie/baltimore/merlin-examples/merlin-xmldsig-twenty-three/xml-stylesheet.b64", "text/plain");
        }
    }
  • コード2、署名、チェック
  • import org.apache.commons.io.IOUtils;
    import org.apache.xml.security.exceptions.XMLSecurityException;
    import org.apache.xml.security.signature.XMLSignature;
    import org.apache.xml.security.signature.XMLSignatureException;
    import org.apache.xml.security.transforms.Transforms;
    import org.apache.xml.security.utils.Constants;
    import org.apache.xml.security.utils.XMLUtils;
    import org.apache.xpath.XPathAPI;
    import org.dom4j.Document;
    import org.dom4j.DocumentHelper;
    import org.w3c.dom.Element;
    import org.w3c.dom.Node;
    import org.xml.sax.SAXException;
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    import javax.xml.transform.TransformerException;
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.security.KeyStore;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.cert.Certificate;
    import java.security.cert.CertificateException;
    import java.security.cert.CertificateFactory;
    import java.security.cert.X509Certificate;
    
    public class XmlSignature {
    
            /**
             *   
             * @param document
             * @param messageType
             * @param privateKey
             * @param password
             * @return
             * @throws Exception
             */
            public static String generateXMLDigitalSignature1(Document document, String messageType, PrivateKey privateKey, String password) throws Exception {
                ByteArrayOutputStream os = null;
                //   document   W3C     
                org.w3c.dom.Document doc = parse(document);//     DOM4J >>> W3C
                XMLSignature sig = new XMLSignature(doc, doc.getDocumentURI(), XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1);//         
                sig.getSignedInfo().addResourceResolver(new OfflineResolver());
                Node messageNode = doc.getElementsByTagName("Message").item(0);
                messageNode.appendChild(sig.getElement());
                Transforms transforms = new Transforms(doc);
                transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
                //          
                sig.addDocument("#" + messageType, transforms, Constants.ALGO_ID_DIGEST_SHA1);
                sig.sign(privateKey);
                os = new ByteArrayOutputStream();//      XML    
                XMLUtils.outputDOM((Node) doc, os);
                return os.toString("UTF-8");
            }
    
        /**
         *   
         * @param signatureXml
         * @param publicKeyByte
         * @return
         * @throws Exception
         */
            public static boolean validateXMLDigitalSignature(String signatureXml, byte[] publicKeyByte) throws Exception {
                ByteArrayInputStream is = null;
                try {
                    CertificateFactory certificatefactory;
                    certificatefactory = CertificateFactory.getInstance("X.509");
                    //          
                    is = new ByteArrayInputStream(publicKeyByte);
                    X509Certificate cert = (X509Certificate) certificatefactory.generateCertificate(is);
                    PublicKey pk = cert.getPublicKey();
                    org.w3c.dom.Document doc = (org.w3c.dom.Document) parse(DocumentHelper.parseText(signatureXml));
                    Element nscontext = XMLUtils.createDSctx(doc, "ds", "http://www.w3.org/2000/09/xmldsig#");
                    Element signElement = (Element) XPathAPI.selectSingleNode(doc, "//ds:Signature[1]", nscontext);
                    //       
                    if (signElement == null) {
                        return false;
                    }
                    XMLSignature signature;
                    signature = new XMLSignature(signElement, doc.getDocumentURI());
                    return signature.checkSignatureValue(pk);
                } catch (TransformerException e) {
                    throw new Exception("    !Exception is : " + e);
                } catch (XMLSignatureException e) {
                    throw new Exception("XML    !Exception is : " + e);
                } catch (XMLSecurityException e) {
                    throw new Exception("XML    !Exception is :" + e);
                } catch (CertificateException e) {
                    throw new Exception("    !Exception is :" + e);
                }  finally {
                    if (is != null) {
                        try {
                            is.close();
                        } catch (IOException e) {
                            throw new Exception("XML    !Exception is : " + e);
                        }
                    }
                }
            }
    
    
        public static PrivateKey getPrivateKey(byte[] privateKeyStream, String privateKeyPassword,String keyAlias) throws Exception {
            if (privateKeyStream == null) {
                throw new RuntimeException("nullPointException: privateKey byte is null");
            }
            if (privateKeyPassword == null) {
                throw new RuntimeException("nullPointException: privateKeyPassword is null");
            }
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            InputStream inputStream = new ByteArrayInputStream(privateKeyStream);
            keyStore.load(inputStream, privateKeyPassword.toCharArray());
            PrivateKey p =(PrivateKey) keyStore.getKey(keyAlias, privateKeyPassword.toCharArray());
            return p;
        }
    
            public static PublicKey getPublicKey(byte[] publicKeyStream) throws Exception {
                if (publicKeyStream == null) {
                    throw new RuntimeException("nullPointException: publicKey byte is null");
                }
                CertificateFactory cf = CertificateFactory.getInstance("X.509");
                InputStream inputStream = new ByteArrayInputStream(publicKeyStream);
                Certificate c = cf.generateCertificate(inputStream);
                return c.getPublicKey();
            }
            /**
             *   dom4j org.w3c.dom.Document   
             * @param doc
             * @return
             * @throws
             */
            public static org.w3c.dom.Document parse(Document doc) throws Exception{
                if (doc == null) {
                    return (null);
                }
                InputStream is = null;
                try {
                    is = IOUtils.toInputStream(doc.asXML(), "UTF-8");
                    DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
                    docBuilderFactory.setNamespaceAware(true);
                    DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
                    is.close();
                    return docBuilder.parse(is);
                } catch (IOException e) {
                    throw new Exception("XML    !Exception is : " + e);
                } catch (SAXException e) {
                    throw new Exception("      !Exception is : " + e);
                } catch (ParserConfigurationException e) {
                    throw new Exception("      !Exception is : " + e);
                } finally {
                    if (is != null) {
                        try {
                            is.close();
                        } catch (IOException e) {
                            throw new Exception("XML    !Exception is : " + e);
                        }
                    }
                }
            }
    }