¿Cómo verifico un certificado SSL en python?

Necesito verificar que mi CA personalizada haya firmado un certificado. Usando las utilidades de línea de comandos de OpenSSL esto es fácil de hacer:

# Custom CA file: ca-cert.pem # Cert signed by above CA: bob.cert $ openssl verify -CAfile test-ca-cert.pem bob.cert bob.cert: OK 

Pero necesito hacer lo mismo en Python, y realmente no quiero llamar a las utilidades de línea de comandos. Por lo que sé, M2Crypto es el envoltorio de python “más completo” para OpenSSL, pero no puedo descubrir cómo lograr lo que hace la utilidad de línea de comandos.

Haciendo referencia a esta pregunta sobre cómo realizar esta misma tarea en el código C, he podido llegar a la mitad. Los nombres de variables que elegí son los mismos que se usaron en el código fuente para la utilidad de línea de comandos de openssl-xxx/apps/verify.c , consulte openssl-xxx/apps/verify.c .

 import M2Crypto as m2 # Load the certificates cacert = m2.X509.load_cert('test-ca-cert.pem') # Create cert object from CA cert file bobcert = m2.X509.load_cert('bob.cert') # Create cert object from Bob's cert file cert_ctx = m2.X509.X509_Store() # Step 1 from referenced C code steps csc = m2.X509.X509_Store_Context(cert_ctx) # Step 2 & 5 cert_ctx.add_cert(cacert) # Step 3 cert_ctx.add_cert(bobcert) # ditto # Skip step 4 (no CRLs to add) # Step 5 is combined with step 2...I think. (X509_STORE_CTX_init: Python creates and # initialises an object in the same step) # Skip step 6? (can't find anything corresponding to # X509_STORE_CTX_set_purpose, not sure if we need to anyway???) # # It all falls apart at this point, as steps 7 and 8 don't have any corresponding # functions in M2Crypto -- I even grepped the entire source code of M2Crypto, and # neither of the following functions are present in it: # Step 7: X509_STORE_CTX_set_cert - Tell the context which certificate to validate. # Step 8: X509_verify_cert - Finally, validate it 

Así que estoy a mitad de camino, ¡pero parece que no puedo realmente hacer la validación! ¿Me estoy perdiendo de algo? ¿Hay alguna otra función que debería usar de M2Crypto? ¿Debería estar buscando un envoltorio Python completamente diferente de OpenSSL? ¿Cómo puedo realizar esta tarea en python!?!?

Tenga en cuenta que estoy usando certificados para cifrar / descifrar ARCHIVOS, por lo que no estoy interesado en usar la verificación de certificado de pares basada en la conexión SSL (que ya ha sido respondida ), porque no tengo ninguna conexión SSL activa.

    No puede hacer esto con M2Crypto simple, ya que no envuelve algunas de las funciones requeridas. La buena noticia es que si tiene SWIG instalado, puede envolverlos usted mismo y usarlo con el código M2Crypto. Hice un módulo con algunas funciones adicionales para mí hace algún tiempo, y decidí publicarlo ahora, ya que hace este tipo de validación. Puede comprobarlo aquí: https://github.com/abbot/m2ext . Este es un ejemplo de cómo validar un certificado usando este módulo:

     import sys from m2ext import SSL from M2Crypto import X509 print "Validating certificate %s using CApath %s" % (sys.argv[1], sys.argv[2]) cert = X509.load_cert(sys.argv[1]) ctx = SSL.Context() ctx.load_verify_locations(capath=sys.argv[2]) if ctx.validate_certificate(cert): print "valid" else: print "invalid" 

    Desafortunadamente, el desarrollo de M2Crypto parece estar estancado (no hay problemas cerrados en el rastreador de errores durante los últimos dos años) y el mantenedor estaba ignorando mis errores y correos electrónicos con estos y algunos otros parches …

    Puede utilizar el método X509.verify desafortunadamente no X509.verify para verificar si el certificado se firmó con la clave privada de la CA. Como esto llama x509_verify de OpenSSL en segundo plano, estoy seguro de que esto también verifica todos los parámetros (como la caducidad) correctamente:

     from M2Crypto X509 cert = X509.load_cert("certificate-filename") caCertificate = X509.load_cert("trusted-ca-filename") caPublic = caCertificate.get_pubkey() if cert.verify(caPublic) == 1: # Certificate is okay! else: # not okay 

    Como dijiste, OpenSSL requiere conexión

    M2Crypto no tiene buena verificación

    ¿Qué tal esta idea ingeniosa?

     import os os.system('openssl verify -CAfile ../ca-cert.pem bob.cert') 

    Es feo, pero funciona!