我试图了解如何处理具有特定于应用程序内容的ASN.1类型的解析。给出一个相当简单的模式:
World-Schema DEFINITIONS AUTOMATIC TAGS ::=
BEGIN
Rocket ::= SEQUENCE
{
name IA5String,
type IA5String
}
END
和数据:
value Rocket ::= {
name "Falcon",
type "Boo"
}
(我使用http://asn1-playground.oss.com/来生成序列化的DER数据)。
我可以使用d2i函数获得外部容器:
ASN1_SEQUENCE_ANY * container = d2i_ASN1_SEQUENCE_ANY(0, (const unsigned char**)&ptr, (long)len);
ASN1_TYPE * el = sk_ASN1_TYPE_value(container, 0);
该el
的类型为-3,即V_ASN1_OTHER
,这对我的架构是正确的。但是,我想尽一切办法使用ASN.1 API钻研IA5Strings内容。我相信内容在el->value.asn1_value
中,但是我不应该直接访问它(类型对我来说是不透明的),我只考虑https://www.openssl.org/docs/man1.1.0/crypto/中的函数。是否还有任何文档说明应如何做?
答案 0 :(得分:1)
关于ASN.1功能,OpenSSL文档非常有限。了解它的最佳方法是检查相关的公共头文件asn1.h
和asn1t.h
。它们定义了一组宏,这些宏使您可以创建自己的ASN.1类型。同样,查看源代码是了解如何使用它们的最佳方法,例如在ts_asn1.c
中。 ASN1_ITEM()中提供了基本说明。玩得开心!
幸运的是,您的示例Rocket
类型很简单。可以创建具有辅助功能的ASN.1类型定义:
/* Rocket.h */
#include <openssl/asn1.h>
typedef struct Rocket_st {
ASN1_IA5STRING *name;
ASN1_IA5STRING *type;
} ROCKET;
DECLARE_ASN1_FUNCTIONS(ROCKET)
该结构是手工编码的,DECLARE_ASN1_FUNCTIONS
宏扩展为一组帮助函数,可以通过以下方式实现:
/* Rocket.c */
#include "Rocket.h"
#include <openssl/asn1t.h>
ASN1_SEQUENCE(ROCKET) = {
ASN1_SIMPLE(ROCKET, name, ASN1_IA5STRING),
ASN1_SIMPLE(ROCKET, type, ASN1_IA5STRING),
} ASN1_SEQUENCE_END(ROCKET)
IMPLEMENT_ASN1_FUNCTIONS(ROCKET)
编译后,符号表如下所示(我使用的是Mac):
$ objdump -t Rocket.o
Rocket.o: file format Mach-O 64-bit x86-64
SYMBOL TABLE:
00000000000000d0 l __DATA,__const _ROCKET_seq_tt
00000000000000a0 g F __TEXT,__text _ROCKET_free
0000000000000120 g __DATA,__const _ROCKET_it
0000000000000080 g F __TEXT,__text _ROCKET_new
0000000000000000 g F __TEXT,__text _d2i_ROCKET
0000000000000040 g F __TEXT,__text _i2d_ROCKET
0000000000000000 *UND* _ASN1_IA5STRING_it
0000000000000000 *UND* _ASN1_item_d2i
0000000000000000 *UND* _ASN1_item_free
0000000000000000 *UND* _ASN1_item_i2d
0000000000000000 *UND* _ASN1_item_new
未定义的符号由OpenSSL crypto
库提供。您可以将名称中带有ROCKET
的函数用于C结构化数据和DER序列化数据之间的来回转换。有关d2i
和i2d
函数的更多信息,可以在称为d2i_X509
的OpenSSL文档页面中找到。您的应用程序代码可能类似于以下内容:
ROCKET *rocket;
ROCKET *rocket2;
unsigned char *rocketString;
const unsigned char *ptr;
int len;
rocket = ROCKET_new();
rocket->name = ASN1_IA5STRING_new();
ASN1_STRING_set(rocket->name, "Falcon", -1);
rocket->type = ASN1_IA5STRING_new();
ASN1_STRING_set(rocket->type, "Boo", -1);
len = i2d_ROCKET(rocket, &rocketString);
printf("DER-encoded Rocket has length %d\n", len);
ptr = rocketString;
rocket2 = d2i_ROCKET(NULL, &ptr, len);
printf("rocket2 fields are:\n name = \"%s\"\n type = \"%s\"\n",
ASN1_STRING_get0_data(rocket2->name),
ASN1_STRING_get0_data(rocket2->type));
结果:
$ ./main
DER-encoded Rocket has length 15
rocket2 fields are:
name = "Falcon"
type = "Boo"