从 X.509 v3 扩展解析的额外字符

Extra characters parsed from X.509 v3 extensions

我正在尝试使用 OpenSSL v1.1.1 创建一些证书,它将在其中保存一些特定数据,作为 v3 扩展字段。我正在使用一个简单的 bash 脚本,它将自动执行所有这些操作:

#!/bin/bash

set -e

openssl genrsa -out client.key 4096

openssl req -sha256 -new -utf8 -key client.key -out client.csr -config openssl_client.cnf

openssl x509 -req -days 1000 -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -CAserial certserial -out client.crt -extensions v3_req -extfile client_ext.cnf

openssl x509 -in client.crt -text -noout

openssl_client.cnf的结构为:

[ req ]
prompt = no
distinguished_name = server_distinguished_name
req_extensions = v3_req

[ server_distinguished_name ]
commonName = localhost
stateOrProvinceName = VA
countryName = US
emailAddress = george@me.com
organizationName = Home
organizationalUnitName = Workstation

[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names

openssl_client.cnf 包含:

[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
1.2.3.4.5.6.7.8 = ASN1:UTF8:User1

[ alt_names ]
DNS.0 = localhost

当脚本为 运行 时,v3 扩展的输出如下:

...........
      X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            X509v3 Key Usage:
                Digital Signature, Non Repudiation, Key Encipherment
            X509v3 Subject Alternative Name:
                DNS:localhost
            1.2.3.4.5.6.7.8:
                ..User1
    Signature Algorithm: sha256WithRSAEncryption
         07:1c:89:eb:1f:30:47:a6:0b:71:33:18:66:b6:00:8f:02:52:
         55:41:0c:12:e5:ba:94:a6:7c:f5:7b:97:ba:6e:1a:55:8b:ea:
         21:4c:c9:f9:b3:09:6f:6c:99:e3:38:89:f5:65:90:25:15:82:
         9e:a6:bf:ce:a5:58:73:01:b1:51:71:cf:10:f1:b0:13:c6:5f:
...........

我正在尝试使用一个简单的 python 程序阅读这些扩展:

from OpenSSL import crypto as c
cert = c.load_certificate(c.FILETYPE_PEM, open('./client.crt').read())
count = cert.get_extension_count()

print(count)

for i in range(0, count):
    ext = cert.get_extension(i)
    ext.get_short_name()
    data = ext.get_data()

    print("Extension {0}".format(data))

    if data == "User1":
        print("User1 found!")
    else:
        print("User1 not found!")

但是,每个扩展都在开头包含额外的字节:

4
Extensions b'0\x00'
User1 not found!
Extension b'\x03\x02\x05\xe0'
User1 not found!
Extension b'0\x0b\x82\tlocalhost'
User1 not found!
Extension b'\x0c\x05User1'
User1 not found!

缺乏关于该主题的文档。有人可以解释为什么每个字符串的开头都包含 2 个额外的字节吗?

.get_data() returns a bytes value, encoded as ASN.1。这不是字符串。

如果您需要扩展的字符串表示,只需使用 str():

data = str(ext)

在@Selcuk 的帮助下,我发现您可以使用 asn1 Python 模块进行转换。以下代码可以很好地打印 User1 扩展名。

import asn1
from OpenSSL import crypto as c

cert = c.load_certificate(c.FILETYPE_PEM, open('../client.crt').read())
count = cert.get_extension_count()

print(count)

for i in range(0, count):
    ext = cert.get_extension(i)
    ext.get_short_name()
    data = ext.get_data()

    decoder = asn1.Decoder()
    decoder.start(data)
    tag, value = decoder.read()

    if i == 3:
        if value.decode("utf-8") == "User1":
            print("User1 found!")
        else:
            print("User1 not found!")