由于通过_asn1_ordering_set_of重新排序而导致签名验证失败

时间:2015-05-12 14:14:20

标签: ssl x509certificate x509 gnutls

我正在使用GnuTLS 3.4.1。我有一个带有一系列序列的x509证书。证书以这种方式存储在智能卡上。

GnuTLS正在通过函数WITH RunningTotal AS ( SELECT Id, ListItem, SUM(ListItem) OVER (ORDER BY Id) AS RT FROM @Table) SELECT Id, ListItem, RT, CASE WHEN RT > 100 THEN RT % 50 + 50 ELSE RT END AS NewRT FROM RunningTotal 重新排列序列,这似乎导致验证失败。

这里的序列是什么样的:

_asn1_ordering_set_of

OpenSSL(可能还有Java PKCS11提供程序)按原样加载此构造。 证书加载的GnuTLS在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' 中对此构造进行排序。所以它变成了:

_asn1_ordering_set_of

为什么GnuTLS会对序列集进行排序?它应该以什么方式完成,是GnuTLS错误还是其他库只是省略了排序?

2 个答案:

答案 0 :(得分:2)

RFC5280有:

  

4.1。基本证书字段

     

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

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

它看起来似乎正在尝试编码一个专有名称,但是它做错了。它根据ASN1有效,因为规范真的很奇怪。每个零件可以有多个值。但是你想要CN,SN等各自的SET,所以那些SEQUENCE应该有自己的SET。

答案 1 :(得分:1)

  

应该采取什么方式......

国际电联建议使用BER对SET进行编码,只要不需要CER或DER即可。我能说的最好,没有必要。有关ITU和ASN.1领域的更详细说明,请参见下文。

然而 ,GnuTLS可能正在遵守创造需求的标准。在这种情况下,我不知道它是哪个标准。见Kurt的回答。

我看了RFC 5280, PKIX Certificate and CRL Profile,但我找不到限制。也许它在另一个PKIX文档中。

  

是GnuTLS错误还是其他库只是省略了排序?

我不相信它是GnuTLS 本身的错误。这就是图书馆做事的方式。以RFC或其他标准的形式提出这个模块的要求。

另请注意,其他库不会省略排序。他们使用证书中显示属性的顺序, 订购:)

  

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

这对我来说听起来像个错误(模数标准要求)。在这种情况下,错误是在签署TBS /证书后重新排序SET OF。

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

  

(评论)GnuTLS是否根据DER规则以正确的顺序放置SET OF类型的元素

ASN.1 encoding rules, X.690, BER/CER/DER中:

  

8.12一组值的编码
  ...
  8.12.3编码和后续解码不需要保留数据值的顺序。

SET OF似乎没有被排序(例如,词典顺序),因此发送者可以按任何顺序放置它们,接收者可以重新排序它们。

然而,11.6说:

  

11 CER和DER使用的BER限制   ...
  11.6组件组件
  一组值的分量值的编码应按升序出现,编码作为八位字符串进行比较,较短的分量在其尾端用0-八位字节填充。   注 - 填充八位字节仅用于比较目的,不会出现在编码中。

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

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

  

简介
  ...
  ...如果编码包含设定值或设定值,则基本编码规则比规范或区分编码规则更合适,并且不需要规范和区分编码规则强加的限制......

因此,引言建议SET为SET OF。

但总的来说:证书是BER。这就是签名的方式。由于证书数据的签名,GnuTLS一旦获得证书就无法更改。

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

  

(评论)gnutls_certificate_set_x509_key_file(xcred, CERT_URL, KEY_URL, GNUTLS_X509_FMT_PEM);

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

显然,_asn1_ordering_set_of过去没有按预期工作。它在2014年4月得到了改进。请参阅GnuTLS邮件列表中的PATCH 1/3: Make _asn1_ordering_set_of() really sort(和朋友)。

以下是来源中的点击次数:

$ 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_der_codingasn1_der_coding在其他组件中使用频率更高......

  

(评论)但我不确定它是GNUTls中的错误而不是服务器端的错误,所以我想在做任何事情之前找出它应该如何工作

您可能应该与B.3 Bug Reports详细说明的GnuTLS人员联系。它看起来像处理非GnuTLS证书时的错误。

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

他们的测试套件可能会错过它,因为GnuTLS DER编码SET OF。他们可能不知道它的发生。