2016-09-30 27 views
2

因此,我已經編寫了一些代碼來獲取PEM,並通過bouncycastle將其添加到PKCS密鑰庫,然後使用java crypto將PKCS密鑰庫值導入到JKS密鑰庫中。算法HmacPBESHA256不可用

我發誓,昨天我有一個單元測試通過在成功地執行這些步驟,但今天早上我開始打這個

Caused by: java.security.NoSuchAlgorithmException: Algorithm HmacPBESHA256 not available 
    at javax.crypto.Mac.getInstance(Mac.java:181) ~[na:1.8.0_60] 
    at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:2039) ~[na:1.8.0_65] 

現在,它總是可能的東西改變了我的下面,但我想不出是什麼是。似乎無論提供商我使用該算法已經消失。

這裏是我的java.security文件片段:

security.provider.1=sun.security.provider.Sun 
security.provider.2=sun.security.rsa.SunRsaSign 
security.provider.3=sun.security.ec.SunEC 
security.provider.4=com.sun.net.ssl.internal.ssl.Provider 
security.provider.5=com.sun.crypto.provider.SunJCE 
security.provider.6=sun.security.jgss.SunProvider 
security.provider.7=com.sun.security.sasl.Provider 
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI 
security.provider.9=sun.security.smartcardio.SunPCSC 
security.provider.10=apple.security.AppleProvider 

這裏沒有一大堆的代碼。首先,我通過bouncycastle創建一個PKCS密鑰庫,添加一個pem並將其作爲PKCS12保存到磁盤。然後通過java crypto導入,並保存爲JKS。

public KeystoreBuilder createJksFromPem(String pemPrivate, String pemPublic, String alias) throws Exception 
    { 
     Preconditions.checkState(StringUtils.isNotEmpty(pemPrivate), "pemPrivate must not be empty"); 
     Preconditions.checkState(StringUtils.isNotEmpty(pemPublic), "pemPublic must not be empty"); 
     Preconditions.checkState(StringUtils.isNotEmpty(alias), "alias must not be empty"); 

     String pkcsFilename = filename + ".pkcs"; 
     convertPemToPkcs(pemPrivate, pemPublic, pkcsFilename); 

     importPkcsIntoJks(pkcsFilename); 

     return this; 
    } 

    private void importPkcsIntoJks(String pkcsFilename) throws Exception 
    { 
     KeyStore pkcs = KeyStore.getInstance("PKCS12"); 
     File pkcsFile = new File(pkcsFilename); 
     try (FileInputStream fis = new FileInputStream(pkcsFile)) 
     { 
      pkcs.load(fis, password.toCharArray()); 
     } 
     pkcsFile.delete(); 

     KeyStore jks = KeyStore.getInstance("JKS"); 
     jks.load(null); 

     Enumeration<String> aliases = pkcs.aliases(); 
     while (aliases.hasMoreElements()) 
     { 
      String alias = aliases.nextElement(); 
      if (!pkcs.isKeyEntry(alias)) 
      { 
       continue; 
      } 
      Key key = pkcs.getKey(alias, password.toCharArray()); 
      Certificate[] chain = pkcs.getCertificateChain(alias); 

      jks.setKeyEntry(alias, key, password.toCharArray(), chain); 
     } 

     persist(jks); 
    } 

    private void convertPemToPkcs(String pemPrivate, String pemPublic, String pkcsFilename) throws IOException, NoSuchAlgorithmException, OperatorCreationException, PKCSException, FileNotFoundException 
    { 
     Security.addProvider(new BouncyCastleProvider()); 

     X509CertificateHolder cert = (X509CertificateHolder) readObject(pemPublic); 
     PEMKeyPair keyPair = (PEMKeyPair) readObject(pemPrivate); 

     JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils(); 
     PKCS12SafeBagBuilder pkcs12BagBuilder = new PKCS12SafeBagBuilder(cert); 
     pkcs12BagBuilder.addBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName, new DERBMPString("Kafka SSL Certificate")); 
     pkcs12BagBuilder.addBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_localKeyId, extUtils.createSubjectKeyIdentifier(keyPair.getPublicKeyInfo())); 

     PKCS12PfxPduBuilder builder = new PKCS12PfxPduBuilder(); 

     builder.addData(pkcs12BagBuilder.build()); 

     builder.addEncryptedData(new JcePKCSPBEOutputEncryptorBuilder(PKCSObjectIdentifiers.pbeWithSHAAnd128BitRC2_CBC).setProvider("BC").build(password.toCharArray()), pkcs12BagBuilder.build()); 

     PKCS12PfxPdu pfx = builder.build(new JcePKCS12MacCalculatorBuilder(NISTObjectIdentifiers.id_sha256), password.toCharArray()); 

     try (FileOutputStream fos = new FileOutputStream(new File(pkcsFilename))) 
     { 
      fos.write(pfx.getEncoded(ASN1Encoding.DL)); 
     } 
    } 

和繁榮它

pkcs.load(fis, password.toCharArray()); 

炸燬正如你所看到的,BouncyCastleProvider被明確添加。有什麼建議麼?

更新:感謝dave_thompson_085的建議。不能相信我沒有看到重載方法,但解決方案是在調用get Keystore.getInstance(「PKCS12」,「BC」)中指定提供程序。

+0

互聯網搜索顯示[此錯誤](https://bugs.openjdk.java.net/browse/JDK-8013493)可能有關。此外,我沒有在任何地方看到Bouncy Castle提供商,也許這會有所幫助? –

+0

編輯一些代碼來重放問題會很有幫助。 –

+1

添加BC提供程序不會優先考慮;您的堆棧跟蹤確認您正在獲取SunJSSE提供程序的實現。嘗試使用'KeyStore.getInstance(「PKCS12」,「BC」)'或者如果您想要危險地生活**將BC提供程序插入到位置4或位置4以下。或者只需使用SHA1在PKCS12上執行PB-MAC像所有其他人一樣 - 您已經在使用PBE。另外它看起來像我強烈加密證書 - 爲什麼? –

回答

0

as dave_thompson_085指出,我可以指定我想用於密鑰庫的提供者。我沒有意識到這一點,因爲我錯過了getInstance()重載。

因此,在總結,調用這個固定我的問題:

KeyStore.getInstance("PKCS12","BC")

太容易了。