Ssl 由于通过_asn1 _排序_集合_重新排序,签名验证失败

Ssl 由于通过_asn1 _排序_集合_重新排序,签名验证失败,ssl,x509certificate,x509,gnutls,Ssl,X509certificate,X509,Gnutls,我正在使用。我有一个x509证书,里面有一组序列。证书以这种方式存储在智能卡上 GnuTLS正在通过的函数\u asn1\u ordering\u set\u重新排列序列,这似乎导致验证失败 下面是序列的样子: SEQUENCE : ... SET : SEQUENCE : OBJECT_IDENTIFIER : 'CN (2.5.4.3)' PrintableString : '0000' SEQUENCE :

我正在使用。我有一个x509证书,里面有一组序列。证书以这种方式存储在智能卡上

GnuTLS正在通过的函数
\u asn1\u ordering\u set\u重新排列序列,这似乎导致验证失败

下面是序列的样子:

SEQUENCE : 
...
   SET : 
      SEQUENCE : 
         OBJECT_IDENTIFIER : 'CN (2.5.4.3)'
         PrintableString : '0000'
      SEQUENCE : 
         OBJECT_IDENTIFIER : 'SN (2.5.4.4)'
         TeletexString : 'XXX'
      SEQUENCE : 
         OBJECT_IDENTIFIER : 'G (2.5.4.42)'
         TeletexString : 'YYY'
OpenSSL(可能还有Java PKCS11提供程序)按原样加载此构造。 加载证书的GnuTLS在
\u asn1\u ordering\u set\u中对该结构进行排序。使其成为:

SEQUENCE : 
...
   SET : 
      SEQUENCE : 
         OBJECT_IDENTIFIER : 'G (2.5.4.42)'
         TeletexString : 'YYY'
      SEQUENCE : 
         OBJECT_IDENTIFIER : 'SN (2.5.4.4)'
         TeletexString : 'XXX'
      SEQUENCE : 
         OBJECT_IDENTIFIER : 'CN (2.5.4.3)'
         PrintableString : '0000'
为什么GnuTLS对序列集进行排序?应该怎么做,是GnuTLS错误还是其他库忽略了排序

应该怎么做

ITU建议使用BER对一组数据进行编码,只要不需要CER或DER。据我所知,没有必要。有关ITU和ASN.1领域的更详细解释,请参见下文

然而,GNUTL可能遵守了产生需求的标准。在这种情况下,我不知道它是哪个标准。见库尔特的答案

我看了看,但找不到限制。也许它在另一个PKIX文档中


这是GnuTLS错误还是其他库忽略了排序

我不相信这是GnuTLS本身的一个bug。这就是图书馆做事的方式。以RFC或其他标准中的要求为模

还要注意,其他库并没有忽略排序。它们使用属性在证书中显示的顺序,这是一种顺序:)



(评论)问题是GNUTLS重新排列会导致SSL身份验证失败

对我来说,这听起来像个bug(模标准要求)。在这种情况下,在TBS/证书上放置签名后,错误将对集合进行重新排序

如果GnuTLS正在构建TBS/证书,那么可以重新排序,直到签名被放置在其上


(注释)GnuTLS是否根据DER规则以正确的顺序放置了一组类型的元素

在:

8.12一组值的编码

8.12.3编码和后续解码不需要保留数据值的顺序

一组数据似乎没有顺序(例如,字典顺序),因此发送方可以将它们按任意顺序排列,接收方可以对它们重新排序

然而,11.6说:

11 CER和DER对BER的限制

11.6组件组
一组值的分量值的编码应以升序出现,编码作为八位字节字符串进行比较,较短的分量在其尾端用0-8位字节填充。 注意–填充八位字节仅用于比较目的,不会出现在编码中

在上面,他们说BER可以是任何顺序,但CER和DER是升序

最后但并非最不重要的是,引言中说:

引言

... 如果编码包含一个集值或一组值,并且不需要规范编码规则和区分编码规则施加的限制,则基本编码规则比规范编码规则或区分编码规则更合适

因此,导言建议将误码率用于一组数据

但总的来说:证书是错误的。这就是它的签字方式。由于证书数据上的签名,GnuTLS一旦获得证书,就无法改变这一点

GnuTLS可以自由地以DER编码创建证书。他们只是不能在事后强加编码



(注释)
gnutls\u证书集\u x509\u密钥文件(xcred,CERT\u URL,key\u URL,gnutls\u x509\u FMT\u PEM)

我查看了最新的GnuTLS来源。这似乎就是它在
src/serv.c
中的使用方式


显然,
\asn1\u排序\u集合\u在过去并没有像预期的那样工作。2014年4月进行了改进。请参阅GnuTLS邮件列表上的(和朋友)

以下是来源中的点击率:

$ grep -R -n _asn1_ordering_set_of * | grep -v doc
lib/minitasn1/coding.c:832:  /* Function : _asn1_ordering_set_of */
lib/minitasn1/coding.c:843:  _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node)
lib/minitasn1/coding.c:1261:  err = _asn1_ordering_set_of (der + len2, counter - len2, p);
第1261行附近的用法用于
asn1\u der\u编码
<代码>asn1\u der\u编码
在其他组件中使用得更频繁


(评论)但我不确定这是GNUTls中的bug,而不是服务器端的bug,所以我想在做任何事情之前了解一下它应该如何工作

您可能应该联系GnuTLS人员,详见。它看起来像是处理非GnuTLS证书时的一个bug

明确地说,GnuTLS在创建证书时使用DER,这很好。但是GnuTLS在收到非GnuTLS证书后不能强制执行排序,因为这会使签名无效

他们的测试套件可能遗漏了它,因为GnuTLS-DER对一组数据进行了编码。他们可能没有意识到它的发生。

RFC5280有:

4.1。基本证书字段

X.509 v3证书的基本语法如下所示。供签署 计算时,将要签名的数据使用ASN.1进行编码 可分辨编码规则(DER)[X.690]

所以在我看来,GnuTLS做的事情是正确的


它看起来还试图对一个可分辨名称进行编码,但这是错误的。根据ASN1,它是有效的,因为规范真的很奇怪。每个零件可以有多个值。但是您希望CN、SN等都在自己的集合中,因此所有这些序列都应该有自己的集合。

问题是GNUTLS重新排列会导致SSL身份验证失败。所以问题是GNUTls是对的,它“根据DER规则将一组类型的元素按正确的顺序排列”,或者序列没有这样的规则,它是自动执行的。@elevener-这听起来像个bug。以防万一,您应该在验证过程中展示一些代码。您还可以将该事实添加到您的问题中