4 votes

Comment créer et signer des certificats avec pyOpenSSL de Python ?

Je voudrais utiliser python pour créer un certificat d'autorité de certification, et les certificats des clients que je signe avec. Je vais les utiliser avec OpenVPN. Après plusieurs jours de recherche, d'essais et d'erreurs, voici ce que j'ai trouvé :

#!/usr/bin/env python

import os
import sys
import random
from OpenSSL import crypto

###########
# CA Cert #
###########

ca_key = crypto.PKey()
ca_key.generate_key(crypto.TYPE_RSA, 2048)

ca_cert = crypto.X509()
ca_cert.set_version(2)
ca_cert.set_serial_number(random.randint(50000000,100000000))

ca_subj = ca_cert.get_subject()
ca_subj.commonName = "My CA"

ca_cert.add_extensions([
    crypto.X509Extension("subjectKeyIdentifier", False, "hash", subject=ca_cert),
])

ca_cert.add_extensions([
    crypto.X509Extension("authorityKeyIdentifier", False, "keyid:always", issuer=ca_cert),
])

ca_cert.add_extensions([
    crypto.X509Extension("basicConstraints", False, "CA:TRUE"),
    crypto.X509Extension("keyUsage", False, "keyCertSign, cRLSign"),
])

ca_cert.set_issuer(ca_subj)
ca_cert.set_pubkey(ca_key)
ca_cert.sign(ca_key, 'sha256')

ca_cert.gmtime_adj_notBefore(0)
ca_cert.gmtime_adj_notAfter(10*365*24*60*60)

# Save certificate
with open("ca.crt", "wt") as f:
    f.write(crypto.dump_certificate(crypto.FILETYPE_PEM, ca_cert))

# Save private key
with open("ca.key", "wt") as f:
    f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, ca_key))

###############
# Client Cert #
###############

client_key = crypto.PKey()
client_key.generate_key(crypto.TYPE_RSA, 2048)

client_cert = crypto.X509()
client_cert.set_version(2)
client_cert.set_serial_number(random.randint(50000000,100000000))

client_subj = client_cert.get_subject()
client_subj.commonName = "Client"

client_cert.add_extensions([
    crypto.X509Extension("basicConstraints", False, "CA:FALSE"),
    crypto.X509Extension("subjectKeyIdentifier", False, "hash", subject=client_cert),
])

client_cert.add_extensions([
    crypto.X509Extension("authorityKeyIdentifier", False, "keyid:always", issuer=ca_cert),
    crypto.X509Extension("extendedKeyUsage", False, "clientAuth"),
    crypto.X509Extension("keyUsage", False, "digitalSignature"),
])

client_cert.set_issuer(ca_subj)
client_cert.set_pubkey(client_key)
client_cert.sign(ca_key, 'sha256')

client_cert.gmtime_adj_notBefore(0)
client_cert.gmtime_adj_notAfter(10*365*24*60*60)

# Save certificate
with open("client.crt", "wt") as f:
    f.write(crypto.dump_certificate(crypto.FILETYPE_PEM, client_cert))

# Save private key
with open("client.key", "wt") as f:
    f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, client_key))

Cela génère les certificats et les clés privées, mais malheureusement, je dois faire quelque chose de mal car ils ne se vérifient pas :

$ openssl verify -verbose -CAfile ca.crt client.crt
client.crt: CN = Client
error 7 at 0 depth lookup:certificate signature failure
139823049836448:error:04091068:rsa routines:INT_RSA_VERIFY:bad signature:rsa_sign.c:293:
139823049836448:error:0D0C5006:asn1 encoding routines:ASN1_item_verify:EVP lib:a_verify.c:241:

Qu'est-ce que je fais de mal ?

4voto

Steffen Ullrich Points 56226

Vous définissez notBefore et notAfter après avoir déjà signé le certificat et modifiez donc le certificat déjà signé - ce qui fait que la signature ne correspond plus au certificat :

client_cert.sign(ca_key, 'sha256')  

client_cert.gmtime_adj_notBefore(0)
client_cert.gmtime_adj_notAfter(10*365*24*60*60)

# Save certificate
...

Si vous faites en sorte que la signature soit la dernière étape, c'est-à-dire juste avant l'écriture du fichier, la vérification sera réussie :

client_cert.gmtime_adj_notBefore(0)
client_cert.gmtime_adj_notAfter(10*365*24*60*60)

client_cert.sign(ca_key, 'sha256')  

# Save certificate
...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X