简体   繁体   中英

Java WSS4J certificate disappears from keystore after signing request

I am using WSS4J to create a soap request signer with a certificate from the keystore. My keystore format is .pkcs and everything works with the first signing, but if I try to run the program to sign more than one document and it doesn't find the certificate in the keystore. It seems to me that the certificate is possibly consumed during signing, which means that it no longer exists for the current environment. If the program stops and starts again it will sign the first request but the second request fails. I have stepped through multiple times and cannot figure out what the cause is. This code is the last thing being called before the certificate disappears from the keystore this.certUri = getWsConfig().getIdAllocator().createSecureId("X509-", certs[0]); this is found on line 556 in WSSecSignature.class . Here is my code.

package com.soapsigner;

import java.io.*;
import java.util.Properties;

import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.ws.security.*;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.components.crypto.Merlin;
import org.apache.ws.security.message.WSSecHeader;
import org.apache.ws.security.message.WSSecSignature;
import org.apache.ws.security.message.WSSecTimestamp;
import org.w3c.dom.Document;
import org.xml.sax.*;

public class SoapSigner {
    private Crypto crypto;
    private WSSecSignature sig;
    private WSSecTimestamp time;
    private WSSecHeader header; 
    private String alias;
    private String password;
    private String keyFile;
    private String keyFileType;
    private Document signedDoc;
    private String lastError;   
    {
        Logger rootLogger = Logger.getRootLogger();
        rootLogger.setLevel(Level.INFO);
        rootLogger.addAppender(new ConsoleAppender(
                   new PatternLayout("%-6r [%p] %c - %m%n")));
    }   
    //constructor
    public SoapSigner(String XML){
        try {           
            alias = "myalias";
            password = "mypassword";
            keyFile = "/keystore/mykeystore.pkcs";
            keyFileType = "pkcs12";
            sig = new WSSecSignature(); 
            time = new WSSecTimestamp();
            header = new WSSecHeader();
            signedDoc = null;
            lastError = "";         

            Merlin merlin = new Merlin(getCryptoProperties());  
            System.out.println("real signing keystore object: "+merlin.getKeyStore().getCertificate(alias).toString().length()); //Passed
            crypto = merlin;            

            signDocument(xmlToDoc(XML));

            Merlin test = new Merlin(getCryptoProperties());
            System.out.println("test  keystore object: "+test.getKeyStore().getCertificate(alias).toString().length()); //Failed, this is null

        } catch (Exception e) {
            setLastError(e);
        }
    }

    //properties
    public Properties getCryptoProperties(){
        Properties cryptoProperties = new Properties();
        cryptoProperties.setProperty("org.apache.ws.security.crypto.merlin.keystore.alias", alias);       
        cryptoProperties.setProperty("org.apache.ws.security.crypto.merlin.keystore.password", password);
        cryptoProperties.setProperty("org.apache.ws.security.crypto.merlin.keystore.type", keyFileType);
        cryptoProperties.setProperty("org.apache.ws.security.crypto.merlin.keystore.file", keyFile);        
        return cryptoProperties;        
    }

    //sign the document
    public void signDocument(Document doc){             
        try {   
            header.setMustUnderstand(true);
            sig.setSignatureAlgorithm(WSConstants.C14N_EXCL_OMIT_COMMENTS);
            sig.setSignatureAlgorithm(WSConstants.RSA);
            sig.setUserInfo(alias, password);
            sig.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE); 
            header.insertSecurityHeader(doc);
            sig.build(doc, crypto, header);
            time.build(doc, header);
            signedDoc = doc;
        } catch (Exception e) {         
            setLastError(e);
        }           
    }

    //get the signed document
    public Document getDocument(){      
        return signedDoc;       
    }

    //get the signed xml
    public String getXML(){
        return getStringFromDoc(getDocument()).trim();
    }

    //get last error
    public String getLastError(){
        return lastError;
    }

    //set last error
    private void setLastError(Throwable e){
        StringWriter sw = new StringWriter();
        e.printStackTrace(new PrintWriter(sw));
        lastError += "     NEXT ERROR     "+sw.toString();
        e.printStackTrace();
    }   

    //document to string
    public String getStringFromDoc(Document doc){
        try
        {
           DOMSource domSource = new DOMSource(doc);
           StringWriter writer = new StringWriter();
           StreamResult result = new StreamResult(writer);
           TransformerFactory tf = TransformerFactory.newInstance();
           Transformer transformer = tf.newTransformer();
           transformer.transform(domSource, result);
           writer.flush();
           return writer.toString();
        }
        catch(Exception e)
        {
           setLastError(e);
           return null;
        }
    }

    //string to document
    public Document xmlToDoc(String XML){   
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            DocumentBuilder db;     
            db = dbf.newDocumentBuilder();      
            InputSource is = new InputSource();
            is.setCharacterStream(new StringReader(XML));
            Document doc = db.parse(is);
        return doc;
        } catch (Exception e) {
            setLastError(e);
            return null;
        }       
    }

    //main
    public static void main(String[] args){     
        String XML1 = "<?xml version='1.0' encoding='UTF-8'?><soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> <soap:Body> <test1></test1> </soap:Body> </soap:Envelope>";  
        String XML2 = "<?xml version='1.0' encoding='UTF-8'?><soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> <soap:Body> <test2></test2> </soap:Body> </soap:Envelope>";  
        new SoapSigner(XML1);           
        new SoapSigner(XML2);               
    }
}

Also, I would like to turn the doDebug mode on in the WSSecBase.class but it won't showup in the variable viewer to toggle the value. I created a breakpoint in the constructor and set it to be watched but it never shows up to toggle.

Your testcase works fine for me with a .p12 from WSS4J test source on the latest WSS4J SNAPSHOT code. Are you using an older version of WSS4J? If so please try with the latest releases + see if it works. If not, then please create a test-case with your .p12 file + create a new issue in the WSS4J JIRA:

https://issues.apache.org/jira/browse/WSS

Colm.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM