2017-04-23 67 views
1

2007年,我編寫了一個小型的Java應用程序,它可以數字簽名幾個不同的PDF文檔(帶有我的簽名圖像)。我一直在努力,直到大我升級到Java 8Java 8打破了我使用PKCS12的應用程序

現在我得到的錯誤:

IOException: Unable to read private key from keystore 
e: java.io.IOException: unsupported PKCS12 secret value type 48 

我看來,現在的Java 8 PKCS12不能存儲密鑰的條目。這對我來說是一個關鍵的應用程序。我每天使用它數百次。

我該如何解決這個問題?

下面是關鍵代碼的刪節版:

String appPath = SignPDF.class.getProtectionDomain().getCodeSource().getLocation().getPath(); 

String keytype = "pkcs12"; 
String keyfile = appPath + "DanVokt.pfx"; 
String keyimage = appPath + "DanVokt.png"; 
String keypass = "xxxxxxxxx"; 

KeyStore ks = KeyStore.getInstance(keytype); 
ks.load(new FileInputStream(keyfile), keypass.toCharArray()); 
String alias = (String)ks.aliases().nextElement(); 
PrivateKey key = (PrivateKey)ks.getKey(alias, keypass.toCharArray()); 
Certificate[] chain = ks.getCertificateChain(alias); 

PdfReader reader = new PdfReader(ifile); 
FileOutputStream fout = new FileOutputStream(ofile); 

PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0'); 
PdfSignatureAppearance sap = stp.getSignatureAppearance(); 
sap.setCrypto(key, chain, null, PdfSignatureAppearance.SELF_SIGNED); 

// allow only printing 
stp.setEncryption(null, keypass.getBytes(), PdfWriter.ALLOW_PRINTING, 
        PdfWriter.STANDARD_ENCRYPTION_128); 
stp.close(); 

這裏是一個堆棧TACE:

$ signpdf "Timelog*" 1 
Processing File: "Timelog - Current Week.pdf" 1 
IOException: Unable to read private key from keystore 
java.io.IOException: unsupported PKCS12 secret value type 48 
    at sun.security.pkcs12.PKCS12KeyStore.loadSafeContents(PKCS12KeyStore.java:2197) 
    at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:2025) 
    at java.security.KeyStore.load(KeyStore.java:1445) 
    at SignPDF.main(SignPDF.java:61) 

這裏是版本和構建:

$ java -version 
java version "1.8.0_131" 
Java(TM) SE Runtime Environment (build 1.8.0_131-b11) 
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode) 

嘗試使用keytool查看PKCS12(.pfx)文件:

$ keytool -list -keystore DanVokt.pfx -storepass XXXXXXXX -storetype PKCS12 -v 
keytool error: java.io.IOException: unsupported PKCS12 secret value type 48 
java.io.IOException: unsupported PKCS12 secret value type 48 
    at sun.security.pkcs12.PKCS12KeyStore.loadSafeContents(PKCS12KeyStore.java:2197) 
    at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:2025) 
    at java.security.KeyStore.load(KeyStore.java:1445) 
    at sun.security.tools.keytool.Main.doCommands(Main.java:795) 
    at sun.security.tools.keytool.Main.run(Main.java:343) 
    at sun.security.tools.keytool.Main.main(Main.java:336) 
+0

請包括例外的完整堆棧跟蹤。它將幫助我們弄清楚發生了什麼。另外,請提供您用於運行代碼的JRE的Java版本/內部版本號。 –

+0

在尋找修復程序時,只能爲此安裝較舊版本的Java。 –

回答

0

[解決]

我創建的Java密鑰庫(JKS)文件:

keytool -genkey -keyalg RSA -keysize 2048 -keystore danv_keystore.jks -alias danv 

當然,這創建了一個新的私鑰和新的證書,但目前這不是一個問題,因爲它是自簽名的。我對如何使用我自己的私鑰和證書感到困惑。任何例子?

然後,我只是改變關鍵字類型和密鑰文件:

//  String keytype = "pkcs12"; 
     String keytype = "JKS"; 
//  String keyfile = appPath + "DanVokt.pfx"; 
     String keyfile = appPath + "danv_keystore.jks"; 

瞧!它現在正在工作。

我在J8和J7下編譯它,它可以在兩種環境下工作。

謝謝!

1

我做了一些挖掘。這些更改似乎是作爲某些Keystore API增強功能的一部分發生的。 (他們在2013年1月分別committed

具體的測試是這樣的:

 } else if (bagId.equals((Object)SecretBag_OID)) { 
      DerInputStream ss = new DerInputStream(bagValue.toByteArray()); 
      DerValue[] secretValues = ss.getSequence(2); 
      ObjectIdentifier secretId = secretValues[0].getOID(); 
      if (!secretValues[1].isContextSpecific((byte)0)) { 
       throw new IOException(
        "unsupported PKCS12 secret value type " 
            + secretValues[1].tag); 
      } 

其中!(isContextSpecific()正在檢查的DERvalue的「標籤」,以確保它沒有上下文位設置。這個測試失敗了。

看起來解決方法是將這些密鑰存儲爲DER值,且標記類型沒有設置位0x80

參見:

相關問題