Como você assina uma solicitação de assinatura de certificado com sua autoridade de certificação?

195

Durante minha pesquisa, encontrei várias maneiras de assinar uma solicitação de assinatura de certificado SSL:

  1. Usando o x509módulo:

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

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

Nota: Não tenho certeza do uso dos parâmetros corretos para este. Por favor, informe o uso correto se eu quiser usá-lo.

Como usar para assinar solicitações de certificado com sua Autoridade de Certificação? Um método é melhor que o outro (por exemplo, um sendo preterido)?

Bernard Rosset
fonte
1
Eu gosto desse pequeno script que configura uma autoridade de certificação e permite gerar certificados "subordinados" assinados. Observe que, se você deseja que seu sistema fique satisfeito com as certezas (como S / MIME ou outros enfeites), é necessário adicionar o certificado da CA como uma "raiz confiável".
jar
Pelo que posso ver, caé para casos em que você é mais sério ao se tornar um CA.
X-yuri
Você pode achar minha resposta interessante.
X-yuri
Stack Overflow é um site para perguntas sobre programação e desenvolvimento. Esta questão parece estar fora de tópico, porque não se trata de programação ou desenvolvimento. Consulte Quais tópicos posso perguntar aqui na Central de Ajuda. Talvez o Superusuário ou o Unix e Linux Stack Exchange sejam um lugar melhor para perguntar.
JWW

Respostas:

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

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

Está faltando o prelúdio para esses comandos.

Este é um processo de duas etapas. Primeiro, você configura sua autoridade de certificação e, em seguida, assina um certificado de entidade final (também conhecido como servidor ou usuário). Os dois comandos descrevem as duas etapas em uma. E ambos assumem que você já possui um arquivo de configuração do OpenSSL para os certificados de CA e de servidor (entidade final).


Primeiro, crie um arquivo de configuração básica :

$ touch openssl-ca.cnf

Em seguida, adicione o seguinte:

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

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

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

Os campos acima são retirados de um campo mais complexo openssl.cnf(você pode encontrá-lo /usr/lib/openssl.cnf), mas acho que eles são essenciais para criar o certificado de CA e a chave privada.

Ajuste os campos acima para se adequar ao seu gosto. Os padrões economizam seu tempo para inserir as mesmas informações ao experimentar o arquivo de configuração e as opções de comando.

Omiti o material relevante para a CRL, mas suas operações de CA devem tê-lo. Veja openssl.cnfe a crl_extseção relacionada .

Em seguida, execute o seguinte. O -nodesomite a senha ou frase secreta para que você possa examinar o certificado. É uma muito ideia para omitir a senha ou frase secreta.

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

Após a execução do comando, cacert.pemserá o seu certificado para operações da CA e cakey.pemserá a chave privada. Lembre-se de que a chave privada não possui uma senha ou senha.

Você pode despejar o certificado com o seguinte.

$ 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 teste seu objetivo com o seguinte (não se preocupe com o Any Purpose: Yes; consulte "CA crítica: FALSE", mas "CA com qualquer finalidade: Sim" ).

$ 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-----

Na parte dois, vou criar outro arquivo de configuração que seja facilmente digerível. Primeiro, toucho openssl-server.cnf(você também pode criar um desses certificados de usuário).

$ touch openssl-server.cnf

Em seguida, abra-o e adicione o seguinte.

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 = [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 você estiver desenvolvendo e precisar usar sua estação de trabalho como servidor, faça o seguinte no Chrome. Caso contrário, o Chrome poderá reclamar que um Nome Comum é inválido ( ERR_CERT_COMMON_NAME_INVALID) . Não tenho certeza de qual é a relação entre um endereço IP na SAN e uma CN nessa instância.

# IPv4 localhost
IP.1     = 127.0.0.1

# IPv6 localhost
IP.2     = ::1

Em seguida, crie a solicitação de certificado do servidor. Certifique-se de omitir -x509 *. A adição -x509criará um certificado, e não uma solicitação.

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

Após a execução deste comando, você terá uma solicitação servercert.csre uma chave privada serverkey.pem.

E você pode inspecionar novamente.

$ 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

Em seguida, você deve assiná-lo com sua autoridade de certificação.


Você está quase pronto para assinar o certificado do servidor por sua CA. A CA openssl-ca.cnfprecisa de mais duas seções antes de emitir o comando.

Primeiro, abra openssl-ca.cnfe adicione as duas seções a seguir.

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

Segundo, adicione o seguinte à [ CA_default ]seção de openssl-ca.cnf. Eu os deixei de fora mais cedo, porque eles podem complicar as coisas (eles não eram usados ​​na época). Agora você verá como eles são usados, por isso espero que façam 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.

Terceiro, toque index.txte serial.txt:

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

Em seguida, execute o seguinte:

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

Você deve ver semelhante ao seguinte:

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

Após a execução do comando, você terá um certificado de servidor recém-cunhado servercert.pem. A chave privada foi criada anteriormente e está disponível em serverkey.pem.

Por fim, você pode inspecionar seu certificado recém-cunhado com o seguinte:

$ 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

Mais cedo, você adicionou o seguinte para CA_default: copy_extensions = copy. Esta extensão de cópias é fornecida pela pessoa que faz a solicitação.

Se você omitir copy_extensions = copy, o certificado do servidor não terá os SANs (Subject Alternate Names) como www.example.come mail.example.com.

Se você usar copy_extensions = copy, mas não examinar a solicitação, o solicitante poderá induzi-lo a assinar algo como uma raiz subordinada (em vez de um servidor ou certificado de usuário). O que significa que ele será capaz de cunhar certificados que retornam à sua raiz confiável. Certifique-se de verificar a solicitação openssl req -verifyantes de assinar.


Se você omitir unique_subject ou configurá-lo como yes, você poderá criar apenas um certificado com o nome distinto do sujeito.

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

Tentar criar um segundo certificado durante a experiência resultará no seguinte ao assinar o certificado do servidor com a chave privada da CA:

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

Então, unique_subject = noé perfeito para testes.


Se você deseja garantir que o Nome da organização seja consistente entre CAs autoassinadas, CA subordinada e certificados de entidade final, adicione o seguinte aos seus arquivos de configuração da CA:

[ policy_match ]
organizationName = match

Se você deseja permitir que o Nome da organização seja alterado, use:

[ policy_match ]
organizationName = supplied

Existem outras regras relacionadas ao tratamento de nomes DNS nos certificados X.509 / PKIX. Refira estes documentos para as regras:

As RFC 6797 e RFC 7469 estão listadas porque são mais restritivas que os outros RFCs e documentos CA / B. Os RFCs 6797 e 7469 também não permitem um endereço IP.

jww
fonte
4
Obrigado por essa resposta extensa ... No entanto, estou meio perdido aqui. O que eu entendi do que você escreveu: openssl reqé usado para gerar CSR, openssl req -x509é usado para gerar certificado de CA (vi em algum outro lugar que você também pode criar certificado autoassinado), openssl caé usado para assinar um CSR com um certificado de CA. Certo? O que também me confunde é que as mesmas partes do arquivo openssl.cnf são usadas com valores diferentes, dependendo do comando ... Acho que estou totalmente perdido agora.
Bernard Rosset
27
Primeiro, openssl req -x509é usado para criar a CA. Segundo, openssl reqé usado para criar o CSR do servidor. Terceiro, openssl caé usado para criar o certificado do servidor e certificá-lo com a assinatura da CA.
JWW
1
"O que me confunde também é que as mesmas partes do openssl.cnf ..." - Certo. É por isso que eu os expliquei para você openssl-ca.cnfe openssl-server.cnf. Depois de se acostumar com eles e como as seções são invocadas, você pode combiná-las em uma monstruosidade openssl.cnf.
JWW
1
@JeffPuckettII - É uma seção comum. É usado pelos utilitários CA e Req. Eles devem ser extensões v3.
JWW
5
@ahnkle Use a opção -days para algo diferente dos 30 dias padrão. OpenSSL docs
george
14

Além da resposta de @jww, gostaria de dizer que a configuração no openssl-ca.cnf,

default_days     = 1000         # How long to certify for

define o número padrão de dias em que o certificado assinado por este root-ca será válido. Para definir a validade do próprio root-ca, você deve usar a opção '-days n' em:

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

Caso contrário, seu root-ca será válido apenas pelo mês padrão e qualquer certificado assinado por essa CA raiz também terá validade de um mês.

humble_wolf
fonte