Merge pull request #18 from lunixbochs/keygen

restructure certs/keys; add key/cert generation
This commit is contained in:
JT Olds 2014-11-18 21:57:17 -07:00
commit a6e28b4958
7 changed files with 713 additions and 65 deletions

367
cert.go Normal file
View File

@ -0,0 +1,367 @@
// Copyright (C) 2014 Space Monkey, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build cgo
package openssl
// #include <openssl/conf.h>
// #include <openssl/ssl.h>
// #include <openssl/x509v3.h>
//
// void OPENSSL_free_not_a_macro(void *ref) { OPENSSL_free(ref); }
//
import "C"
import (
"errors"
"io/ioutil"
"runtime"
"time"
"unsafe"
)
type EVP_MD int
const (
EVP_NULL EVP_MD = iota
EVP_MD5 EVP_MD = iota
EVP_SHA EVP_MD = iota
EVP_SHA1 EVP_MD = iota
EVP_DSS EVP_MD = iota
EVP_DSS1 EVP_MD = iota
EVP_MDC2 EVP_MD = iota
EVP_RIPEMD160 EVP_MD = iota
EVP_SHA224 EVP_MD = iota
EVP_SHA256 EVP_MD = iota
EVP_SHA384 EVP_MD = iota
EVP_SHA512 EVP_MD = iota
)
type Certificate struct {
x *C.X509
Issuer *Certificate
ref interface{}
pubKey PublicKey
}
type CertificateInfo struct {
Serial int
Issued time.Duration
Expires time.Duration
Country string
Organization string
CommonName string
}
type Name struct {
name *C.X509_NAME
}
// Allocate and return a new Name object.
func NewName() (*Name, error) {
n := C.X509_NAME_new()
if n == nil {
return nil, errors.New("could not create x509 name")
}
name := &Name{name: n}
runtime.SetFinalizer(name, func(n *Name) {
C.X509_NAME_free(n.name)
})
return name, nil
}
// AddTextEntry appends a text entry to an X509 NAME.
func (n *Name) AddTextEntry(field, value string) error {
cfield := C.CString(field)
defer C.free(unsafe.Pointer(cfield))
cvalue := (*C.uchar)(unsafe.Pointer(C.CString(value)))
defer C.free(unsafe.Pointer(cvalue))
ret := C.X509_NAME_add_entry_by_txt(
n.name, cfield, C.MBSTRING_ASC, cvalue, -1, -1, 0)
if ret != 1 {
return errors.New("failed to add x509 name text entry")
}
return nil
}
// AddTextEntries allows adding multiple entries to a name in one call.
func (n *Name) AddTextEntries(entries map[string]string) error {
for f, v := range entries {
if err := n.AddTextEntry(f, v); err != nil {
return err
}
}
return nil
}
// NewCertificate generates a basic certificate based
// on the provided CertificateInfo struct
func NewCertificate(info *CertificateInfo, key PublicKey) (*Certificate, error) {
c := &Certificate{x: C.X509_new()}
runtime.SetFinalizer(c, func(c *Certificate) {
C.X509_free(c.x)
})
name, err := c.GetSubjectName()
if err != nil {
return nil, err
}
err = name.AddTextEntries(map[string]string{
"C": info.Country,
"O": info.Organization,
"CN": info.CommonName,
})
if err != nil {
return nil, err
}
// self-issue for now
if err := c.SetIssuerName(name); err != nil {
return nil, err
}
if err := c.SetSerial(info.Serial); err != nil {
return nil, err
}
if err := c.SetIssueDate(info.Issued); err != nil {
return nil, err
}
if err := c.SetExpireDate(info.Expires); err != nil {
return nil, err
}
if err := c.SetPubKey(key); err != nil {
return nil, err
}
return c, nil
}
func (c *Certificate) GetSubjectName() (*Name, error) {
n := C.X509_get_subject_name(c.x)
if n == nil {
return nil, errors.New("failed to get subject name")
}
return &Name{name: n}, nil
}
func (c *Certificate) GetIssuerName() (*Name, error) {
n := C.X509_get_issuer_name(c.x)
if n == nil {
return nil, errors.New("failed to get issuer name")
}
return &Name{name: n}, nil
}
func (c *Certificate) SetSubjectName(name *Name) error {
if C.X509_set_subject_name(c.x, name.name) != 1 {
return errors.New("failed to set subject name")
}
return nil
}
// SetIssuer updates the stored Issuer cert
// and the internal x509 Issuer Name of a certificate.
// The stored Issuer reference is used when adding extensions.
func (c *Certificate) SetIssuer(issuer *Certificate) error {
name, err := issuer.GetSubjectName()
if err != nil {
return err
}
if err = c.SetIssuerName(name); err != nil {
return err
}
c.Issuer = issuer
return nil
}
// SetIssuerName populates the issuer name of a certificate.
// Use SetIssuer instead, if possible.
func (c *Certificate) SetIssuerName(name *Name) error {
if C.X509_set_issuer_name(c.x, name.name) != 1 {
return errors.New("failed to set subject name")
}
return nil
}
// SetSerial sets the serial of a certificate.
func (c *Certificate) SetSerial(serial int) error {
if C.ASN1_INTEGER_set(C.X509_get_serialNumber(c.x), C.long(serial)) != 1 {
return errors.New("failed to set serial")
}
return nil
}
// SetIssueDate sets the certificate issue date relative to the current time.
func (c *Certificate) SetIssueDate(when time.Duration) error {
offset := C.long(when / time.Second)
result := C.X509_gmtime_adj(c.x.cert_info.validity.notBefore, offset)
if result == nil {
return errors.New("failed to set issue date")
}
return nil
}
// SetExpireDate sets the certificate issue date relative to the current time.
func (c *Certificate) SetExpireDate(when time.Duration) error {
offset := C.long(when / time.Second)
result := C.X509_gmtime_adj(c.x.cert_info.validity.notAfter, offset)
if result == nil {
return errors.New("failed to set expire date")
}
return nil
}
// SetPubKey assigns a new public key to a certificate.
func (c *Certificate) SetPubKey(pubKey PublicKey) error {
c.pubKey = pubKey
if C.X509_set_pubkey(c.x, pubKey.evpPKey()) != 1 {
return errors.New("failed to set public key")
}
return nil
}
// Sign a certificate using a private key and a digest name.
// Accepted digest names are 'sha256', 'sha384', and 'sha512'.
func (c *Certificate) Sign(privKey PrivateKey, digest EVP_MD) error {
switch digest {
case EVP_SHA256:
case EVP_SHA384:
case EVP_SHA512:
default:
return errors.New("Unsupported digest" +
"You're probably looking for 'EVP_SHA256' or 'EVP_SHA512'.")
}
return c.insecureSign(privKey, digest)
}
func (c *Certificate) insecureSign(privKey PrivateKey, digest EVP_MD) error {
var md *C.EVP_MD
switch digest {
// please don't use these digest functions
case EVP_NULL:
md = C.EVP_md_null()
case EVP_MD5:
md = C.EVP_md5()
case EVP_SHA:
md = C.EVP_sha()
case EVP_SHA1:
md = C.EVP_sha1()
case EVP_DSS:
md = C.EVP_dss()
case EVP_DSS1:
md = C.EVP_dss1()
case EVP_RIPEMD160:
md = C.EVP_ripemd160()
case EVP_SHA224:
md = C.EVP_sha224()
// you actually want one of these
case EVP_SHA256:
md = C.EVP_sha256()
case EVP_SHA384:
md = C.EVP_sha384()
case EVP_SHA512:
md = C.EVP_sha512()
}
if C.X509_sign(c.x, privKey.evpPKey(), md) <= 0 {
return errors.New("failed to sign certificate")
}
return nil
}
// Add an extension to a certificate.
// Extension constants are NID_* as found in openssl.
func (c *Certificate) AddExtension(nid NID, value string) error {
issuer := c
if c.Issuer != nil {
issuer = c.Issuer
}
var ctx C.X509V3_CTX
C.X509V3_set_ctx(&ctx, c.x, issuer.x, nil, nil, 0)
ex := C.X509V3_EXT_conf_nid(nil, &ctx, C.int(nid), C.CString(value))
if ex == nil {
return errors.New("failed to create x509v3 extension")
}
defer C.X509_EXTENSION_free(ex)
if C.X509_add_ext(c.x, ex, -1) <= 0 {
return errors.New("failed to add x509v3 extension")
}
return nil
}
// Wraps AddExtension using a map of NID to text extension.
// Will return without finishing if it encounters an error.
func (c *Certificate) AddExtensions(extensions map[NID]string) error {
for nid, value := range extensions {
if err := c.AddExtension(nid, value); err != nil {
return err
}
}
return nil
}
// LoadCertificateFromPEM loads an X509 certificate from a PEM-encoded block.
func LoadCertificateFromPEM(pem_block []byte) (*Certificate, error) {
if len(pem_block) == 0 {
return nil, errors.New("empty pem block")
}
runtime.LockOSThread()
defer runtime.UnlockOSThread()
bio := C.BIO_new_mem_buf(unsafe.Pointer(&pem_block[0]),
C.int(len(pem_block)))
cert := C.PEM_read_bio_X509(bio, nil, nil, nil)
C.BIO_free(bio)
if cert == nil {
return nil, errorFromErrorQueue()
}
x := &Certificate{x: cert}
runtime.SetFinalizer(x, func(x *Certificate) {
C.X509_free(x.x)
})
return x, nil
}
// MarshalPEM converts the X509 certificate to PEM-encoded format
func (c *Certificate) MarshalPEM() (pem_block []byte, err error) {
bio := C.BIO_new(C.BIO_s_mem())
if bio == nil {
return nil, errors.New("failed to allocate memory BIO")
}
defer C.BIO_free(bio)
if int(C.PEM_write_bio_X509(bio, c.x)) != 1 {
return nil, errors.New("failed dumping certificate")
}
return ioutil.ReadAll(asAnyBio(bio))
}
// PublicKey returns the public key embedded in the X509 certificate.
func (c *Certificate) PublicKey() (PublicKey, error) {
pkey := C.X509_get_pubkey(c.x)
if pkey == nil {
return nil, errors.New("no public key found")
}
key := &pKey{key: pkey}
runtime.SetFinalizer(key, func(key *pKey) {
C.EVP_PKEY_free(key.key)
})
return key, nil
}
// GetSerialNumberHex returns the certificate's serial number in hex format
func (c *Certificate) GetSerialNumberHex() (serial string) {
asn1_i := C.X509_get_serialNumber(c.x)
bignum := C.ASN1_INTEGER_to_BN(asn1_i, nil)
hex := C.BN_bn2hex(bignum)
serial = C.GoString(hex)
C.BN_free(bignum)
C.OPENSSL_free_not_a_macro(unsafe.Pointer(hex))
return
}

101
cert_test.go Normal file
View File

@ -0,0 +1,101 @@
// Copyright (C) 2014 Ryan Hileman
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package openssl
import (
"testing"
"time"
)
func TestCertGenerate(t *testing.T) {
key, err := GenerateRSAKey(2048)
if err != nil {
t.Fatal(err)
}
info := &CertificateInfo{
Serial: 1,
Issued: 0,
Expires: 24 * time.Hour,
Country: "US",
Organization: "Test",
CommonName: "localhost",
}
cert, err := NewCertificate(info, key)
if err != nil {
t.Fatal(err)
}
if err := cert.Sign(key, EVP_SHA256); err != nil {
t.Fatal(err)
}
}
func TestCAGenerate(t *testing.T) {
cakey, err := GenerateRSAKey(2048)
if err != nil {
t.Fatal(err)
}
info := &CertificateInfo{
Serial: 1,
Issued: 0,
Expires: 24 * time.Hour,
Country: "US",
Organization: "Test CA",
CommonName: "CA",
}
ca, err := NewCertificate(info, cakey)
if err != nil {
t.Fatal(err)
}
if err := ca.AddExtensions(map[NID]string{
NID_basic_constraints: "critical,CA:TRUE",
NID_key_usage: "critical,keyCertSign,cRLSign",
NID_subject_key_identifier: "hash",
NID_netscape_cert_type: "sslCA",
}); err != nil {
t.Fatal(err)
}
if err := ca.Sign(cakey, EVP_SHA256); err != nil {
t.Fatal(err)
}
key, err := GenerateRSAKey(2048)
if err != nil {
t.Fatal(err)
}
info = &CertificateInfo{
Serial: 1,
Issued: 0,
Expires: 24 * time.Hour,
Country: "US",
Organization: "Test",
CommonName: "localhost",
}
cert, err := NewCertificate(info, key)
if err != nil {
t.Fatal(err)
}
if err := cert.AddExtensions(map[NID]string{
NID_basic_constraints: "critical,CA:FALSE",
NID_key_usage: "keyEncipherment",
NID_ext_key_usage: "serverAuth",
}); err != nil {
t.Fatal(err)
}
if err := cert.SetIssuer(ca); err != nil {
t.Fatal(err)
}
if err := cert.Sign(cakey, EVP_SHA256); err != nil {
t.Fatal(err)
}
}

View File

@ -73,8 +73,8 @@ type Cipher struct {
ptr *C.EVP_CIPHER
}
func (c *Cipher) Nid() int {
return int(C.EVP_CIPHER_nid_not_a_macro(c.ptr))
func (c *Cipher) Nid() NID {
return NID(C.EVP_CIPHER_nid_not_a_macro(c.ptr))
}
func (c *Cipher) ShortName() (string, error) {
@ -93,7 +93,7 @@ func (c *Cipher) IVSize() int {
return int(C.EVP_CIPHER_iv_length_not_a_macro(c.ptr))
}
func Nid2ShortName(nid int) (string, error) {
func Nid2ShortName(nid NID) (string, error) {
sn := C.OBJ_nid2sn(C.int(nid))
if sn == nil {
return "", fmt.Errorf("NID %d not found", nid)
@ -112,7 +112,7 @@ func GetCipherByName(name string) (*Cipher, error) {
return &Cipher{ptr: p}, nil
}
func GetCipherByNid(nid int) (*Cipher, error) {
func GetCipherByNid(nid NID) (*Cipher, error) {
sn, err := Nid2ShortName(nid)
if err != nil {
return nil, err

11
ctx.go
View File

@ -101,6 +101,9 @@ var (
type Ctx struct {
ctx *C.SSL_CTX
cert *Certificate
chain []*Certificate
key PrivateKey
verify_cb VerifyCallback
}
@ -244,6 +247,7 @@ func (c *Ctx) SetEllipticCurve(curve EllipticCurve) error {
func (c *Ctx) UseCertificate(cert *Certificate) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
c.cert = cert
if int(C.SSL_CTX_use_certificate(c.ctx, cert.x)) != 1 {
return errorFromErrorQueue()
}
@ -255,6 +259,7 @@ func (c *Ctx) UseCertificate(cert *Certificate) error {
func (c *Ctx) AddChainCertificate(cert *Certificate) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
c.chain = append(c.chain, cert)
if int(C.SSL_CTX_add_extra_chain_cert_not_a_macro(c.ctx, cert.x)) != 1 {
return errorFromErrorQueue()
}
@ -266,6 +271,7 @@ func (c *Ctx) AddChainCertificate(cert *Certificate) error {
func (c *Ctx) UsePrivateKey(key PrivateKey) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
c.key = key
if int(C.SSL_CTX_use_PrivateKey(c.ctx, key.evpPKey())) != 1 {
return errorFromErrorQueue()
}
@ -274,7 +280,9 @@ func (c *Ctx) UsePrivateKey(key PrivateKey) error {
type CertificateStore struct {
store *C.X509_STORE
ctx *Ctx // for gc
// for GC
ctx *Ctx
certs []*Certificate
}
// GetCertificateStore returns the context's certificate store that will be
@ -292,6 +300,7 @@ func (c *Ctx) GetCertificateStore() *CertificateStore {
func (s *CertificateStore) AddCertificate(cert *Certificate) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
s.certs = append(s.certs, cert)
if int(C.X509_STORE_add_cert(s.store, cert.x)) != 1 {
return errorFromErrorQueue()
}

View File

@ -20,8 +20,6 @@ package openssl
// #include <openssl/ssl.h>
// #include <openssl/conf.h>
//
// void OPENSSL_free_not_a_macro(void *ref) { OPENSSL_free(ref); }
//
// int EVP_SignInit_not_a_macro(EVP_MD_CTX *ctx, const EVP_MD *type) {
// return EVP_SignInit(ctx, type);
// }
@ -312,65 +310,24 @@ func LoadPublicKeyFromDER(der_block []byte) (PublicKey, error) {
return p, nil
}
type Certificate struct {
x *C.X509
ref interface{}
}
// LoadCertificateFromPEM loads an X509 certificate from a PEM-encoded block.
func LoadCertificateFromPEM(pem_block []byte) (*Certificate, error) {
if len(pem_block) == 0 {
return nil, errors.New("empty pem block")
// GenerateRSAKey generates a new RSA private key with an exponent of 3.
func GenerateRSAKey(bits int) (PrivateKey, error) {
exponent := 3
rsa := C.RSA_generate_key(C.int(bits), C.ulong(exponent), nil, nil)
if rsa == nil {
return nil, errors.New("failed to generate RSA key")
}
runtime.LockOSThread()
defer runtime.UnlockOSThread()
bio := C.BIO_new_mem_buf(unsafe.Pointer(&pem_block[0]),
C.int(len(pem_block)))
cert := C.PEM_read_bio_X509(bio, nil, nil, nil)
C.BIO_free(bio)
if cert == nil {
return nil, errorFromErrorQueue()
key := C.EVP_PKEY_new()
if key == nil {
return nil, errors.New("failed to allocate EVP_PKEY")
}
x := &Certificate{x: cert}
runtime.SetFinalizer(x, func(x *Certificate) {
C.X509_free(x.x)
if C.EVP_PKEY_assign(key, C.EVP_PKEY_RSA, unsafe.Pointer(rsa)) != 1 {
C.EVP_PKEY_free(key)
return nil, errors.New("failed to assign RSA key")
}
p := &pKey{key: key}
runtime.SetFinalizer(p, func(p *pKey) {
C.EVP_PKEY_free(p.key)
})
return x, nil
}
// MarshalPEM converts the X509 certificate to PEM-encoded format
func (c *Certificate) MarshalPEM() (pem_block []byte, err error) {
bio := C.BIO_new(C.BIO_s_mem())
if bio == nil {
return nil, errors.New("failed to allocate memory BIO")
}
defer C.BIO_free(bio)
if int(C.PEM_write_bio_X509(bio, c.x)) != 1 {
return nil, errors.New("failed dumping certificate")
}
return ioutil.ReadAll(asAnyBio(bio))
}
// PublicKey returns the public key embedded in the X509 certificate.
func (c *Certificate) PublicKey() (PublicKey, error) {
pkey := C.X509_get_pubkey(c.x)
if pkey == nil {
return nil, errors.New("no public key found")
}
key := &pKey{key: pkey}
runtime.SetFinalizer(key, func(key *pKey) {
C.EVP_PKEY_free(key.key)
})
return key, nil
}
// GetSerialNumberHex returns the certificate's serial number in hex format
func (c *Certificate) GetSerialNumberHex() (serial string) {
asn1_i := C.X509_get_serialNumber(c.x)
bignum := C.ASN1_INTEGER_to_BN(asn1_i, nil)
hex := C.BN_bn2hex(bignum)
serial = C.GoString(hex)
C.BN_free(bignum)
C.OPENSSL_free_not_a_macro(unsafe.Pointer(hex))
return
return p, nil
}

View File

@ -132,3 +132,18 @@ func TestMarshal(t *testing.T) {
t.Fatal("invalid public key der bytes")
}
}
func TestGenerate(t *testing.T) {
key, err := GenerateRSAKey(2048)
if err != nil {
t.Fatal(err)
}
_, err = key.MarshalPKIXPublicKeyPEM()
if err != nil {
t.Fatal(err)
}
_, err = key.MarshalPKCS1PrivateKeyPEM()
if err != nil {
t.Fatal(err)
}
}

199
nid.go Normal file
View File

@ -0,0 +1,199 @@
// Copyright (C) 2014 Ryan Hileman
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package openssl
type NID int
const (
NID_rsadsi NID = 1
NID_pkcs NID = 2
NID_md2 NID = 3
NID_md5 NID = 4
NID_rc4 NID = 5
NID_rsaEncryption NID = 6
NID_md2WithRSAEncryption NID = 7
NID_md5WithRSAEncryption NID = 8
NID_pbeWithMD2AndDES_CBC NID = 9
NID_pbeWithMD5AndDES_CBC NID = 10
NID_X500 NID = 11
NID_X509 NID = 12
NID_commonName NID = 13
NID_countryName NID = 14
NID_localityName NID = 15
NID_stateOrProvinceName NID = 16
NID_organizationName NID = 17
NID_organizationalUnitName NID = 18
NID_rsa NID = 19
NID_pkcs7 NID = 20
NID_pkcs7_data NID = 21
NID_pkcs7_signed NID = 22
NID_pkcs7_enveloped NID = 23
NID_pkcs7_signedAndEnveloped NID = 24
NID_pkcs7_digest NID = 25
NID_pkcs7_encrypted NID = 26
NID_pkcs3 NID = 27
NID_dhKeyAgreement NID = 28
NID_des_ecb NID = 29
NID_des_cfb64 NID = 30
NID_des_cbc NID = 31
NID_des_ede NID = 32
NID_des_ede3 NID = 33
NID_idea_cbc NID = 34
NID_idea_cfb64 NID = 35
NID_idea_ecb NID = 36
NID_rc2_cbc NID = 37
NID_rc2_ecb NID = 38
NID_rc2_cfb64 NID = 39
NID_rc2_ofb64 NID = 40
NID_sha NID = 41
NID_shaWithRSAEncryption NID = 42
NID_des_ede_cbc NID = 43
NID_des_ede3_cbc NID = 44
NID_des_ofb64 NID = 45
NID_idea_ofb64 NID = 46
NID_pkcs9 NID = 47
NID_pkcs9_emailAddress NID = 48
NID_pkcs9_unstructuredName NID = 49
NID_pkcs9_contentType NID = 50
NID_pkcs9_messageDigest NID = 51
NID_pkcs9_signingTime NID = 52
NID_pkcs9_countersignature NID = 53
NID_pkcs9_challengePassword NID = 54
NID_pkcs9_unstructuredAddress NID = 55
NID_pkcs9_extCertAttributes NID = 56
NID_netscape NID = 57
NID_netscape_cert_extension NID = 58
NID_netscape_data_type NID = 59
NID_des_ede_cfb64 NID = 60
NID_des_ede3_cfb64 NID = 61
NID_des_ede_ofb64 NID = 62
NID_des_ede3_ofb64 NID = 63
NID_sha1 NID = 64
NID_sha1WithRSAEncryption NID = 65
NID_dsaWithSHA NID = 66
NID_dsa_2 NID = 67
NID_pbeWithSHA1AndRC2_CBC NID = 68
NID_id_pbkdf2 NID = 69
NID_dsaWithSHA1_2 NID = 70
NID_netscape_cert_type NID = 71
NID_netscape_base_url NID = 72
NID_netscape_revocation_url NID = 73
NID_netscape_ca_revocation_url NID = 74
NID_netscape_renewal_url NID = 75
NID_netscape_ca_policy_url NID = 76
NID_netscape_ssl_server_name NID = 77
NID_netscape_comment NID = 78
NID_netscape_cert_sequence NID = 79
NID_desx_cbc NID = 80
NID_id_ce NID = 81
NID_subject_key_identifier NID = 82
NID_key_usage NID = 83
NID_private_key_usage_period NID = 84
NID_subject_alt_name NID = 85
NID_issuer_alt_name NID = 86
NID_basic_constraints NID = 87
NID_crl_number NID = 88
NID_certificate_policies NID = 89
NID_authority_key_identifier NID = 90
NID_bf_cbc NID = 91
NID_bf_ecb NID = 92
NID_bf_cfb64 NID = 93
NID_bf_ofb64 NID = 94
NID_mdc2 NID = 95
NID_mdc2WithRSA NID = 96
NID_rc4_40 NID = 97
NID_rc2_40_cbc NID = 98
NID_givenName NID = 99
NID_surname NID = 100
NID_initials NID = 101
NID_uniqueIdentifier NID = 102
NID_crl_distribution_points NID = 103
NID_md5WithRSA NID = 104
NID_serialNumber NID = 105
NID_title NID = 106
NID_description NID = 107
NID_cast5_cbc NID = 108
NID_cast5_ecb NID = 109
NID_cast5_cfb64 NID = 110
NID_cast5_ofb64 NID = 111
NID_pbeWithMD5AndCast5_CBC NID = 112
NID_dsaWithSHA1 NID = 113
NID_md5_sha1 NID = 114
NID_sha1WithRSA NID = 115
NID_dsa NID = 116
NID_ripemd160 NID = 117
NID_ripemd160WithRSA NID = 119
NID_rc5_cbc NID = 120
NID_rc5_ecb NID = 121
NID_rc5_cfb64 NID = 122
NID_rc5_ofb64 NID = 123
NID_rle_compression NID = 124
NID_zlib_compression NID = 125
NID_ext_key_usage NID = 126
NID_id_pkix NID = 127
NID_id_kp NID = 128
NID_server_auth NID = 129
NID_client_auth NID = 130
NID_code_sign NID = 131
NID_email_protect NID = 132
NID_time_stamp NID = 133
NID_ms_code_ind NID = 134
NID_ms_code_com NID = 135
NID_ms_ctl_sign NID = 136
NID_ms_sgc NID = 137
NID_ms_efs NID = 138
NID_ns_sgc NID = 139
NID_delta_crl NID = 140
NID_crl_reason NID = 141
NID_invalidity_date NID = 142
NID_sxnet NID = 143
NID_pbe_WithSHA1And128BitRC4 NID = 144
NID_pbe_WithSHA1And40BitRC4 NID = 145
NID_pbe_WithSHA1And3_Key_TripleDES_CBC NID = 146
NID_pbe_WithSHA1And2_Key_TripleDES_CBC NID = 147
NID_pbe_WithSHA1And128BitRC2_CBC NID = 148
NID_pbe_WithSHA1And40BitRC2_CBC NID = 149
NID_keyBag NID = 150
NID_pkcs8ShroudedKeyBag NID = 151
NID_certBag NID = 152
NID_crlBag NID = 153
NID_secretBag NID = 154
NID_safeContentsBag NID = 155
NID_friendlyName NID = 156
NID_localKeyID NID = 157
NID_x509Certificate NID = 158
NID_sdsiCertificate NID = 159
NID_x509Crl NID = 160
NID_pbes2 NID = 161
NID_pbmac1 NID = 162
NID_hmacWithSHA1 NID = 163
NID_id_qt_cps NID = 164
NID_id_qt_unotice NID = 165
NID_rc2_64_cbc NID = 166
NID_SMIMECapabilities NID = 167
NID_pbeWithMD2AndRC2_CBC NID = 168
NID_pbeWithMD5AndRC2_CBC NID = 169
NID_pbeWithSHA1AndDES_CBC NID = 170
NID_ms_ext_req NID = 171
NID_ext_req NID = 172
NID_name NID = 173
NID_dnQualifier NID = 174
NID_id_pe NID = 175
NID_id_ad NID = 176
NID_info_access NID = 177
NID_ad_OCSP NID = 178
NID_ad_ca_issuers NID = 179
NID_OCSP_sign NID = 180
)