2014-02-22 46 views
0

我正在尝试使用PKCS11 keystone(智能卡)和WSS4J。我有用于从智能卡创建keystone的代码,以及使用来自文件的keystone用WSS4J演唱SOAP消息的另一个代码。问题是如何“合并”它们。WSS4J和PCKS11密钥库

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 

回答

0

我不知道这是否可以正常工作,但您可以尝试...根据您的代码,首先将pkcs11提供程序加载到安全性。

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= 

希望这会有所帮助,

0

以下是我如何做到的:

  1. 创建新类CryptoSmartCard,它是Merlin的副本并扩展了CryptoBase。新的类和默林之间的区别是在方法loadProperties(属性属性,类加载器加载器):

    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 = new 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 
0

有一个 “MerlinDevice” 加密在WSS4J可实施此方案。因此,只需在您的加密属性文件中定义以下内容:

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