¿Cómo se firma una solicitud de firma de certificado con su autoridad de certificación?

195

Durante mi búsqueda, encontré varias formas de firmar una solicitud de firma de certificado SSL:

  1. Usando el x509módulo:

    openssl x509 -req -days 360 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
    
  2. Usando el camódulo:

    openssl ca -cert ca.crt -keyfile ca.key -in server.csr -out server.crt
    

Nota: no estoy seguro del uso de los parámetros correctos para este. Indique el uso correcto si debo usarlo.

¿De qué manera se debe usar para firmar solicitudes de certificados con su Autoridad de Certificación? ¿Es un método mejor que el otro (por ejemplo, uno está en desuso)?

Bernard Rosset
fuente
1
Me gusta este pequeño script que configura una CA y le permite generar certificados "subordinados" firmados. Tenga en cuenta que si desea que su sistema esté contento con los certificados (como para S / MIME o cualquier otra cosa), debe agregar el certificado de CA como una "raíz confiable".
jar
Por lo que puedo ver, caes para los casos en que eres más serio acerca de convertirte en un CA.
x-yuri
Puede encontrar mi respuesta interesante.
x-yuri
Stack Overflow es un sitio para preguntas de programación y desarrollo. Esta pregunta parece estar fuera de tema porque no se trata de programación o desarrollo. Consulte los temas sobre los que puedo preguntar aquí en el Centro de ayuda. Quizás Super User o Unix & Linux Stack Exchange sería un mejor lugar para preguntar.
jww

Respuestas:

458
1. Using the x509 module
openssl x509 ...
...

2 Using the ca module
openssl ca ...
...

Te estás perdiendo el preludio de esos comandos.

Este es un proceso de dos pasos. Primero configura su CA y luego firma un certificado de entidad final (también conocido como servidor o usuario). Los dos comandos eluden los dos pasos en uno. Y ambos suponen que ya tiene un archivo de configuración de OpenSSL configurado para las CA y los certificados de servidor (entidad final).


Primero, cree un archivo de configuración básica :

$ touch openssl-ca.cnf

Luego, agregue lo siguiente:

HOME            = .
RANDFILE        = $ENV::HOME/.rnd

####################################################################
[ ca ]
default_ca    = CA_default      # The default ca section

[ CA_default ]

default_days     = 1000         # How long to certify for
default_crl_days = 30           # How long before next CRL
default_md       = sha256       # Use public key default MD
preserve         = no           # Keep passed DN ordering

x509_extensions = ca_extensions # The extensions to add to the cert

email_in_dn     = no            # Don't concat the email in the DN
copy_extensions = copy          # Required to copy SANs from CSR to cert

####################################################################
[ req ]
default_bits       = 4096
default_keyfile    = cakey.pem
distinguished_name = ca_distinguished_name
x509_extensions    = ca_extensions
string_mask        = utf8only

####################################################################
[ ca_distinguished_name ]
countryName         = Country Name (2 letter code)
countryName_default = US

stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = Maryland

localityName                = Locality Name (eg, city)
localityName_default        = Baltimore

organizationName            = Organization Name (eg, company)
organizationName_default    = Test CA, Limited

organizationalUnitName         = Organizational Unit (eg, division)
organizationalUnitName_default = Server Research Department

commonName         = Common Name (e.g. server FQDN or YOUR name)
commonName_default = Test CA

emailAddress         = Email Address
emailAddress_default = test@example.com

####################################################################
[ ca_extensions ]

subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid:always, issuer
basicConstraints       = critical, CA:true
keyUsage               = keyCertSign, cRLSign

Los campos anteriores están tomados de un complejo openssl.cnf(puede encontrarlo en /usr/lib/openssl.cnf), pero creo que son los elementos esenciales para crear el certificado de CA y la clave privada.

Ajusta los campos de arriba para adaptarlos a tu gusto. Los valores predeterminados le ahorran el tiempo de ingresar la misma información mientras experimenta con el archivo de configuración y las opciones de comando.

Omití las cosas relevantes para CRL, pero sus operaciones de CA deberían tenerlas. Ver openssl.cnfy la crl_extsección relacionada .

Luego, ejecute lo siguiente. La -nodesomite la contraseña o frase de contraseña para que pueda examinar el certificado. Es una muy mala idea omitir la contraseña o frase de contraseña.

$ openssl req -x509 -config openssl-ca.cnf -newkey rsa:4096 -sha256 -nodes -out cacert.pem -outform PEM

Después de que se ejecute el comando, cacert.pemserá su certificado para las operaciones de CA y cakey.pemserá la clave privada. Recuerde que la clave privada no tiene una contraseña o frase de contraseña.

Puede volcar el certificado con lo siguiente.

$ openssl x509 -in cacert.pem -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 11485830970703032316 (0x9f65de69ceef2ffc)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=US, ST=MD, L=Baltimore, CN=Test CA/emailAddress=test@example.com
        Validity
            Not Before: Jan 24 14:24:11 2014 GMT
            Not After : Feb 23 14:24:11 2014 GMT
        Subject: C=US, ST=MD, L=Baltimore, CN=Test CA/emailAddress=test@example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (4096 bit)
                Modulus:
                    00:b1:7f:29:be:78:02:b8:56:54:2d:2c:ec:ff:6d:
                    ...
                    39:f9:1e:52:cb:8e:bf:8b:9e:a6:93:e1:22:09:8b:
                    59:05:9f
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                4A:9A:F3:10:9E:D7:CF:54:79:DE:46:75:7A:B0:D0:C1:0F:CF:C1:8A
            X509v3 Authority Key Identifier:
                keyid:4A:9A:F3:10:9E:D7:CF:54:79:DE:46:75:7A:B0:D0:C1:0F:CF:C1:8A

            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Key Usage:
                Certificate Sign, CRL Sign
    Signature Algorithm: sha256WithRSAEncryption
         4a:6f:1f:ac:fd:fb:1e:a4:6d:08:eb:f5:af:f6:1e:48:a5:c7:
         ...
         cd:c6:ac:30:f9:15:83:41:c1:d1:20:fa:85:e7:4f:35:8f:b5:
         38:ff:fd:55:68:2c:3e:37

Y pruebe su propósito con lo siguiente (no se preocupe por el Any Purpose: Yes; vea "crítico, CA: FALSO" pero "CA de cualquier propósito: Sí" ).

$ openssl x509 -purpose -in cacert.pem -inform PEM
Certificate purposes:
SSL client : No
SSL client CA : Yes
SSL server : No
SSL server CA : Yes
Netscape SSL server : No
Netscape SSL server CA : Yes
S/MIME signing : No
S/MIME signing CA : Yes
S/MIME encryption : No
S/MIME encryption CA : Yes
CRL signing : Yes
CRL signing CA : Yes
Any Purpose : Yes
Any Purpose CA : Yes
OCSP helper : Yes
OCSP helper CA : Yes
Time Stamp signing : No
Time Stamp signing CA : Yes
-----BEGIN CERTIFICATE-----
MIIFpTCCA42gAwIBAgIJAJ9l3mnO7y/8MA0GCSqGSIb3DQEBCwUAMGExCzAJBgNV
...
aQUtFrV4hpmJUaQZ7ySr/RjCb4KYkQpTkOtKJOU1Ic3GrDD5FYNBwdEg+oXnTzWP
tTj//VVoLD43
-----END CERTIFICATE-----

Para la segunda parte, voy a crear otro archivo de configuración que sea fácilmente digerible. Primero, touchel openssl-server.cnf(puede hacer uno de estos para certificados de usuario también).

$ touch openssl-server.cnf

Luego ábralo y agregue lo siguiente.

HOME            = .
RANDFILE        = $ENV::HOME/.rnd

####################################################################
[ req ]
default_bits       = 2048
default_keyfile    = serverkey.pem
distinguished_name = server_distinguished_name
req_extensions     = server_req_extensions
string_mask        = utf8only

####################################################################
[ server_distinguished_name ]
countryName         = Country Name (2 letter code)
countryName_default = US

stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = MD

localityName         = Locality Name (eg, city)
localityName_default = Baltimore

organizationName            = Organization Name (eg, company)
organizationName_default    = Test Server, Limited

commonName           = Common Name (e.g. server FQDN or YOUR name)
commonName_default   = Test Server

emailAddress         = Email Address
emailAddress_default = test@example.com

####################################################################
[ server_req_extensions ]

subjectKeyIdentifier = hash
basicConstraints     = CA:FALSE
keyUsage             = digitalSignature, keyEncipherment
subjectAltName       = @alternate_names
nsComment            = "OpenSSL Generated Certificate"

####################################################################
[ alternate_names ]

DNS.1  = example.com
DNS.2  = www.example.com
DNS.3  = mail.example.com
DNS.4  = ftp.example.com

Si está desarrollando y necesita usar su estación de trabajo como servidor, es posible que deba hacer lo siguiente para Chrome. De lo contrario, Chrome puede quejarse de que un Nombre común no es válido ( ERR_CERT_COMMON_NAME_INVALID) . No estoy seguro de cuál es la relación entre una dirección IP en la SAN y un CN en este caso.

# IPv4 localhost
IP.1     = 127.0.0.1

# IPv6 localhost
IP.2     = ::1

Luego, cree la solicitud de certificado del servidor. Asegúrese de omitir -x509 *. Agregar -x509creará un certificado, y no una solicitud.

$ openssl req -config openssl-server.cnf -newkey rsa:2048 -sha256 -nodes -out servercert.csr -outform PEM

Después de que se ejecute este comando, tendrá una solicitud servercert.csry una clave privada serverkey.pem.

Y puedes inspeccionarlo de nuevo.

$ openssl req -text -noout -verify -in servercert.csr
Certificate:
    verify OK
    Certificate Request:
        Version: 0 (0x0)
        Subject: C=US, ST=MD, L=Baltimore, CN=Test Server/emailAddress=test@example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:ce:3d:58:7f:a0:59:92:aa:7c:a0:82:dc:c9:6d:
                    ...
                    f9:5e:0c:ba:84:eb:27:0d:d9:e7:22:5d:fe:e5:51:
                    86:e1
                Exponent: 65537 (0x10001)
        Attributes:
        Requested Extensions:
            X509v3 Subject Key Identifier:
                1F:09:EF:79:9A:73:36:C1:80:52:60:2D:03:53:C7:B6:BD:63:3B:61
            X509v3 Basic Constraints:
                CA:FALSE
            X509v3 Key Usage:
                Digital Signature, Key Encipherment
            X509v3 Subject Alternative Name:
                DNS:example.com, DNS:www.example.com, DNS:mail.example.com, DNS:ftp.example.com
            Netscape Comment:
                OpenSSL Generated Certificate
    Signature Algorithm: sha256WithRSAEncryption
         6d:e8:d3:85:b3:88:d4:1a:80:9e:67:0d:37:46:db:4d:9a:81:
         ...
         76:6a:22:0a:41:45:1f:e2:d6:e4:8f:a1:ca:de:e5:69:98:88:
         a9:63:d0:a7

Luego, debe firmarlo con su CA.


Ya casi está listo para firmar el certificado del servidor con su CA. La CA openssl-ca.cnfnecesita dos secciones más antes de emitir el comando.

Primero, abra openssl-ca.cnfy agregue las siguientes dos secciones.

####################################################################
[ signing_policy ]
countryName            = optional
stateOrProvinceName    = optional
localityName           = optional
organizationName       = optional
organizationalUnitName = optional
commonName             = supplied
emailAddress           = optional

####################################################################
[ signing_req ]
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid,issuer
basicConstraints       = CA:FALSE
keyUsage               = digitalSignature, keyEncipherment

En segundo lugar, agregue lo siguiente a la [ CA_default ]sección de openssl-ca.cnf. Los dejé afuera antes, porque pueden complicar las cosas (no se usaban en ese momento). Ahora verás cómo se usan, así que espero que tengan sentido.

base_dir      = .
certificate   = $base_dir/cacert.pem   # The CA certifcate
private_key   = $base_dir/cakey.pem    # The CA private key
new_certs_dir = $base_dir              # Location for new certs after signing
database      = $base_dir/index.txt    # Database index file
serial        = $base_dir/serial.txt   # The current serial number

unique_subject = no  # Set to 'no' to allow creation of
                     # several certificates with same subject.

Tercero, toque index.txty serial.txt:

$ touch index.txt
$ echo '01' > serial.txt

Luego, realice lo siguiente:

$ openssl ca -config openssl-ca.cnf -policy signing_policy -extensions signing_req -out servercert.pem -infiles servercert.csr

Deberías ver algo similar a lo siguiente:

Using configuration from openssl-ca.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'US'
stateOrProvinceName   :ASN.1 12:'MD'
localityName          :ASN.1 12:'Baltimore'
commonName            :ASN.1 12:'Test CA'
emailAddress          :IA5STRING:'test@example.com'
Certificate is to be certified until Oct 20 16:12:39 2016 GMT (1000 days)
Sign the certificate? [y/n]:Y

1 out of 1 certificate requests certified, commit? [y/n]Y
Write out database with 1 new entries
Data Base Updated

Después de que se ejecute el comando, tendrá un certificado de servidor recién acuñado servercert.pem. La clave privada se creó anteriormente y está disponible en serverkey.pem.

Finalmente, puede inspeccionar su certificado recién acuñado con lo siguiente:

$ openssl x509 -in servercert.pem -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 9 (0x9)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=US, ST=MD, L=Baltimore, CN=Test CA/emailAddress=test@example.com
        Validity
            Not Before: Jan 24 19:07:36 2014 GMT
            Not After : Oct 20 19:07:36 2016 GMT
        Subject: C=US, ST=MD, L=Baltimore, CN=Test Server
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:ce:3d:58:7f:a0:59:92:aa:7c:a0:82:dc:c9:6d:
                    ...
                    f9:5e:0c:ba:84:eb:27:0d:d9:e7:22:5d:fe:e5:51:
                    86:e1
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                1F:09:EF:79:9A:73:36:C1:80:52:60:2D:03:53:C7:B6:BD:63:3B:61
            X509v3 Authority Key Identifier:
                keyid:42:15:F2:CA:9C:B1:BB:F5:4C:2C:66:27:DA:6D:2E:5F:BA:0F:C5:9E

            X509v3 Basic Constraints:
                CA:FALSE
            X509v3 Key Usage:
                Digital Signature, Key Encipherment
            X509v3 Subject Alternative Name:
                DNS:example.com, DNS:www.example.com, DNS:mail.example.com, DNS:ftp.example.com
            Netscape Comment:
                OpenSSL Generated Certificate
    Signature Algorithm: sha256WithRSAEncryption
         b1:40:f6:34:f4:38:c8:57:d4:b6:08:f7:e2:71:12:6b:0e:4a:
         ...
         45:71:06:a9:86:b6:0f:6d:8d:e1:c5:97:8d:fd:59:43:e9:3c:
         56:a5:eb:c8:7e:9f:6b:7a

Anteriormente, se añade el texto siguiente CA_default: copy_extensions = copy. Esta copia copia la extensión proporcionada por la persona que realiza la solicitud.

Si omite copy_extensions = copy, su certificado de servidor carecerá de los nombres alternativos del sujeto (SAN) como www.example.comy mail.example.com.

Si usa copy_extensions = copy, pero no revisa la solicitud, entonces el solicitante podría engañarlo para que firme algo como una raíz subordinada (en lugar de un servidor o un certificado de usuario). Lo que significa que él / ella podrá acuñar certificados que se encadenan a su raíz de confianza. Asegúrese de verificar la solicitud openssl req -verifyantes de firmar.


Si lo omite unique_subject o lo establece yes, solo se le permitirá crear un certificado con el nombre distinguido del sujeto.

unique_subject = yes            # Set to 'no' to allow creation of
                                # several ctificates with same subject.

Intentar crear un segundo certificado mientras experimentas resultará en lo siguiente al firmar el certificado de tu servidor con la clave privada de la CA:

Sign the certificate? [y/n]:Y
failed to update database
TXT_DB error number 2

Entonces unique_subject = noes perfecto para probar.


Si desea asegurarse de que el Nombre de la organización sea ​​coherente entre las CA autofirmadas, la CA subordinada y los certificados de entidad final, agregue lo siguiente a sus archivos de configuración de CA:

[ policy_match ]
organizationName = match

Si desea permitir que cambie el Nombre de la organización , utilice:

[ policy_match ]
organizationName = supplied

Existen otras reglas sobre el manejo de nombres DNS en los certificados X.509 / PKIX. Consulte estos documentos para conocer las reglas:

RFC 6797 y RFC 7469 están listados, porque son más restrictivos que los otros RFC y documentos CA / B. Las RFC 6797 y 7469 tampoco permiten una dirección IP.

jww
fuente
44
Gracias por esa extensa respuesta ... Sin embargo, estoy un poco perdido aquí. Lo que entendí de lo que escribió: openssl reqse usa para generar CSR, openssl req -x509se usa para generar un certificado de CA (vi en otro lugar que también podría crear un certificado autofirmado), openssl case usa para firmar un CSR con un certificado de CA. ¿Correcto? Lo que también me confunde es que las mismas partes del archivo openssl.cnf se usan con diferentes valores dependiendo del comando ... Creo que ahora estoy totalmente perdido.
Bernard Rosset
27
Primero, openssl req -x509se usa para crear la CA. En segundo lugar, openssl reqse usa para crear la CSR del servidor. En tercer lugar, openssl case utiliza para crear el certificado del servidor y certificarlo con la firma de la CA.
jww
1
"Lo que también me confunde es que las mismas partes del openssl.cnf ..." - Correcto. Es por eso que los descubrí para ti openssl-ca.cnfy openssl-server.cnf. Después de acostumbrarse a ellos y cómo se invocan las secciones, puede combinarlos en una monstruosidad openssl.cnf.
jww
1
@JeffPuckettII: es una sección común. Es utilizado por la utilidad CA y la utilidad Req. Deben ser extensiones v3.
jww
55
@ahnkle Use la opción -days para cualquier cosa diferente de los 30 días predeterminados. Documentos de OpenSSL
george
14

Además de la respuesta de @jww, me gustaría decir que la configuración en openssl-ca.cnf,

default_days     = 1000         # How long to certify for

define el número predeterminado de días que el certificado firmado por este root-ca será válido. Para establecer la validez de root-ca, debe usar la opción '-days n' en:

openssl req -x509 -days 3000 -config openssl-ca.cnf -newkey rsa:4096 -sha256 -nodes -out cacert.pem -outform PEM

De lo contrario, su root-ca será válida solo por el mes predeterminado y cualquier certificado firmado por esta CA raíz también tendrá una validez de un mes.

humilde_lobo
fuente