首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Ruby中解析ASN1

如何在Ruby中解析ASN1
EN

Stack Overflow用户
提问于 2018-12-18 20:13:56
回答 2查看 697关注 0票数 0

仍然有点与ASN1混淆。我正在用ruby解析RFC3161时间戳响应,所以我知道规范。我很确定结构是正确加载的,但我对如何找到我想要的碎片/键感到困惑。我知道有序列(有序)和集合(无序/唯一)。

我知道我们可以调用asn1_object.value[0].value[0],但是这是笨拙的,我希望如果我知道键或头,我可以像对待JSON或YAML一样对待它,只需要调用 asn1_object['TSTInfo']['serialNumber']它不是这样工作的吗?

我们是否应该使用序列的性质,因为我们也有规格和长度,所以应该按照顺序并知道它们的位置吗?这对我来说很奇怪,但可能是因为我以前没有使用过很多TLV格式。不幸的是,openssl只有很少的文档,只有如何用OpenSSL::ASN1.decode(der)加载对象并按索引访问值。还有traverse方法,但这不会产生标题名称或我认为在本例中使用的任何东西。

代码语言:javascript
复制
                #<OpenSSL::ASN1::Sequence:0x000055fdee1a2c68
                   @indefinite_length=false,
                   @tag=16,
                   @tag_class=:UNIVERSAL,
                   @tagging=nil,
                   @value=
                    [#<OpenSSL::ASN1::ObjectId:0x000055fdee1a2ec0
                      @indefinite_length=false,
                      @tag=6,
                      @tag_class=:UNIVERSAL,
                      @tagging=nil,
                      @value="1.2.840.113549.1.9.52">,
                     #<OpenSSL::ASN1::Set:0x000055fdee1a2c90
                      @indefinite_length=false,
                      @tag=17,
                      @tag_class=:UNIVERSAL,
                      @tagging=nil,
                      @value=
                       [#<OpenSSL::ASN1::Sequence:0x000055fdee1a2cb8
                         @indefinite_length=false,
                         @tag=16,
                         @tag_class=:UNIVERSAL,
                         @tagging=nil,
                         @value=
                        [#<OpenSSL::ASN1::Sequence:0x000055fdee1a2da8
                            @indefinite_length=false,
                            @tag=16,
                            @tag_class=:UNIVERSAL,
                            @tagging=nil,
                            @value=

                   @value=
                    [#<OpenSSL::ASN1::ObjectId:0x000055fdee1a3190
                      @indefinite_length=false,
                      @tag=6,
                      @tag_class=:UNIVERSAL,
                      @tagging=nil,
                      @value="signingTime">,
                     #<OpenSSL::ASN1::Set:0x000055fdee1a30f0
                      @indefinite_length=false,
                      @tag=17,
                      @tag_class=:UNIVERSAL,
                      @tagging=nil,
                      @value=
                       [#<OpenSSL::ASN1::UTCTime:0x000055fdee1a3118
                         @indefinite_length=false,
                         @tag=23,
                         @tag_class=:UNIVERSAL,
                         @tagging=nil,
                         @value=2018-12-19 01:49:08 UTC>]>]>
EN

回答 2

Stack Overflow用户

发布于 2018-12-18 23:35:07

在您链接的示例中,Openssl.ASN1.decode( DER )利用DER的规范性质从有线数据中重构结构,而根本没有使用ASN.1模式。因此,虽然它可以从从有线数据读取的内容中推断出该结构的形状、组成和内容(特别是如果它是用显式标记编码的,这也给出了数据类型),但它不知道原始模式中的字段名会是什么(这些不是有线格式的数据)。

如果您查看RFC3161时间戳的原始ASN.1模式,就可以确定哪些字段在哪里。

使用带有C/C++的ASN.1,Java和C# one通常使用ASN.1编译器生成源代码。此源代码定义包含从架构中获取字段名的字段的类。抱歉,我不知道这在Ruby的Openssl.ASN1中是否可行

隐式/显式.

您提供的示例提供了一个链接,用于使用隐式标记示例进行次要操作。它将值解释为整数;严格地说,应该将其解释为需要解码的更多ASN.1。碰巧的是,这些字节是整数。

票数 0
EN

Stack Overflow用户

发布于 2021-02-09 16:59:25

让我在这里澄清一下,我刚刚发现了一个矛盾。OP说他是knows the specification,但也提到the signingTime value is two below the declarationstrange

这使我得出结论,OP意味着他知道格式是由规范决定的,但实际上并不知道规范本身。

让我们一起读其中的一些,这样你就知道了。

让我们回答为什么有时间价值的问题?

RFC5652第11.3节中提到了签名时间;从这里,我们将知道它是一种属性类型(因为它在第11节下)。第5.3节中的同一文档中也提到了属性类型的结构。

属性::=序列{ attrType对象标识符, attrValues集AttributeValue }

因此,它基本上是一个对象标识符的序列,后面跟着一个集合。

第11.3条还指定集合必须包含确切的一个成员。

这正是我们在这里看到的:

代码语言:javascript
复制
[
  #<OpenSSL::ASN1::ObjectId:0x000055fdee1a3190
    @indefinite_length=false,
    @tag=6,
    @tag_class=:UNIVERSAL,
    @tagging=nil,
    @value="signingTime">,
  #<OpenSSL::ASN1::Set:0x000055fdee1a30f0
    @indefinite_length=false,
    @tag=17,
    @tag_class=:UNIVERSAL,
    @tagging=nil,
    @value=[
      #<OpenSSL::ASN1::UTCTime:0x000055fdee1a3118
        @indefinite_length=false,
        @tag=23,
        @tag_class=:UNIVERSAL,
        @tagging=nil,
        @value=2018-12-19 01:49:08 UTC>
    ]>
]

正如前面提到的,OpenSSL::ASN1.decode将der解码为仅仅结构化的红宝石对象,并且没有考虑到每个字段的含义。因此,您需要阅读规范并自己制定字段。这是乏味的,但绝不可能是不可能的。

由于官方库提供的遍历功能几乎毫无用处,我最终自己实现了它。不过,它仍然只是一个工作的原型。

代码语言:javascript
复制
class TraverseASN1
  class StopIteration < ::StandardError
    def initialize(result = nil)
      super(nil)
      @result = result
    end

    attr_reader :result
  end

  def call(
    decoded,
    _depth: 0,
    _sequence: nil,
    _parents: [],
    &traversal_block
  )
    traversal_block.call(
      decoded,
      depth: _depth,
      sequence: _sequence,
      parents: _parents
    )
    value = decoded.value
    return unless value.is_a?(::Array)
    value.each_with_index do |sub_token, sequence|
      call(
        sub_token,
        _depth: (_depth + 1),
        _sequence: sequence,
        _parents: [*_parents, decoded],
        &traversal_block
      )
    end
  end
end

我就是这样用它的:

代码语言:javascript
复制
target_element = begin
  TraverseASN1.new.call(asn1) do |current, depth:, parents:, **_unused_args|
    next unless depth == 2
    next unless current.is_a?(::OpenSSL::ASN1::ObjectId)
    next unless current.value == 'pkcs7-signedData'
    raise TraverseASN1::StopIteration.new(parents.last)
  end
rescue TraverseASN1::StopIteration => e
  e.result
end

一旦你知道了格式,开始黑客攻击是相当微不足道的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53840379

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档