1

Given a CA file containing these extension sets:

[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection

[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth

Using "regular" openssl I can create a cert given a CSR and the following statement:

openssl ca -config intermediate/openssl.cnf -extensions server_cert -days 375 -notext -md sha256 -in intermediate/csr/www.example.com.csr.pem -out intermediate/certs/www.example.com.cert.pem

I'd like to do the same using pyOpenSSL, however, I can't find a method on the crypto.X509() class that allows me to do this:

cert = crypto.X509()
cert.set_issuer(caCert.get_subject())
cert.set_serial_number(1)
cert.set_notAfter("20170201000000Z")
cert.set_notBefore("20160201000000Z")
cert.set_subject(deviceCsr.get_subject())
cert.set_issuer(issuer=caCert.get_issuer())
cert.set_pubkey(deviceCsr.get_pubkey())
cert.sign(CAprivatekey, "sha1")

I can see a cert.add_extensions, but that doesn't seem to allow adding a "template", but rather exlicit extensions such as critical, digitalSignature, keyEncipherment etc.

Is there a way I can specify the "template"/extension set in pyOpenSSL when creating a cert?

EDIT: Thinking about this more, I realize that pyOpenSSL doesn't care about the ca.conf file at all, it just uses the ca cert to sign the new server cert in question and that's it. So I gues my question should rather be: Is there a way to have pyopenssl use the config from the ca.conf file at all, or do I have to create all the options in code? if true then it certainly looks like it's easier to just have python shell out to openssl in order to generate the cert.

Trondh
  • 3,221
  • 1
  • 25
  • 34
  • Also see [How do you sign Certificate Signing Request with your Certification Authority](http://stackoverflow.com/a/21340898/608639) and [How to create a self-signed certificate with openssl?](http://stackoverflow.com/q/10175812/608639). It has useful information about setting up the OpenSSL CONF files. – jww Jan 23 '17 at 06:16
  • *" Thinking about this more, I realize that pyOpenSSL doesn't care about the ca.conf file at all, it just uses the ca cert to sign the new server cert in question and that's it..."* - Not necessarily true. See the first link in the other comment. Maybe you need to set the CONF file in PyOpenSSL so it uses the correct one. – jww Jan 23 '17 at 06:17
  • Thanks. I can't see any way of referring to a config file in the python openssl api – Trondh Jan 23 '17 at 09:59

1 Answers1

1

Here is an example on how to set various extensions. Each extension has a different data/payload.

You got the extension name, they critical flag and last is the extension data.

extensions = [
    crypto.X509Extension(b'basicConstraints', False, b'CA:FALSE'),
    crypto.X509Extension(b'keyUsage', 'digitalSignature, nonRepudiation', keyusage),
    crypto.X509Extension(b'extendedKeyUsage', True, b'serverAuth'),
    crypto.X509Extension(b'subjectAltName', False, b'DNS:www.ex.com,IP:1.2.3.4')
    ]
cert.add_extensions(extensions)
Adi Roiban
  • 1,293
  • 2
  • 13
  • 28