使用OpenSSL解码ASN.1 DER OCTET STRING

11

使用OpenSSL API,我已经从X.509v3证书中提取了一个自定义扩展:

X509_EXTENSION* ex = X509_get_ext(x509, 4);

X509_EXTENSION对象包含一个值(ex->value),该值是ASN.1 OCTET STRING。OCTET STRING包含一个DER编码的UTF-8字符串。我正在尝试解码OCTET STRING以获取纯UTF-8字符串。

我尝试了一些方法,例如:

ASN1_STRING_to_UTF8(&buf, ex->value);

并且

M_ASN1_OCTET_STRING_print(bio, ex->value);
int len = BIO_read(bio, buf, buf_size);
buf[len] = '\0';

这两者都给了我 DER 编码的字符串。我如何获得纯粹的 UTF-8 字符串?


1
我曾经使用'asn1_get_object'来完成这个任务,遵循openssl代码中的示例(大约在crypto/asn1/asn1_par.c:135附近)。用这种方式解码一个大结构是非常痛苦的,我建议使用其他asn1解析器,如SNACC或libtasn1。 - Francois
1
@Francois:感谢您的提示。由于我不是在尝试解码一个大结构,只是一个单独的字符串,所以ASN1_get_object()可能就足够了。然而,我尝试使用它,基于asn1_par.c中的用法,但无法使其工作。您能否提供一个示例? - Roger Dahl
1
@Francois:我找到了如何使用该函数,并基于此发布了一个答案。再次感谢。 - Roger Dahl
1个回答

8

@Francois向我指出了ASN1_get_object()函数。该函数适用于证书扩展仅包含单个值的情况。

ASN1_get_object()接受一个指向包含DER编码对象的C缓冲区的指针,它返回数据本身(通过调整指针),数据长度,ASN.1标记值和ASN.1对象类。

ASN1_OCTET_STRING* octet_str = X509_EXTENSION_get_data(extension);
const unsigned char* octet_str_data = octet_str->data;
long xlen;
int tag, xclass;
int ret = ASN1_get_object(&octet_str_data, &xlen, &tag, &xclass, octet_str->length);
printf("value: %s\n", octet_str_data);

1
我也在尝试做同样的事情,但是当应用你的解决方案时,我得到的字符串与调用ASN1_get_object函数之前相同。你确定这个函数进行了DER解码吗? - Maggie
1
@Maggie:对于我处理的ASN.1类型“OCTET STRING”,它是有效的。但这可能是因为DER编码对“OCTET STRING”所做的唯一操作就是用头部包装它。字节本身保持不变。ASN1_get_object()确实会删除头部,但也许这就是它所做的全部? - Roger Dahl
2
是的,ASN.1简单类型包括BOOLEANINTEGERBIT STRINGOCTET STRINGNULLOBJECT IDENTIFIERREALENUMERATEDCHARACTER STRING - Roger Dahl
2
看起来你正在寻求一个通用的解决方案,以提取 x509v3 扩展中的信息。正如这个问题的标题所述,它仅涉及解码单个 OCTET STRING 的特殊情况。除此之外,我只能指向 @Francois 的原始建议,即使用外部 ASN.1 解析器,例如 SNACC 或 libtasn1,并查看 OpenSSL 源代码 (around crypto/asn1/asn1_par.c:135)。 - Roger Dahl
4
谢谢链接。野马也无法将我拉回到OpenSSL API :) - Roger Dahl
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接