Openssl 读一篇「;“其他名称”;来自“a”的值;subjectAltName“;证书扩展

Openssl 读一篇「;“其他名称”;来自“a”的值;subjectAltName“;证书扩展,openssl,Openssl,看起来OpenSSL总是显示subjectAltName为“otherName”的“unsupported” 写入的字符串(通过M2Crypto和通过openssl.cnf直接在命令行中写入): 转储(openssl x509-in-test.crt-noout-text): c3:88:36:93:82:58:0c:08:7f 指数:65537(0x100001) X509v3扩展: X509v3受试者备选名称: 其他名称: 签名算法:Sha1WithRSA加密 05:76:d5:fc:d0:

看起来OpenSSL总是显示subjectAltName为“otherName”的“unsupported”

写入的字符串(通过M2Crypto和通过openssl.cnf直接在命令行中写入):

转储(openssl x509-in-test.crt-noout-text):

c3:88:36:93:82:58:0c:08:7f
指数:65537(0x100001)
X509v3扩展:
X509v3受试者备选名称:
其他名称:
签名算法:Sha1WithRSA加密
05:76:d5:fc:d0:44:50:af:39:76:05:b4:cb:b6:99:9f:7c:c0:
在OpenSSL源代码中搜索“otherName”,这在我看来很突出(在v3_alt.c中):

1:

STACK_OF(CONF_VALUE)*i2v_GENERAL_NAME(X509V3_EXT_METHOD*方法,
一般名称*gen,堆栈(配置值)*ret)
{
无符号字符*p;
煤油烯[256],htmp[5];
int i;
开关(发电机->类型)
{
案例GEN_其他名称:
X509V3_添加_值(“其他名称”、“其他名称”和“&ret”);
打破
案例GEN_X400:
X509V3_添加_值(“X400Name”、“”“和ret”);
打破
案件一方:
X509V3_添加_值(“ePartyName”、“”、&ret);
打破
2:

int-GENERAL\u-NAME\u-print(BIO*out,GENERAL\u-NAME*gen)
{
无符号字符*p;
int i;
开关(发电机->类型)
{
案例GEN_其他名称:
BIO_printf(输出,“其他名称:”);
打破
案例GEN_X400:
BIO_printf(输出,X400Name:);
打破
案件一方:
/*也许可以解决这个问题:现在支持它*/
BIO_printf(输出,“ePartyName:”);
打破

所以,我敢打赌,这一点和我在上述尝试中获得的经验知识都意味着,我不应该期望“其他名称”值将通过命令行或库调用正确呈现。这可能是因为它们是实际的、编码为ASN.1的字符串。那么,我该怎么做?人们如何提取这些值?如果它们是实际的ASN.1字符串,是否由开发人员对其进行解码?

确实,命令行实用程序不支持subjectAlternateName(SAN)以一种有意义的方式。但该库确实支持通过编程工作访问这些值

在我回答你的具体问题之前,请看一下Zakir Durumeric的文章。这篇文章提供了一些有用的提示

下面是我在Linux/OpenSSL 1.0.1h上测试的完整程序。它演示了如何访问SAN中的用户原则名称(UPN)。UPN的OID是1.3.6.1.4.1.311.20.2.3。如果需要查找其他OID,请按照下面的演示,将自己的调用添加到OBJ_create

#包括
#包括
#包括
#包括
静态常量无符号字符测试证书[]={
/*DER格式证书的十六进制字节*/
};
int main(){
/*在本例中,我们正在查找Microsoft UPN,它已存在
*在X.509v3中,证书适用于基于证书的身份验证。
*/
int upn_nid=OBJ_create(“1.3.6.1.4.1.311.20.2.3”、“upn”、“userPrincipleName”);
const unsigned char*in=测试证书编号;
X509*证书=d2i_X509(空,&in,sizeof(测试证书));
如果(证书==NULL){
printf(“错误\n”);
返回1;
}
int version=((int)X509_get_version(cert))+1;
如果(版本<3){
printf(“不是版本3或更高版本的证书。\n”);
返回1;
}
/*现在,我们可以看看这些扩展。它们已经被解析为一个内部
*format,调用d2i_X509()的结果。我们只需要循环遍历它们,
*在找桑。
*/
X509_分机*分机;
int next=X509获取外部计数(证书);
int i;
对于(i=0;iobject)=NID_subject_alt_name){
/*好的,我们找到了SAN。现在将其值解析为一组通用名称。
*/
in=ext->value->data;
常规名称*NAMES=d2i\U常规名称(空、中、外->值->长度);
如果(名称==NULL){
printf(“未找到通用名称”);
继续;
}
int nbr_of_NAME=sk_GENERAL_NAME_num(名称);
int j,nid;
char*astr;
对于(j=0;jtype){
案例GEN_其他名称:
/*这是UPN吗*/
nid=OBJ_obj2nid(当前_名称->d.otherName->类型_id);
如果(nid==upn\U nid){
astr=(char*)ASN1\u字符串\u数据(当前\u名称->d.otherName->
值->值.asn1_字符串);
}否则{
/*TODO:在此处添加对其他OID的支持*/
astr=“GEN_OTHERNAME”;
}
打破
case GEN_电子邮件:
astr=(char*)ASN1_STRING_数据(当前名称->d.rfc822Name);
打破
案例GEN_DNS:
astr=(char*)ASN1_字符串_数据(当前名称->d.dNSName);
打破
案例GEN_X400:
/*TODO:在此处添加对X400名称的支持*/
astr=“GEN_X400”;
打破
案例GEN_DIRNAME:
/*TODO:在此处添加对目录名的支持*/
astr=“GEN_DIRNAME”;
打破
案件一方:
/*TODO:在此处添加对EDI参与方名称的支持*/
astr=“GEN_EDIPARTY”;
打破
案例genu_URI:
astr=(char*)ASN1_字符串_数据(当前名称->d.uniformResourceIdentifier);
打破
ca
1.2.3.4;UTF8:some other identifier
                c3:88:36:93:82:58:0c:08:7f
            Exponent: 65537 (0x10001)
    X509v3 extensions:
        X509v3 Subject Alternative Name: 
            othername:<unsupported>
Signature Algorithm: sha1WithRSAEncryption
    05:76:d5:fc:d0:44:50:af:39:76:05:b4:cb:b6:99:9f:7c:c0:
STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
                GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret)
{
    unsigned char *p;
    char oline[256], htmp[5];
    int i;
    switch (gen->type)
    {
        case GEN_OTHERNAME:
        X509V3_add_value("othername","<unsupported>", &ret);
        break;

        case GEN_X400:
        X509V3_add_value("X400Name","<unsupported>", &ret);
        break;

        case GEN_EDIPARTY:
        X509V3_add_value("EdiPartyName","<unsupported>", &ret);
        break;
int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
{
    unsigned char *p;
    int i;
    switch (gen->type)
    {
        case GEN_OTHERNAME:
        BIO_printf(out, "othername:<unsupported>");
        break;

        case GEN_X400:
        BIO_printf(out, "X400Name:<unsupported>");
        break;

        case GEN_EDIPARTY:
        /* Maybe fix this: it is supported now */
        BIO_printf(out, "EdiPartyName:<unsupported>");
        break;