For example say I want to sign a cert with an arbitrary or deprecated extension (nsCertType for example): https://www.openssl.org/docs/manmaster/man5/x509v3_config.html
I believe I'm supposed to add the arbitrary extension as part of the certificate as per below but how / where do you discover the asn1 object identifier? I've read more documentation that I care to admit today and am still stumped.
tmpl := &x509.Certificate{
SerialNumber: big.NewInt(time.Now().Unix()*1000),
Subject: pkix.Name{CommonName: "edgeproxy", Organization: []string{"edgeproxy"}},
NotBefore: now,
NotAfter: now.Add(caMaxAge),
ExtraExtensions: []pkix.Extension{
{
Id: asn1.ObjectIdentifier{}, //what goes here
Critical: false,
[]byte("sslCA"),
},
},
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth,x509.ExtKeyUsageClientAuth,x509.ExtKeyUsageEmailProtection, x509.ExtKeyUsageTimeStamping, x509.ExtKeyUsageMicrosoftCommercialCodeSigning, x509.ExtKeyUsageMicrosoftServerGatedCrypto, x509.ExtKeyUsageNetscapeServerGatedCrypto} ,
KeyUsage: x509.KeyUsageCRLSign | x509.KeyUsageCertSign,
IsCA: true,
BasicConstraintsValid: true,
}
In python I would do this but don't know how to port this into go (which is what I'm doing at the end of the day):
OpenSSL.crypto.X509Extension(
b"nsCertType",
False,
b"sslCA"
),
Go sources at https://golang.org/src/encoding/asn1/asn1.go define:
// An ObjectIdentifier represents an ASN.1 OBJECT IDENTIFIER.
type ObjectIdentifier []int
So the object identifier (OID for short) is an array of integers. The asn1 module has methods to parse them, like parseObjectIdentifier
.
This is the structure you need to put after the Id:
attribute.
But now you need to find out the OID you want.
While difficult to read, OpenSSL source code can show you OIDs of many things in the X.400/X.500/X.509 worlds, or at least those known by OpenSSL.
If you go to https://github.com/openssl/openssl/blob/1aec7716c1c5fccf605a46252a46ea468e684454/crypto/objects/obj_dat.h
and searching on nsCertType
you get:
{"nsCertType", "Netscape Cert Type", NID_netscape_cert_type, 9, &so[407]},
so
is defined previously, and if you jump at its 407th item you see:
0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x01, /* [ 407] OBJ_netscape_cert_type */
and doing a final search on OBJ_netscape_cert_type
in same file gives:
71, /* OBJ_netscape_cert_type 2 16 840 1 113730 1 1 */
which means the corresponding OID is 2.16.840.1.113730.1.1
Or you can decode the above list of integers that describe this OID (see How does ASN.1 encode an object identifier? for details).
0x60
is 96
10 so 2*40 + 16
, which means the OID starts with 2.16.
0x86
is 10000110
2 so has to go with 0x48
aka 01001000
2 so it is in fact 00001101001000
2 or 840
100x01
is less than 128 so it is itself, 1
0x86
is still 10000110
2 but has to be paired with both 0xF8
(11111000
2) and 0x42
(01000010
2 and we stop here since first bit is 0) so 000011011110001000010
2 altogether or 113730
100x01
are themselves, 1
.so we do get again 2.16.840.1.113730.1.1
You can double check it at some online OID browser like here: http://oid-info.com/cgi-bin/display?oid=2.16.840.1.113730.1.1&action=display that gives the following description for it:
Netscape certificate type (a Rec. ITU-T X.509 v3 certificate extension used to identify whether the certificate subject is a Secure Sockets Layer (SSL) client, an SSL server or a Certificate Authority (CA))
You can then even browse various arcs, like the netscape one, or others, to find out other OIDs.
You also get the full ASN.1 notation:
{joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730) cert-ext(1) cert-type(1)}