簡體   English   中英

WSS4J和PCKS11密鑰庫

[英]WSS4J and PCKS11 keystore

我試圖將PKCS11梯形失真(智能卡)與WSS4J結合使用。 我有用於從智能卡創建梯形失真的代碼,還有另一個用於使用文件中的梯形失真通過WSS4J唱歌SOAP消息的代碼。 問題是如何“合並”它們。

PKCS11密鑰庫:

    String pin = "1111";
    char[] pin_arr = pin.toCharArray();
    String pkcs11config = "name = SmartCard\n"  + "library = c:/windows/system32/aetpkss1.dll";
    byte[] pkcs11configBytes = pkcs11config.getBytes();
    ByteArrayInputStream configStream = new ByteArrayInputStream(pkcs11configBytes);
    Provider pkcs11Provider = new sun.security.pkcs11.SunPKCS11(configStream);
    Security.addProvider(pkcs11Provider);

    KeyStore smartCardKeyStore = KeyStore.getInstance("PKCS11");

    smartCardKeyStore.load(null, pin_arr);

WSS4J簽名代碼:

    public Document signSOAPMessage(SOAPMessage soapEnvelope)
        throws SOAPException, TransformerException, WSSecurityException {
    Source src = soapEnvelope.getSOAPPart().getContent();
    TransformerFactory transformerFactory = TransformerFactory.newInstance();
    Transformer transformer = transformerFactory.newTransformer();
    DOMResult result = new DOMResult();
    transformer.transform(src, result);
    Document doc = (Document) result.getNode();

    final RequestData reqData = new RequestData();
    java.util.Map msgContext = new java.util.TreeMap();
    msgContext.put(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION, "true");
    msgContext.put(WSHandlerConstants.MUST_UNDERSTAND, "false");
    msgContext.put(WSHandlerConstants.SIG_PROP_FILE, "sender.properties");
    String bodyPart = "{Content}{}Body";
    String thumbprintPart = "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}BinarySecurityToken";
    msgContext.put(WSHandlerConstants.SIGNATURE_PARTS, bodyPart + ";" + thumbprintPart);
    msgContext.put(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION, "true");


    // Set this property if you want client public key (X509 certificate) sent along with document
    // server will check signature using this public key
    msgContext.put(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
    msgContext.put("password", "keystore");
    reqData.setMsgContext(msgContext);
    reqData.setUsername("clientca3");

    final java.util.List actions = new java.util.ArrayList();
    actions.add(new Integer(WSConstants.SIGN));
    CustomHandler handler = new CustomHandler();

    // sign document
    handler.send(WSConstants.SIGN, doc, reqData, actions, true);

    return doc;
}

最后是sender.properties文件:

    org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
    org.apache.ws.security.crypto.merlin.keystore.type=jks
    org.apache.ws.security.crypto.merlin.keystore.password=keystore
    org.apache.ws.security.crypto.merlin.keystore.alias=clientca3
    org.apache.ws.security.crypto.merlin.keystore.file=C:/temp/keystore.jks

我不確定這是否行得通,但是您可以嘗試...根據您的代碼,首先將pkcs11提供程序加載到Security。

public void loadPkcs11(){
    String pkcs11config = "name = SmartCard\n"  + "library = c:/windows/system32/aetpkss1.dll";
    byte[] pkcs11configBytes = pkcs11config.getBytes();
    ByteArrayInputStream configStream = new ByteArrayInputStream(pkcs11configBytes);
    Provider pkcs11Provider = new sun.security.pkcs11.SunPKCS11(configStream);
    Security.addProvider(pkcs11Provider);
}

然后,在簽署SOAP調用loadPkcs11方法之前,為了在簽署肥皂時提供程序可用:

public Document signSOAPMessage(SOAPMessage soapEnvelope)
    throws SOAPException, TransformerException, WSSecurityException {

    loadPkcs11();

    Source src = soapEnvelope.getSOAPPart().getContent();
    TransformerFactory transformerFactory = TransformerFactory.newInstance();
    Transformer transformer = transformerFactory.newTransformer();
    ...

和您的sender.properties文件:

org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=PKCS11
# provider name, all pkcs11 provider name is "SunPKCS11-" + the value of parameter name in your configuration
org.apache.ws.security.crypto.merlin.keystore.provider=SunPKCS11-SmartCard
# smartcard pin
org.apache.ws.security.crypto.merlin.keystore.password=1111
org.apache.ws.security.crypto.merlin.keystore.alias=
#this param is not required in pkcs11
org.apache.ws.security.crypto.merlin.keystore.file=

希望這可以幫助,

這是我的做法:

  1. 創建新的類CryptoSmartCard,它是Merlin的副本,並擴展了CryptoBase。 新類和Merlin之間的區別在於方法loadProperties(Properties屬性,ClassLoader加載器):

     public void loadProperties(Properties properties, ClassLoader loader) throws CredentialException, IOException { if (properties == null) { return; } this.properties = properties; // // Load the provider(s) // String provider = properties.getProperty(CRYPTO_KEYSTORE_PROVIDER); if (provider != null) { provider = provider.trim(); } String certProvider = properties.getProperty(CRYPTO_CERT_PROVIDER); if (certProvider != null) { setCryptoProvider(certProvider); } // // Load the KeyStore // String alias = properties.getProperty(KEYSTORE_ALIAS); if (alias != null) { alias = alias.trim(); defaultAlias = alias; } String keyStoreLocation = properties.getProperty(KEYSTORE_FILE); if (keyStoreLocation == null) { keyStoreLocation = properties.getProperty(OLD_KEYSTORE_FILE); } if (keyStoreLocation != null) { keyStoreLocation = keyStoreLocation.trim(); InputStream is = loadInputStream(loader, keyStoreLocation); try { String passwd = properties.getProperty(KEYSTORE_PASSWORD, "security"); if (passwd != null) { passwd = passwd.trim(); } String type = properties.getProperty(KEYSTORE_TYPE, KeyStore.getDefaultType()); if (type != null) { type = type.trim(); } String pin = properties.getProperty(KEYSTORE_PRIVATE_PASSWORD); char[] pin_arr = pin.toCharArray(); String pkcs11config = "name = SmartCard\\n" + "library = " + properties.getProperty(KEYSTORE_FILE); byte[] pkcs11configBytes = pkcs11config.getBytes(); ByteArrayInputStream configStream = new ByteArrayInputStream(pkcs11configBytes); Provider pkcs11Provider = new sun.security.pkcs11.SunPKCS11(configStream); try { Security.addProvider(pkcs11Provider); keystore = KeyStore.getInstance(type,pkcs11Provider); keystore.load(null, pin_arr); } catch (Exception ex) { // nothing } //keystore = load(is, passwd, provider, type); if (DO_DEBUG) { LOG.debug( "The KeyStore " + keyStoreLocation + " of type " + type + " has been loaded"); } String privatePasswd = properties.getProperty(KEYSTORE_PRIVATE_PASSWORD); if (privatePasswd != null) { privatePasswordSet = true; } } finally { if (is != null) { is.close(); } } } else { if (DO_DEBUG) { LOG.debug("The KeyStore is not loaded as KEYSTORE_FILE is null"); } } // // Load the TrustStore // String trustStoreLocation = properties.getProperty(TRUSTSTORE_FILE); if (trustStoreLocation != null) { trustStoreLocation = trustStoreLocation.trim(); InputStream is = loadInputStream(loader, trustStoreLocation); try { String passwd = properties.getProperty(TRUSTSTORE_PASSWORD, "changeit"); if (passwd != null) { passwd = passwd.trim(); } String type = properties.getProperty(TRUSTSTORE_TYPE, KeyStore.getDefaultType()); if (type != null) { type = type.trim(); } truststore = load(is, passwd, provider, type); if (DO_DEBUG) { LOG.debug( "The TrustStore " + trustStoreLocation + " of type " + type + " has been loaded"); } loadCACerts = false; } finally { if (is != null) { is.close(); } } } else { String loadCacerts = properties.getProperty(LOAD_CA_CERTS, "false"); if (loadCacerts != null) { loadCacerts = loadCacerts.trim(); } if (Boolean.valueOf(loadCacerts).booleanValue()) { String cacertsPath = System.getProperty("java.home") + "/lib/security/cacerts"; if (cacertsPath != null) { cacertsPath = cacertsPath.trim(); } InputStream is = new FileInputStream(cacertsPath); try { String cacertsPasswd = properties.getProperty(TRUSTSTORE_PASSWORD, "changeit"); if (cacertsPasswd != null) { cacertsPasswd = cacertsPasswd.trim(); } truststore = load(is, cacertsPasswd, null, KeyStore.getDefaultType()); if (DO_DEBUG) { LOG.debug("CA certs have been loaded"); } loadCACerts = true; } finally { if (is != null) { is.close(); } } } } // // Load the CRL file // String crlLocation = properties.getProperty(X509_CRL_FILE); if (crlLocation != null) { crlLocation = crlLocation.trim(); InputStream is = loadInputStream(loader, crlLocation); try { CertificateFactory cf = getCertificateFactory(); X509CRL crl = (X509CRL) cf.generateCRL(is); if (provider == null || provider.length() == 0) { crlCertStore = CertStore.getInstance( "Collection", new CollectionCertStoreParameters(Collections.singletonList(crl))); } else { crlCertStore = CertStore.getInstance( "Collection", new CollectionCertStoreParameters(Collections.singletonList(crl)), provider); } if (DO_DEBUG) { LOG.debug( "The CRL " + crlLocation + " has been loaded"); } } catch (Exception e) { if (DO_DEBUG) { LOG.debug(e.getMessage(), e); } throw new CredentialException(CredentialException.IO_ERROR, "ioError00", e); } finally { if (is != null) { is.close(); } } } 

    }

在該方法中,只有以下幾行發生了變化:

            String pin = properties.getProperty(KEYSTORE_PRIVATE_PASSWORD);
            char[] pin_arr = pin.toCharArray();
            String pkcs11config = "name = SmartCard\n" + "library = " + properties.getProperty(KEYSTORE_FILE);
            byte[] pkcs11configBytes = pkcs11config.getBytes();
            ByteArrayInputStream configStream = new ByteArrayInputStream(pkcs11configBytes);
            Provider pkcs11Provider = new sun.security.pkcs11.SunPKCS11(configStream);
            try {
                Security.addProvider(pkcs11Provider);

                keystore = KeyStore.getInstance(type,pkcs11Provider);

                keystore.load(null, pin_arr);


            } catch (Exception ex) {
                // nothing
            }
  1. 之后,我使用該類手動創建Crypto對象:

    Crypto crypto =新的CryptoSmartCard(prop);

這是簽名方法的代碼:

   public Document signSOAPMessage3(SOAPMessage soapEnvelope)
        throws SOAPException, TransformerException, WSSecurityException, CredentialException, IOException {
    Source src = soapEnvelope.getSOAPPart().getContent();
    TransformerFactory transformerFactory = TransformerFactory.newInstance();
    Transformer transformer = transformerFactory.newTransformer();
    DOMResult result = new DOMResult();
    transformer.transform(src, result);
    Document doc = (Document) result.getNode();

    Properties prop = new Properties();
    try {
        InputStream input = new FileInputStream("sender.properties");
        prop.load(input);
    } catch (IOException ex) {
        Logger.getLogger(TestSignWS1.class.getName()).log(Level.SEVERE, null, ex);
    }

    Crypto crypto = new CryptoSmartCard(prop);

    final RequestData reqData = new RequestData();
    java.util.Map msgContext = new java.util.TreeMap();
    //msgContext.put(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION, "true");
    msgContext.put(WSHandlerConstants.MUST_UNDERSTAND, "false");
    //msgContext.put(WSHandlerConstants.SIG_PROP_FILE, "sender.properties");
    String bodyPart = "{Content}{}Body";
    String thumbprintPart = "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}BinarySecurityToken";
    msgContext.put(WSHandlerConstants.SIGNATURE_PARTS, thumbprintPart + ";" + bodyPart);
    msgContext.put(WSHandlerConstants.IS_BSP_COMPLIANT, "false");
    msgContext.put(WSHandlerConstants.SIG_ALGO, WSConstants.RSA_SHA1);


    // Set this property if you want client public key (X509 certificate) sent along with document
    // server will check signature using this public key
    msgContext.put(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
    msgContext.put("password", prop.getProperty(KEYSTORE_PRIVATE_PASSWORD));
    reqData.setMsgContext(msgContext);
    reqData.setUsername(crypto.getDefaultX509Identifier());
    reqData.setUseSingleCert(true);
    reqData.setSigCrypto(crypto);

    final java.util.List actions = new java.util.ArrayList();
    actions.add(new Integer(WSConstants.SIGN));
    CustomHandler handler = new CustomHandler();

    // sign document
    handler.send(WSConstants.SIGN, doc, reqData, actions, true);

    return doc;
}

和配置文件:

org.apache.ws.security.crypto.provider=hgaa.ws.crypto.CryptoSmartCard
org.apache.ws.security.crypto.merlin.keystore.provider=SunPKCS11
org.apache.ws.security.crypto.merlin.keystore.type=PKCS11
org.apache.ws.security.crypto.merlin.keystore.file=c:/windows/system32/aetpkss1.dll
org.apache.ws.security.crypto.merlin.keystore.private.password=xxxx

在這種情況下,WSS4J中提供了“ MerlinDevice”加密實現。 因此,只需在您的加密屬性文件中定義以下內容:

org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.MerlinDevice

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM