Home > Back-end >  Extra characters parsed from X.509 v3 extensions
Extra characters parsed from X.509 v3 extensions

Time:09-26

I am trying to create some certificates using OpenSSL v1.1.1, that it will hold some specific data in, as a v3 extension field. I am using a simple bash script that will perform all these actions automatically:

#!/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

The openssl_client.cnf is structured as:

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

[ server_distinguished_name ]
commonName = localhost
stateOrProvinceName = VA
countryName = US
emailAddress = [email protected]
organizationName = Home
organizationalUnitName = Workstation

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

And the openssl_client.cnf contains:

[ 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

When the script is run, the output for the v3 extensions is the following:

...........
      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:
...........

I am trying to read those extensions with a simple python program:

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!")

However, each extension includes extra bytes in the beginning:

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!

Documentation in this topic is lacking. Can someone explain why the 2 extra bytes are included in the beginning of each string?

CodePudding user response:

.get_data() returns a bytes value, encoded as ASN.1. It's not a string.

If you need a string representation of the extension simply use str():

data = str(ext)

CodePudding user response:

Based on the help from @Selcuk I figured out that you can do the conversion using the asn1 Python module. The follwoing code prints the User1 extension just fine.

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!")
  • Related