PKCS#12:DerInputStream.getLength() 异常

Posted

技术标签:

【中文标题】PKCS#12:DerInputStream.getLength() 异常【英文标题】:PKCS#12 : DerInputStream.getLength() exception 【发布时间】:2011-11-15 23:34:53 【问题描述】:

我使用 keytool 命令生成证书:

keytool -genkeypair -alias myRSAKey -keyalg RSA -keysize 1024 -keystore test.p12 -storepass test -storetype pkcs12

然后,如果我尝试使用 java 安全 API 加载它,在将文件作为 byte[] 获取后:

KeyStore ks = KeyStore.getInstance("PKCS12");
try
   ks.load(new ByteArrayInputStream(data), "test".toCharArray())
 catch (Exception e)
   ...

我得到一个 DerInputStream.getLength(): lengthTag=127, too big exception。

怎么了?

【问题讨论】:

【参考方案1】:

此错误有多种原因...日志可能真的很混乱。

一个主要原因可能是 Maven 过滤。 根据maven official documentation 警告:不要过滤带有二进制内容的文件,如图像!这很可能会导致输出损坏。 我们的 .jks 在打包阶段被 maven 破坏了。

This thread 帮我弄明白了。

我们可以在相关的 pom.xml 中直接排除一些目录或文件扩展名的过滤:

       <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <version>$maven-resources-plugin.version</version>
            <configuration>
                <nonFilteredFileExtensions>
                    <nonFilteredFileExtension>jks</nonFilteredFileExtension>
                    <nonFilteredFileExtension>p12</nonFilteredFileExtension>
                </nonFilteredFileExtensions>
            </configuration>
        </plugin>

【讨论】:

【参考方案2】:

这发生在我身上,因为以下命令:

openssl pkcs12 -export -in import.pem -inkey myhost.key.pem -name shared &gt; server.p12(来自https://docs.oracle.com/en/database/other-databases/nosql-database/12.2.4.5/security/import-key-pair-java-keystore.html

生成了格式错误的 pkcs12 文件。使用以下方法更正了问题:

openssl pkcs12 -export -in import.pem -inkey myhost.key.pem -name shared -out server.p12

【讨论】:

【参考方案3】:

确保 inputstream 变量的范围仅适用于您声明它的方法,而不是静态/类变量。这样可以避免这种异常。 原因:第一次加载证书或数据后,输入流没有被关闭,而它被声明为类变量。所以让它只对方法可用。

【讨论】:

【参考方案4】:

我的问题 (lengthTag=109, too big) 是 .p12 文件实际上是 JKS 格式而不是 PKCS # 12 格式。有人重命名了文件扩展名。通过以正确的 PKCS 格式重新生成解决了该问题。

java.io.IOException: DerInputStream.getLength(): lengthTag=109, too big.
    at sun.security.util.DerInputStream.getLength(DerInputStream.java:599)
    at sun.security.util.DerValue.init(DerValue.java:365)
    at sun.security.util.DerValue.<init>(DerValue.java:320)
    at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1914)
    at java.security.KeyStore.load(KeyStore.java:1445)

要检查安全文件的格式,可以使用KeyStore Explorer 打开文件。左下栏显示实际格式。

【讨论】:

【参考方案5】:

androidX 迁移并使用新的测试框架后,我在 Android Studio 中发生了这种情况。即使删除现有的~/.android/debug.keystore 对我来说也失败了

解决方案是手动重新生成它(接受所有问题为空并在最后一个回答是)

$ keytool -genkey -v -keystore debug.keystore -storepass android -alias androiddebugkey -keypass android -keyalg RSA -keysize 2048 -validity 10000

然后复制它

$ rm ~/.android/debug.keystore
$ cp debug.keystore ~/.android/debug.keystore

【讨论】:

【参考方案6】:

这发生在我身上,因为我在我的 Windows 10 机器上本地复制并粘贴了 .p12 文件。不知道如何/为什么这是一个问题,但是当我克隆一个包含 .p12 文件的项目并将我的代码指向它们时,这些文件可以工作。但是,将 Windows 文件资源管理器中的文件复制并粘贴到硬盘上的其他位置会导致此错误!!!!

【讨论】:

【参考方案7】:

我遇到了同样的问题。

我的解决方案是在下面的行中用 jceks 替换 PKCS12,因为我显然使用了错误的类型。

KeyStore clientStore = KeyStore.getInstance("PKCS12");

【讨论】:

【参考方案8】:

在代码中指定证书的类型 例如:

System.setProperty("javax.net.ssl.trustStoreType", "jks");
System.setProperty("javax.net.ssl.keyStoreType", "pkcs12"); 

【讨论】:

【参考方案9】:

对于其他有类似问题的人:

"keystore load: DerInputStream.getLength(): lengthTag=109, too big."

对我来说,解决方案是删除参数:-storetype pkcs12 因为标准类型是 jks

【讨论】:

【参考方案10】:

可能您创建的证书末尾有一个额外的字符,被误解为另一个证书。 最后使用一个或多个空行。

参考:Java Certificate Parsing

【讨论】:

是的,我已经检查过了,因为我在 x509 证书上遇到了类似的错误,但事实并非如此。感谢您的回答,我会 +1,因为这可能是问题所在。 链接好像失效了。 @AniketThakur:我修复了链接。您现在可以参考。 Java 7+ 已修复此问题。【参考方案11】:

我遇到了这个问题,我搜索了谷歌的深度,仍然找不到答案。经过几天与质量糟糕的遗留代码作斗争后,我发现了导致此错误的原因。

KeyStore.load(InputStream is, String pass);

这个方法接受一个I​​nputStream,如果这个InputStream有任何问题,就会抛出这个异常,我遇到的一些问题:

InputStream 指向错误/空白/刚刚创建的文件 InputStream 已经打开或其他东西正在持有资源 InputStream已经被使用并读取,因此InputStream的下一个字节的位置是结束

最后一个是我的问题的原因。该代码从证书创建一个 InputStream,并在两个 KeyStore.load() 调用中继续使用它,第一个成功,第二个总是给我这个错误。

【讨论】:

谢谢。错误消息确实具有误导性。在我的情况下,data(密钥)是一个空字节数组,导致了这个错误。而这一切都是因为我重用了输入流。 您指出的第一个原因是 IMO 最常见的原因:通常是错误的文件。即,当我尝试使用带有KeyStore.getInstance("PKCS12") 或反转:)JKS 密钥库文件时,有时会发生这种情况。【参考方案12】:

你做错了什么。 我试过你的命令,然后加载 p12 就好了。 以下代码有效:

 FileInputStream fin = new FileInputStream("..\\test.p12");
 KeyStore ks = KeyStore.getInstance("PKCS12");
 ks.load(fin, "123456".toCharArray());
 System.out.println(ks.getCertificate("myrsakey"));

我想知道您是否按原样输入命令,您会从 keytool 收到一个错误,即密码必须至少为 6 个字符。 你没有得到那个错误?你用的是什么版本的java? 注意:如果您需要创建证书,也可以查看此工具。http://sourceforge.net/projects/certhelper/

【讨论】:

以上是关于PKCS#12:DerInputStream.getLength() 异常的主要内容,如果未能解决你的问题,请参考以下文章

PKCS12 到 JKS 转换失败

PKCS#12:DerInputStream.getLength() 异常

如何使用 keytool 列出存储在 PKCS12 密钥库中的证书?

从 PFX (PKCS #12) 文件创建 RSA 私钥

如何使用 keytool 在 PKCS12 密钥库中创建证书?

bash 脚本中带有 PKCS#12 证书的 cURL