Come si firma una richiesta di firma del certificato con la propria autorità di certificazione?

Durante la mia ricerca, ho trovato diversi modi per firmare una richiesta di firma del certificato SSL:

  1. Usando il modulo x509 :

     openssl x509 -req -days 360 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt 
  2. Utilizzando il modulo ca :

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

Nota: non sono sicuro dell’uso dei parametri corretti per questo. Si prega di avvisare l’uso corretto se devo usarlo.

In che modo si dovrebbe utilizzare per firmare le richieste di certificati con l’Autorità di certificazione? Un metodo è migliore dell’altro (ad esempio, uno è deprecato)?

 1. Using the x509 module openssl x509 ... ... 2 Using the ca module openssl ca ... ... 

Quello che ti manca è il preludio a quei comandi.

Questo è un processo in due fasi. Prima si imposta la CA e quindi si firma un certificato di quadro finale (ovvero server o utente). Entrambi i due comandi elidono i due passaggi in uno. Entrambi suppongono di avere già un file di configurazione OpenSSL già configurato per certificati CA e Server ( quadro finale).


Per prima cosa, crea un file di configurazione di base:

 $ touch openssl-ca.cnf 

Quindi, aggiungi il seguente:

 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 (eg server FQDN or YOUR name) commonName_default = Test CA emailAddress = Email Address emailAddress_default = [email protected] #################################################################### [ ca_extensions ] subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer basicConstraints = critical, CA:true keyUsage = keyCertSign, cRLSign 

I campi sopra sono presi da un più complesso openssl.cnf (lo puoi trovare in /usr/lib/openssl.cnf ), ma penso che siano essenziali per la creazione del certificato CA e della chiave privata.

Modifica i campi sopra per soddisfare i tuoi gusti. Le impostazioni predefinite ti fanno risparmiare tempo nell’inserire le stesse informazioni mentre sperimentano con il file di configurazione e le opzioni di comando.

Ho omesso il contenuto dell’elenco CRL, ma le operazioni CA dovrebbero averle. Vedi openssl.cnf e la relativa sezione crl_ext .

Quindi, eseguire quanto segue. I -nodes omettono la password o passphrase in modo da poter esaminare il certificato. È una pessima idea di omettere la password o la passphrase.

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

Dopo l’esecuzione del comando, cacert.pem sarà il certificato per le operazioni CA e cakey.pem sarà la chiave privata. Ricorda che la chiave privata non ha password o passphrase.

È ansible scaricare il certificato con il seguente.

 $ 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/[email protected] 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/[email protected] 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 

E testare il suo scopo con quanto segue (non preoccuparti di Any Purpose: Yes ; vedi “Critico, CA: FALSO” ma “Qualsiasi scopo CA: 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----- 

Per la seconda parte, creerò un altro file conf facilmente digeribile. Innanzitutto, touch openssl-server.cnf (è ansible creare anche uno di questi per i certificati utente).

 $ touch openssl-server.cnf 

Quindi aprilo e aggiungi quanto segue.

 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 (eg server FQDN or YOUR name) commonName_default = Test Server emailAddress = Email Address emailAddress_default = [email protected] #################################################################### [ 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 

Se stai sviluppando e hai bisogno di utilizzare la tua workstation come server, potresti dover eseguire quanto segue per Chrome. In caso contrario, Chrome potrebbe lamentarsi che un nome comune non è valido ( ERR_CERT_COMMON_NAME_INVALID ) . Non sono sicuro di quale sia la relazione tra un indirizzo IP nella SAN e una CN in questa istanza.

 # IPv4 localhost IP.1 = 127.0.0.1 # IPv6 localhost IP.2 = ::1 

Quindi, creare la richiesta del certificato del server. Assicurati di omettere -x509 *. L’aggiunta di -x509 creerà un certificato e non una richiesta.

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

Dopo che questo comando è stato eseguito, avrai una richiesta in servercert.csr e una chiave privata in serverkey.pem .

E puoi ispezionarlo di nuovo.

 $ 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/[email protected] 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 

Successivamente, devi firmarlo con la tua CA.


Sei quasi pronto per firmare il certificato del server dalla tua CA. openssl-ca.cnf della CA ha bisogno di altre due sezioni prima di emettere il comando.

Per prima cosa apri openssl-ca.cnf e aggiungi le seguenti due sezioni.

 #################################################################### [ 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 

Secondo, aggiungi quanto segue alla sezione [ CA_default ] di openssl-ca.cnf . Li ho lasciati prima perché possono complicare le cose (erano inutilizzati al momento). Ora vedrai come vengono usati, quindi spero che abbiano senso.

 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. 

In terzo luogo, tocca index.txt e serial.txt :

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

Quindi, eseguire quanto segue:

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

Dovresti vedere simile al seguente:

 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:'[email protected]' 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 

Dopo l’esecuzione del comando, si avrà un certificato del server appena rilasciato in servercert.pem . La chiave privata è stata creata in precedenza ed è disponibile in serverkey.pem .

Infine, è ansible controllare il certificato appena coniato con il seguente.

 $ 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/[email protected] 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 

In precedenza, hai aggiunto quanto segue a CA_default : copy_extensions = copy . Questo copia l’estensione fornita dalla persona che effettua la richiesta.

Se si omette copy_extensions = copy , al certificato del server mancheranno i nomi alternativi object (SAN) come www.example.com e mail.example.com .

Se si utilizza copy_extensions = copy ma non si esamina la richiesta, il richiedente potrebbe essere in grado di indurti a firmare qualcosa come una root subordinata (piuttosto che un server o un certificato utente). Il che significa che sarà in grado di coniare certificati che riconducono alla tua radice attendibile. Assicurati di verificare la richiesta con openssl req -verify prima di firmare.


Se ometti unique_subject o lo si imposta su yes , sarà ansible creare un solo certificato con il nome distinto dell’object.

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

Provare a creare un secondo certificato durante la sperimentazione si tradurrà in quanto segue quando si firma il certificato del server con la chiave privata della CA:

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

So unique_subject = no è perfetto per i test.


Se si desidera garantire che il nome organizzativo sia coerente tra CA autofirmate, CA subordinata e certificati di entity framework finale, aggiungere quanto segue ai file di configurazione della CA:

 [ policy_match ] organizationName = match 

Se si desidera consentire la modifica del nome organizzativo, utilizzare:

 [ policy_match ] organizationName = supplied 

Esistono altre regole relative alla gestione dei nomi DNS nei certificati X.509 / PKIX. Fare riferimento a questi documenti per le regole:

  • RFC 5280, Internet X.509 Profilo di infrastruttura a chiave pubblica e profilo di revoche di certificati (CRL)
  • RFC 6125, Rappresentazione e verifica dell’identity framework del servizio applicativo basato su dominio all’interno dell’infrastruttura a chiave pubblica di Internet che utilizza i certificati X.509 (PKIX) nel contesto di Transport Layer Security (TLS)
  • RFC 6797, Appendice A, HTTP Strict Transport Security (HSTS)
  • RFC 7469, estensione Pinning chiave pubblica per HTTP
  • Requisiti di base del forum CA / Browser
  • Linee guida per la convalida estesa del CA / Browser Forum

RFC 6797 e RFC 7469 sono elencati perché sono più restrittivi rispetto agli altri documenti RFC e CA / B. Anche gli RFC 6797 e 7469 non consentono un indirizzo IP.

Oltre alla risposta di @jww, vorrei dire che la configurazione di openssl-ca.cnf

 default_days = 1000 # how long to certify for 

definisce il numero predefinito di giorni in cui il certificato firmato da questo root-ca sarà valido, per impostare la validità di root-ca si dovrebbe usare l’opzione ‘-days n’ in

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

In caso contrario, root-ca sarà valido solo per 1 mese predefinito e qualsiasi certificato firmato da questo rot-ca avrà anche validità di 1 mese.