【问题标题】:Need help understanding org.bouncycastle.asn1.ASN1InputStream "java.io.IOException: DER length more than 4 bytes: 63"需要帮助理解 org.bouncycastle.asn1.ASN1InputStream "java.io.IOException: DER length more than 4 bytes: 63"
【发布时间】:2016-03-22 00:01:33
【问题描述】:

我正在开发 ASN.1 加密文件的解码器,并得到 ​​p>

java.io.IOException: DER length more than 4 bytes: 63

我想了解为什么充气城堡会抛出这个异常。

如果有人能给我他们的 2 美分,将不胜感激!

代码片段

ASN1InputStream bIn = null;
    try {
        byte[] bFile = encoded;
        InputStream input = new ByteArrayInputStream(bFile);
        bIn = new ASN1InputStream(input);

        Object temp = null;
        // logger.info("Decoding and emitting file : ");
        System.out.println("Decoding and emitting file : ");

        while ((temp = bIn.readObject()) != null){
            if (temp instanceof DERTaggedObject) {

                DERTaggedObject octs = (DERTaggedObject) temp;

                ASN1Set instance = ASN1Set.getInstance(octs, false);

错误被抛出

bIn.readObject()

我已经跟踪到 ASN1InputStream 类 readLength() 方法的异常。 http://www.docjar.org/html/api/org/bouncycastle/asn1/ASN1InputStream.java.html

static int readLength(InputStream s, int limit)
  283           throws IOException
  284       {
  285           int length = s.read();
  286           if (length < 0)
  287           {
  288               throw new EOFException("EOF found when length expected");
  289           }
  290   
  291           if (length == 0x80)
  292           {
  293               return -1;      // indefinite-length encoding
  294           }
  295   
  296           if (length > 127)
  297           {
  298               int size = length & 0x7f;
  299   
  300               if (size > 4)
  301               {
  302                   throw new IOException("DER length more than 4 bytes");
  303               }
  304   
  305               length = 0;
  306               for (int i = 0; i < size; i++)
  307               {
  308                   int next = s.read();
  309   
  310                   if (next < 0)
  311                   {
  312                       throw new EOFException("EOF found reading length");
  313                   }
  314   
  315                   length = (length << 8) + next;
  316               }
  317   
  318               if (length < 0)
  319               {
  320                   throw new IOException("corrupted stream - negative length found");
  321               }
  322   
  323               if (length >= limit)   // after all we must have read at least 1 byte
  324               {
  325                   throw new IOException("corrupted stream - out of bounds length found");
  326               }
  327           }
  328   
  329           return length;
  330       }

非常感谢任何有助于理解为什么抛出此异常的帮助!

谢谢!

【问题讨论】:

  • 代码中的错误或损坏的输入。
  • 代码看起来没问题,所以我怀疑输入数据无效或损坏。
  • 我有没有办法检查输入数据是否无效或损坏?
  • 你能给我们一些关于数据来自哪里的信息,以及预期的格式是什么(即其中应该是什么 ASN.1 结构)。 “ASN.1 加密文件”暗示您可能正在解析解密的输出,在这种情况下,一个明显的可能性是它没有正确解密。或者,也许该文件实际上是 base64 编码或其他东西,而您已经跳过了解码步骤。
  • 感谢您的回复!我试图解码的数据是由 Cisco ASR 5000 机器生成的 PGW-CDR。

标签: java exception bouncycastle asn.1 decoder


【解决方案1】:

您可能会收到此错误,因为您正在传递文件的整个流,因此在编码/解码时,您需要传递字节流的块/部分并进行编码,然后添加到字节数组,最后写入文件.

在您之前的帖子中,我觉得您正在对 CDR 文件进行编码,因此您应该注意记录长度。让我假设您有 n 条不定长度的记录,我们需要对其进行编码。例如,考虑一个 2048 字节的块(您可以考虑超过记录的平均大小),其中至少包含一个或多个记录。

将每条记录的字节流添加到一个 2048 字节的块中,同时添加如果块已满或有一些空间但没有记录可以存储然后添加填充字节(即 0xFF 以便您可以轻松找出数字块)然后传递给ASN1InputStream 以获取DERTaggedObject 然后对流进行编码并将其存储在单独的变量中,并且在对所有内容进行编码后,只需将存储的流写入.dat 或任何文件系统。

您可以参考this link以更好地了解od编码/解码过程

【讨论】:

    【解决方案2】:

    根据“ITU-T Recommendation X.690”也称为“ISO/IEC 8825-1”,BER 长度可以以两种形式编码:

    • 明确的形式在您的源代码中实现。
    • 不定式 - 未涵盖此来源。

    定形

    如果值长度 0x00 到 0x7F),则以 短格式 编码 - 一个字节。

    长度超过 127 的则以 长格式 编码。长度八位字节应由一个初始八位字节和一个或多个后续八位字节组成。 在这种情况下:

    • 第一个字节中的第 8 位(初始八位字节)应该是一个。 (源代码第 296 行)
    • 字节 1 中的位 7 到 1 应编码长度八位字节中的后续八位字节(字节)的数量,即在此字节之后。 (源码第298行获取大小)
    • 值 11111111 (0xFF) 不得用于初始八位字节 - 引入此限制是为了将来可能的扩展。

    在原始 ASN.1 中,我认为长格式 后续八位字节 的大小没有限制,但其他规范可以对其应用自己的规则。

    对于示例 ISO 7816 可以使用最多 5 个字节(包括初始八位字节/字节)的长度。换句话说,初始八位字节值可以是0x810x820x830x84

    如果您想覆盖其他长度尺寸,您可以在第 300 到 303 行排除或更改尺寸检查。在这种情况下,由于int 长度数量限制,需要额外实现值大小解析。将长度更改为 long 类型允许使用最多 8 个后续八位字节(字节)。

    但可能你的输入数据和它的长度不是英尺 ASN.1 BER/DER TLV 编码规则。

    【讨论】:

    • 你错了。 DER 不支持不定长度,只支持确定形式。
    • 不要排除 300 到 303 的行。它的存在是有原因的。如果 LENGTH 八位字节的长度超过 4 个字节,您将无法为 asn.1 节点的内容 (VALUE) 初始化字节数组。看看java中int的限制是什么。在 c# 中 sizeof(int) 是 4 个字节。
    • 除@pepo外,第一个长度字节(长度标识符之后)的第8位必须设置为零,否则长度计算将导致负数(因为int是有符号的,而长度必须是非负数)。
    • 感谢大家注意到数字限制。当然,如果实际需要支持 BER 长度超过 5 个字节,则应该重新实现值大小分辨率。我无法想象使用超过 4 294 967 296 字节的 TLV 数据的原因......
    • 我查了java中的int限制也是4个字节。这可能是个愚蠢的问题,但是为什么我们不能初始化一个字节数组长度超过 4 个字节的 asn.1 节点的字节数组呢?
    猜你喜欢
    • 2020-02-07
    • 2013-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-23
    • 2022-01-15
    • 1970-01-01
    相关资源
    最近更新 更多