Estou criando dois certificados simples; um é um certificado raiz e o outro é um certificado de servidor. Este último tem o rootcert.pem
e rootprivkey.pem
atribuído para ser usado nas bandeiras -CA
e CAkey
respectivamente. Eu instalei o certificado raiz no sistema e executei sudo update-cacertificates
também. Depois de muitas tentativas, não consegui trazer o openssl para verificar o certificado do servidor em relação ao certificado autoassinado. Dá-me este erro:
error 20 at 0 depth lookup: unable to get local issuer certificate
error servercrt.pem: verification failed
Nota: Não tenho certificados intermediários.
Agora, como resolvo esse problema?
EDITAR:
Comandos usados para geração e verificação
openssl req -new -newkey rsa:4096 -keyout rootprivkey.pem -out rootreq.pem -config openssl.cnf -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1
openssl ca -out rootcrt.pem -days 2652 -keyfile rootprivkey.pem -selfsign -config openssl.cnf -infiles rootreq.pem
openssl req -new -newkey rsa:4096 -keyout serverprivkey.pem -out serverreq.pem -config openssl.cnf
openssl x509 -req -in serverreq.pem -days 1200 -CA rootcrt.pem -CAkey rootprivkey.pem -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -out servercrt.pem -set_serial 01
openssl verify -CAfile rootcrt.pem servercrt.pem
openssl.cnf
#
# OpenSSL example configuration file.
# This is mostly being used for generation of certificate requests.
#
# You might want to copy this into /etc/ssl/ or define OPENSSL_CONF
#
# This definition stops the following lines choking if HOME isn't
# defined.
HOME = .
RANDFILE = $ENV::HOME/.rnd
# Extra OBJECT IDENTIFIER info:
#oid_file = $ENV::HOME/.oid
oid_section = new_oids
# To use this configuration file with the "-extfile" option of the
# "openssl x509" utility, name here the section containing the
# X.509v3 extensions to use:
# extensions =
# (Alternatively, use a configuration file that has only
# X.509v3 extensions in its main [= default] section.)
[ new_oids ]
# We can add new OIDs in here for use by 'ca', 'req' and 'ts'.
# Add a simple OID like this:
# testoid1=1.2.3.4
# Or use config file substitution like this:
# testoid2=${testoid1}.5.6
# Policies used by the TSA examples.
tsa_policy1 = 1.2.3.4.1
tsa_policy2 = 1.2.3.4.5.6
tsa_policy3 = 1.2.3.4.5.7
####################################################################
[ ca ]
default_ca = CA_default # The default ca section
####################################################################
[ CA_default ]
dir = . # Where everything is kept
certs = $dir # Where the issued certs are kept
crldir = $dir # Where the issued crl are kept
database = $dir # database index file.
unique_subject = yes # Set to 'no' to allow creation of
# several ctificates with same subject.
new_certs_dir = $certs # default place for new certs.
certificate = $certs/rootcrt.pem # The CA certificate
serial = $dir/serial.txt # The current serial number
crlnumber = $dir/crlnumber # the current crl number
# must be commented out to leave a V1 CRL
crl = $crldir/crl.pem # The current CRL
private_key = $dir/private/rootprivkey.pem # The private key
RANDFILE = $dir/private/.rand # private random number file
#x509_extensions = usr_cert # The extentions to add to the cert
# Comment out the following two lines for the "traditional"
# (and highly broken) format.
name_opt = ca_default # Subject Name options
cert_opt = ca_default # Certificate field options
# Extension copying option: use with caution.
copy_extensions = copy
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
# so this is commented out by default to leave a V1 CRL.
# crlnumber must also be commented out to leave a V1 CRL.
# crl_extensions = crl_ext
default_days = 365 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = default # use public key default MD
preserve = no # keep passed DN ordering
# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy = policy_match
# For the CA policy
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
####################################################################
[ req ]
default_bits = 4096
default_keyfile = priv.key.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca
req_extensions = v3_req
# req_extensions = v3_req # The extensions to add to a certificate request
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default =
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default =
localityName = Locality Name (eg, city)
localityName_default =
0.organizationName = Organization Name (eg, company)
0.organizationName_default =
# SET-ex3 = SET extension number 3
[ req_attributes ]
#challengePassword = A challenge password
#challengePassword_min = 4
#challengePassword_max = 20
#unstructuredName = An optional company name
[ usr_cert ]
# These extensions are added when 'ca' signs a request.
# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.
basicConstraints=CA:FALSE
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
[ v3_ca ]
# Extensions for a typical CA
# PKIX recommendation.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints = CA:true
O arquivo de configuração acima falha ao gerar o certificado CA raiz em primeiro lugar porque não possui uma
CommonName
entrada. Estou assumindo que foi um erro de digitação ou copiar/colar e o restante do arquivo de configuração é o real usado.Sua verificação de certificado falha porque sua CA raiz tem as
BasicConstraint
extensões definidas comoCA:False
. Ou seja, não é uma CA e, portanto, no que diz respeito à verificação, não pode ser usada para verificar a assinatura digital em outros certificados.Você precisa alterar seu arquivo de configuração para que o comando usado para gerar o certificado CA use:
basicConstraints = CA:true
. Para torná-lo compatível com RFC 5280, você também deve adicionar o sinalizador críticobasicConstraints = critical,CA:true
e usar .Sua abordagem é um tanto desconexa. Tente o seguinte:
Crie um arquivo de configuração OpenSSL para a CA (
./openssl.cnf
)Em seguida, crie sua solicitação usando um comando semelhante ao que você usou:
Observe que as
-sigopt
opções foram removidas, pois a assinatura neste ponto é a assinatura de solicitação usada para comprovar a posse da chave privada e não a assinatura do próprio certificado - isso é posterior.Em seguida, assine-o para criar o certificado CA autoassinado:
Observe que isso usa
openssl ca
em vez deopenssl x509
significa que você pode se referir a umopenssl.cnf
arquivo personalizado. Observe também o uso da-extensions
opção de apontar o comando para uma seção específica do arquivo de configuração. Por fim, observe que as-sigopt
opções foram movidas para cá, pois este é o comando que assina seu certificado CA e, portanto, deve ter seu esquema PSS.Next, create a separate OpenSSL config file for your server/end-entity certificate (./server.cnf).
Run a similar command to the one you used, but with the config file changed.
Finally, sign it with the CA:
Note that there is no
-extensions
option on this one, so OpenSSL defaults to the section pointed to by thex509_extensions =
option inopenssl.cnf
.You can now verify the certificates: