renew - openssl req




Come creare un certificato autofirmato con openssl? (9)

Sto aggiungendo il supporto https a un dispositivo Linux incorporato. Ho provato a generare un certificato autofirmato con questi passaggi:

openssl req -new > cert.csr
openssl rsa -in privkey.pem -out key.pem
openssl x509 -in cert.csr -out cert.pem -req -signkey key.pem -days 1001
cat key.pem>>cert.pem

Funziona, ma ho alcuni errori con, ad esempio, google chrome:

Questo probabilmente non è il sito che stai cercando!
Il certificato di sicurezza del sito non è affidabile!

Mi sto perdendo qualcosa? È questo il modo corretto di costruire un certificato autofirmato?


Genera chiavi

Sto usando /etc/mysql per l'archiviazione cert perché /etc/apparmor.d/usr.sbin.mysqld contiene /etc/mysql/*.pem r .

sudo su -
cd /etc/mysql
openssl genrsa -out ca-key.pem 2048;
openssl req -new -x509 -nodes -days 1000 -key ca-key.pem -out ca-cert.pem;
openssl req -newkey rsa:2048 -days 1000 -nodes -keyout server-key.pem -out server-req.pem;
openssl x509 -req -in server-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem;
openssl req -newkey rsa:2048 -days 1000 -nodes -keyout client-key.pem -out client-req.pem;
openssl x509 -req -in client-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem;

Aggiungi configurazione

/etc/mysql/my.cnf

[client]
ssl-ca=/etc/mysql/ca-cert.pem
ssl-cert=/etc/mysql/client-cert.pem
ssl-key=/etc/mysql/client-key.pem

[mysqld]
ssl-ca=/etc/mysql/ca-cert.pem
ssl-cert=/etc/mysql/server-cert.pem
ssl-key=/etc/mysql/server-key.pem

Nella mia configurazione, il server ubuntu ha effettuato l'accesso a: /var/log/mysql/error.log

Note di follow-up:

  • SSL error: Unable to get certificate from '...'

    A Mysql potrebbe essere negato l'accesso in lettura al tuo file cert se non è nella configurazione di apparmor . Come menzionato nei passaggi precedenti, salva tutti i nostri certificati come file .pem nella directory /etc/mysql/ che è approvata di default da apparmor (o modifica il tuo apparmor / SELinux per consentire l'accesso ovunque sia memorizzato).

  • SSL error: Unable to get private key

    La tua versione del server mysql potrebbe non supportare il formato predefinito rsa:2048 .

    Covert generato rsa:2048 in rsa normale con:

    openssl rsa -in server-key.pem -out server-key.pem
    openssl rsa -in client-key.pem -out client-key.pem
    
  • Verifica se il server locale supporta ssl :

    mysql -u root -p
    mysql> show variables like "%ssl%"; 
    +---------------+----------------------------+
    | Variable_name | Value                      |
    +---------------+----------------------------+
    | have_openssl  | YES                        |
    | have_ssl      | YES                        |
    | ssl_ca        | /etc/mysql/ca-cert.pem     |
    | ssl_capath    |                            |
    | ssl_cert      | /etc/mysql/server-cert.pem |
    | ssl_cipher    |                            |
    | ssl_key       | /etc/mysql/server-key.pem  |
    +---------------+----------------------------+
    
  • La verifica di una connessione al db è crittografata con ssl :

    Verifica della connessione

    Quando si accede all'istanza MySQL, è possibile effettuare la query:

    show status like 'Ssl_cipher'; 
    

    Se la tua connessione non è crittografata, il risultato sarà vuoto:

    mysql> show status like 'Ssl_cipher'; 
    +---------------+-------+ 
    | Variable_name | Value | 
    +---------------+-------+ 
    | Ssl_cipher    |       |  
    +---------------+-------+ 
    1 row in set (0.00 sec) 
    

    Altrimenti, mostrerebbe una stringa di lunghezza diversa da zero per la cifra in uso:

    mysql> show status like 'Ssl_cipher'; 
    +---------------+--------------------+ 
    | Variable_name | Value              | 
    +---------------+--------------------+ 
    | Ssl_cipher    | DHE-RSA-AES256-SHA |  
    +---------------+--------------------+ 
    1 row in set (0.00 sec) 
    
  • Richiedi ssl per la connessione dell'utente specifico ('require ssl'):

    • SSL

    Indica al server di consentire solo connessioni crittografate SSL per l'account.

    GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
      REQUIRE SSL;
    

    Per connettersi, il client deve specificare l'opzione --ssl-ca per autenticare il certificato del server e può inoltre specificare le opzioni --ssl-key e --ssl-cert. Se non viene specificata l'opzione --ssl-ca né l'opzione --ssl-capath, il client non autentica il certificato del server.

Link alternativo: tutorial lungo qui http://www.madirish.net/214


Mi sto perdendo qualcosa? È questo il modo corretto di costruire un certificato autofirmato?

È facile creare un certificato autofirmato. Devi solo usare il comando openssl req . Può essere complicato crearne uno che possa essere consumato dalla più ampia selezione di client, come browser e strumenti da riga di comando.

È difficile perché i browser hanno il proprio set di requisiti e sono più restrittivi di IETF. I requisiti utilizzati dai browser sono documentati nei forum CA / Browser (vedere i riferimenti di seguito). Le restrizioni si presentano in due aree chiave: (1) trust ancore e (2) nomi DNS.

I browser moderni (come il warez che stiamo usando nel 2014/2015) vogliono un certificato che ritorni su un'ancora di fiducia e vogliono che i nomi DNS siano presentati in modo particolare nel certificato. E i browser si stanno attivamente spostando contro i certificati dei server autofirmati

Alcuni browser non facilitano l'importazione di un certificato server autofirmato. Infatti, non è possibile con alcuni browser, come il browser di Android. Quindi la soluzione completa è diventare la tua autorità.

In assenza di diventare la propria autorità, è necessario ottenere i nomi DNS giusto per dare al certificato le maggiori possibilità di successo. Ma ti incoraggerei a diventare la tua autorità. È facile diventare la tua autorità e affiancherà tutti i problemi di fiducia (chi è meglio fidarsi di te stesso?).

Questo probabilmente non è il sito che stai cercando!
Il certificato di sicurezza del sito non è affidabile!

Questo perché i browser utilizzano un elenco predefinito di trust ancore per convalidare i certificati del server. Un certificato autofirmato non riconduce a un ancoraggio affidabile.

Il modo migliore per evitare questo è:

  1. Crea la tua autorità (cioè, diventa una CA)
  2. Creare una richiesta di firma del certificato (CSR) per il server
  3. Firma il CSR del server con la chiave CA.
  4. Installa il certificato del server sul server
  5. Installa il certificato CA sul client

Fase 1: creare la propria autorità significa semplicemente creare un certificato autofirmato con CA: true utilizzo delle chiavi corretto e corretto. Ciò significa che il Soggetto e l'Emittente sono la stessa entità, CA è impostata su true in Vincoli di base (dovrebbe anche essere contrassegnata come critica), l'utilizzo della chiave è keyCertSign e crlSign (se si utilizzano i CRL) e l'identificatore della chiave oggetto (SKI ) è lo stesso dell'Autent Key Identifier (AKI).

Per diventare un'autorità di certificazione, vedere Come si firma la richiesta di firma del certificato con l'autorità di certificazione? su Overflow dello stack. Quindi, importa la tua CA nel Trust Store utilizzato dal browser.

I passaggi 2 - 4 sono approssimativamente ciò che si fa ora per un server pubblico quando si collegano i servizi di una CA come Startcom o CAcert . I passaggi 1 e 5 consentono di evitare l'autorizzazione di terze parti e di agire come la propria autorità (chi è meglio fidarsi di se stessi?).

Il modo migliore per evitare l'avviso del browser è affidarsi al certificato del server. Ma alcuni browser, come il browser predefinito di Android, non ti permettono di farlo. Quindi non funzionerà mai sulla piattaforma.

Il problema dei browser (e di altri agenti utente simili) che non si fidano dei certificati autofirmati sarà un grosso problema nell'Internet of Things (IoT). Ad esempio, che cosa succederà quando ci si connette al termostato o al frigorifero per programmarlo? La risposta è, nulla di buono per quanto riguarda l'esperienza dell'utente.

Il gruppo di lavoro WebAppSec del W3C sta iniziando a esaminare il problema. Vedi, ad esempio, Proposta: Contrassegnare HTTP come non protetto .

Come creare un certificato autofirmato con openssl?

I comandi seguenti e il file di configurazione creano un certificato autofirmato (mostra anche come creare una richiesta di firma). Si differenziano dalle altre risposte per un aspetto: i nomi DNS utilizzati per il certificato autofirmato sono nell'oggetto Nome alternativo oggetto (SAN) e non nel Nome comune (CN) .

I nomi DNS vengono inseriti nella SAN tramite il file di configurazione con la riga subjectAltName = @alternate_names (non è possibile eseguirlo tramite la riga di comando). Poi c'è una sezione alternate_names nel file di configurazione (dovresti accordarla in base ai tuoi gusti):

[ alternate_names ]

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

# Add these if you need them. But usually you don't want them or
#   need them in production. You may need them for development.
# DNS.5       = localhost
# DNS.6       = localhost.localdomain
# DNS.7       = 127.0.0.1

# IPv6 localhost
# DNS.8     = ::1

È importante inserire il nome DNS nella SAN e non nella CN perché sia la IETF che i CA / Browser Forum specificano la pratica. Inoltre specificano che i nomi DNS nel CN ​​sono deprecati (ma non proibiti). Se si inserisce un nome DNS nel CN, deve essere incluso nella SAN sotto i criteri CA / B. Quindi non puoi evitare di utilizzare il nome alternativo dell'oggetto.

Se non si inseriscono i nomi DNS nella SAN, il certificato non riuscirà a convalidare sotto un browser e altri agenti utente che seguono le linee guida del CA / Browser Forum.

Correlati: i browser seguono le politiche del CA / Browser Forum; e non le politiche IETF. Questo è uno dei motivi per cui un certificato creato con OpenSSL (che generalmente segue IETF) a volte non viene convalidato da un browser (i browser seguono il CA / B). Sono standard diversi, hanno diverse politiche di emissione e diversi requisiti di convalida.

Creare un certificato autofirmato (notare l'aggiunta dell'opzione -x509 ):

openssl req -config example-com.conf -new -x509 -sha256 -newkey rsa:2048 -nodes \
    -keyout example-com.key.pem -days 365 -out example-com.cert.pem

Creare una richiesta di firma (notare la mancanza dell'opzione -x509 ):

openssl req -config example-com.conf -new -sha256 -newkey rsa:2048 -nodes \
    -keyout example-com.key.pem -days 365 -out example-com.req.pem

Stampa un certificato autofirmato :

openssl x509 -in example-com.cert.pem -text -noout

Stampa una richiesta di firma :

openssl req -in example-com.req.pem -text -noout

File di configurazione (passato tramite -config opzione -config )

[ req ]
default_bits        = 2048
default_keyfile     = server-key.pem
distinguished_name  = subject
req_extensions      = req_ext
x509_extensions     = x509_ext
string_mask         = utf8only

# The Subject DN can be formed using X501 or RFC 4514 (see RFC 4519 for a description).
#   Its sort of a mashup. For example, RFC 4514 does not provide emailAddress.
[ subject ]
countryName         = Country Name (2 letter code)
countryName_default     = US

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

localityName            = Locality Name (eg, city)
localityName_default        = New York

organizationName         = Organization Name (eg, company)
organizationName_default    = Example, LLC

# Use a friendly name here because its presented to the user. The server's DNS
#   names are placed in Subject Alternate Names. Plus, DNS names here is deprecated
#   by both IETF and CA/Browser Forums. If you place a DNS name here, then you 
#   must include the DNS name in the SAN too (otherwise, Chrome and others that
#   strictly follow the CA/Browser Baseline Requirements will fail).
commonName          = Common Name (e.g. server FQDN or YOUR name)
commonName_default      = Example Company

emailAddress            = Email Address
emailAddress_default        = [email protected]

# Section x509_ext is used when generating a self-signed certificate. I.e., openssl req -x509 ...
[ x509_ext ]

subjectKeyIdentifier        = hash
authorityKeyIdentifier  = keyid,issuer

# You only need digitalSignature below. *If* you don't allow
#   RSA Key transport (i.e., you use ephemeral cipher suites), then
#   omit keyEncipherment because that's key transport.
basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

# RFC 5280, Section 4.2.1.12 makes EKU optional
#   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
#   In either case, you probably only need serverAuth.
# extendedKeyUsage  = serverAuth, clientAuth

# Section req_ext is used when generating a certificate signing request. I.e., openssl req ...
[ req_ext ]

subjectKeyIdentifier        = hash

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

# RFC 5280, Section 4.2.1.12 makes EKU optional
#   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
#   In either case, you probably only need serverAuth.
# extendedKeyUsage  = serverAuth, clientAuth

[ alternate_names ]

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

# Add these if you need them. But usually you don't want them or
#   need them in production. You may need them for development.
# DNS.5       = localhost
# DNS.6       = localhost.localdomain
# DNS.7       = 127.0.0.1

# IPv6 localhost
# DNS.8     = ::1

Potrebbe essere necessario 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

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

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.


Hai la procedura generale corretta. La sintassi per il comando è sotto.

openssl req -new -key {private key file} -out {output file}

Tuttavia, gli avvisi vengono visualizzati perché il browser non è stato in grado di verificare l'identità convalidando il certificato con un'autorità di certificazione (CA) nota.

Poiché si tratta di un certificato autofirmato, non esiste una CA e si può tranquillamente ignorare l'avviso e procedere. Se si desidera ottenere un certificato reale che sarà riconoscibile da chiunque su Internet pubblica, la procedura è la seguente.

  1. Genera una chiave privata
  2. Usa quella chiave privata per creare un file CSR
  3. Invia CSR a CA (Verisign o altri, ecc.)
  4. Installa il certificato ricevuto da CA sul server web
  5. Aggiungi altri certificati alla catena di autenticazione in base al tipo di certificato

Ho ulteriori dettagli su questo in un post su https://bigthinkingapplied.com/secure-the-connection-installing-certificates-on-3-common-web-servers/


I browser moderni generano ora un errore di sicurezza per i certificati autofirmati altrimenti ben strutturati se mancano una SAN (Subject Alternate Name). OpenSSL non fornisce un modo da riga di comando per specificare questo , quindi molti tutorial e segnalibri di sviluppatori sono improvvisamente obsoleti.

Il modo più veloce per essere nuovamente operativi è un breve file di configurazione stand-alone:

  1. Creare un file di configurazione OpenSSL (esempio: req.cnf )

    [req]
    distinguished_name = req_distinguished_name
    x509_extensions = v3_req
    prompt = no
    [req_distinguished_name]
    C = US
    ST = VA
    L = SomeCity
    O = MyCompany
    OU = MyDivision
    CN = www.company.com
    [v3_req]
    keyUsage = critical, digitalSignature, keyAgreement
    extendedKeyUsage = serverAuth
    subjectAltName = @alt_names
    [alt_names]
    DNS.1 = www.company.com
    DNS.2 = company.com
    DNS.3 = company.net
    
  2. Crea il certificato facendo riferimento a questo file di configurazione

    openssl req -x509 -nodes -days 730 -newkey rsa:2048 \
     -keyout cert.key -out cert.pem -config req.cnf -sha256
    

Esempio di configurazione da https://support.citrix.com/article/CTX135602


Non posso commentare, quindi lo metto come una risposta separata. Ho trovato alcuni problemi con la risposta one-liner accettata:

  • Il one-liner include una passphrase nella chiave.
  • L'one-liner usa SHA1 che in molti browser genera avvisi in console.

Ecco una versione semplificata che rimuove la passphrase, aumenta la sicurezza per sopprimere gli avvertimenti e include un suggerimento nei commenti da passare in -subj per rimuovere l'elenco completo delle domande:

openssl genrsa -out server.key 2048
openssl rsa -in server.key -out server.key
openssl req -sha256 -new -key server.key -out server.csr -subj '/CN=localhost'
openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt

Sostituisci "localhost" con qualsiasi dominio tu richieda. Sarà necessario eseguire i primi due comandi uno per uno, in quanto openssl richiederà una passphrase.

Per unire i due in un file .pem:

cat server.crt server.key > cert.pem

Puoi farlo in un solo comando:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365

Puoi anche aggiungere -nodes (abbreviazione di no DES ) se non vuoi proteggere la tua chiave privata con una passphrase, altrimenti ti verrà richiesta una password "almeno di 4 caratteri". Il parametro days (365) è possibile sostituire con qualsiasi numero per influire sulla data di scadenza. Quindi ti chiederà cose come "Nome Paese", ma puoi semplicemente premere invio e accettare i valori predefiniti.

Aggiungi -subj '/CN=localhost' per sopprimere le domande sul contenuto del certificato (sostituire localhost con il dominio desiderato)

I certificati autofirmati non vengono convalidati con terze parti a meno che non vengano importati precedentemente nei browser. Se è necessaria maggiore sicurezza, è necessario utilizzare un certificato firmato da una CA.


Raccomanderei di aggiungere il parametro -sha256 , per usare l'algoritmo hash SHA-2, perché i principali browser stanno considerando di mostrare "certificati SHA-1" come non sicuri.

La stessa riga di comando dalla risposta accettata - @diegows con aggiunto -sha256

openssl req -x509 -sha256 -newkey rsa: 2048 -keyout key.pem -out cert.pem -days XXX

Ulteriori informazioni nel blog sulla sicurezza di Google .

Aggiornamento maggio 2018. Come molti hanno notato nei commenti che l'utilizzo di SHA-2 non aggiunge alcuna sicurezza al certificato autofirmato. Ma consiglio comunque di usarlo come una buona abitudine di non usare funzioni hash crittografiche obsolete / non sicure. La spiegazione completa è disponibile in: https://security.stackexchange.com/questions/91913/why-is-it-fine-for-certificates-above-the-end-entity-certificate-to-be-sha1-base


Una fodera 2017:

openssl req \
-newkey rsa:2048 \
-x509 \
-nodes \
-keyout server.pem \
-new \
-out server.pem \
-subj /CN=localhost \
-reqexts SAN \
-extensions SAN \
-config <(cat /System/Library/OpenSSL/openssl.cnf \
    <(printf '[SAN]\nsubjectAltName=DNS:localhost')) \
-sha256 \
-days 3650

Questo funziona anche in Chrome 57, poiché fornisce la SAN, senza avere un altro file di configurazione. Tratto da una risposta here . Ciò crea un singolo file .pem che contiene sia la chiave privata che il certificato. Puoi spostarli in file .pem separati, se necessario.


oneliner v2017:

CentOS:

openssl req -x509 -nodes -sha256 -newkey rsa:2048 \
-keyout localhost.key -out localhost.crt \
-days 3650 \
-subj "CN=localhost" \
-reqexts SAN -extensions SAN \
-config <(cat /etc/pki/tls/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=IP:127.0.0.1,DNS:localhost"))

ubuntu:

openssl req -x509 -nodes -sha256 -newkey rsa:2048 \
-keyout localhost.key -out localhost.crt \
-days 3650 \
-subj "CN=localhost" \
-reqexts SAN -extensions SAN \
-config <(cat /etc/ssl/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=IP:127.0.0.1,DNS:localhost"))




x509certificate