Java 8 破坏了我使用 PKCS12 的应用程序
Java 8 has broken my application that uses PKCS12
2007 年,我编写了一个小型 java 应用程序,可以对多个不同的 PDF 文档进行数字签名(带有我的签名图像)。在我升级到 Java 8.
之前,我一直工作得很好
我现在遇到错误:
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, '[=12=]');
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();
这是一个堆栈信息:
$ 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)
我做了一些挖掘。该更改似乎是某些 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()
正在检查 DER 值的 "tag" 以确保它没有设置 CONTEXT 位。此测试失败。
似乎解决方法是将这些密钥存储为 DER 值,其标签类型未设置位 0x80
。
另请参阅:
[已解决]
我创建了一个 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 下编译了它,它在这两种环境下都能工作。
谢谢!
2007 年,我编写了一个小型 java 应用程序,可以对多个不同的 PDF 文档进行数字签名(带有我的签名图像)。在我升级到 Java 8.
之前,我一直工作得很好我现在遇到错误:
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, '[=12=]');
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();
这是一个堆栈信息:
$ 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)
我做了一些挖掘。该更改似乎是某些 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()
正在检查 DER 值的 "tag" 以确保它没有设置 CONTEXT 位。此测试失败。
似乎解决方法是将这些密钥存储为 DER 值,其标签类型未设置位 0x80
。
另请参阅:
[已解决]
我创建了一个 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 下编译了它,它在这两种环境下都能工作。
谢谢!