由Android拒绝的自签名的CA证书
我正在使用以下脚本使用自己的内部CA(正在进行的工作)来创建证书:
#!/bin/bash
while [[ "$#" < 1 ]];do
echo "Usage: cert-admin.sh [COMMAND] [OPTIONS]\n"
echo " Commands:"
echo " newpair - Creates a key and signed certificate"
echo " revoke - Revokes a certificate and re-creates the intermediate CRL"
echo " newcrl - Re-creates the intermediate CRL"
echo ""
echo " Examples: cert-admin.sh newpair server example.mysite.com"
echo " cert-admin.sh revoke example.mysite.com"
echo ""
echo " Types: server"
exit 1
done
command=$1
function newCRL {
cd /root/ca
rm -f intermediate/crl/intermediate.crl.pem
openssl ca -config intermediate/openssl.cnf \
-gencrl -out intermediate/crl/intermediate.crl.pem
openssl crl -in intermediate/crl/intermediate.crl.pem -noout -text
}
while [[ $command == 'newpair' ]];do
type=$2
fqdn=$3
while [[ $type == 'server' ]];do
cd /root/ca
openssl genrsa -out intermediate/private/$fqdn.key.pem 2048
openssl req -reqexts SAN \
-config <(cat intermediate/openssl.cnf \
<(printf "\n[SAN]\nsubjectAltName=DNS:$fqdn\n\n")) \
-key intermediate/private/$fqdn.key.pem \
-new -sha256 -out intermediate/csr/$fqdn.csr.pem
openssl ca -config intermediate/openssl.cnf \
-extensions server_cert -days 375 -notext -md sha256 \
-in intermediate/csr/$fqdn.csr.pem \
-out intermediate/certs/$fqdn.cert.pem
chmod 444 intermediate/private/$fqdn.key.pem
chmod 444 intermediate/certs/$fqdn.cert.pem
openssl x509 -noout -text \
-in intermediate/certs/$fqdn.cert.pem
openssl verify -CAfile intermediate/certs/ca-chain.cert.pem \
intermediate/certs/$fqdn.cert.pem
echo "ca-chain: /root/ca/intermediate/certs/ca-chain.cert.pem"
echo "key: /root/ca/intermediate/private/$fqdn.key.pem"
echo "cert: /root/ca/intermediate/certs/$fqdn.cert.pem"
break;
done
break;
done
while [[ $command == 'revoke' ]];do
cert=$2
cd /root/ca
openssl ca -config intermediate/openssl.cnf \
-revoke intermediate/certs/$cert.cert.pem
newCRL
break;
done
while [[ $command == 'newcrl' ]];do
newCRL
while [[ $2 != 'cron' ]];do
echo "CRL should be re-created by cron every 30 days. Example:"
echo "30 12 2 * * /root/ca/cert-admin.sh newcrl cron"
break;
done
break;
done
InterMediate/openssl.cnf
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = /root/ca/intermediate
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
RANDFILE = $dir/private/.rand
private_key = $dir/private/intermediate.key.pem
certificate = $dir/certs/intermediate.cert.pem
crlnumber = $dir/crlnumber
crl = $dir/crl/intermediate.crl.pem
crl_extensions = crl_ext
default_crl_days = 30
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 375
preserve = no
policy = policy_loose
[ policy_strict ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_loose ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
string_mask = utf8only
default_md = sha256
x509_extensions = v3_ca
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address
countryName_default = US
stateOrProvinceName_default = Denial
localityName_default = Springfield
0.organizationName_default = MyOrg
organizationalUnitName_default = Research
emailAddress_default = [email protected]
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ usr_cert ]
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
[ server_cert ]
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[ crl_ext ]
authorityKeyIdentifier=keyid:always
[ ocsp ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning
在Arch Linux中受到中级CA的信任,该证书不会引发任何错误。
但是,在Android上,我会遇到错误。 I think it has something to do with SAN
as the Bitwarden Android app shows subjectAltNames[]
and Kiwi browser(Chrome Desktop for Android) shows ERR_CERT_COMMON_NAME_INVALID
。
使用-addext“ objectaltname = dns:www.example.com”
带有-config intermediate/openssl.cnf
也不起作用。
创建一个自签名的证书使用:
openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \
-addext "subjectAltName = DNS:www.example.com" \
-subj "/C=US/ST=Denial/L=Springfield/O=MyOrg/CN=www.example.com" \
-keyout web.key -out web.crt
正常工作。
编辑:通用名称
在提示时将其设置为FQDN。
EDIT2:要澄清,这是在Android设备上安装CA链证书之后。运行Android10。Edit3
:由于-Config&lt;(Cat Intermediate/openssl.cnf&lt;(printf“ \ n [san] \ nsubjectaltname = dns:$ fqdn \ n \ n“))
不起作用。指定openssl.cnf
时是否有另一种包含SAN的方法?这对我不起作用...
I'm using the following script to create certificates using my own internal CA(Work in progress):
#!/bin/bash
while [[ "$#" < 1 ]];do
echo "Usage: cert-admin.sh [COMMAND] [OPTIONS]\n"
echo " Commands:"
echo " newpair - Creates a key and signed certificate"
echo " revoke - Revokes a certificate and re-creates the intermediate CRL"
echo " newcrl - Re-creates the intermediate CRL"
echo ""
echo " Examples: cert-admin.sh newpair server example.mysite.com"
echo " cert-admin.sh revoke example.mysite.com"
echo ""
echo " Types: server"
exit 1
done
command=$1
function newCRL {
cd /root/ca
rm -f intermediate/crl/intermediate.crl.pem
openssl ca -config intermediate/openssl.cnf \
-gencrl -out intermediate/crl/intermediate.crl.pem
openssl crl -in intermediate/crl/intermediate.crl.pem -noout -text
}
while [[ $command == 'newpair' ]];do
type=$2
fqdn=$3
while [[ $type == 'server' ]];do
cd /root/ca
openssl genrsa -out intermediate/private/$fqdn.key.pem 2048
openssl req -reqexts SAN \
-config <(cat intermediate/openssl.cnf \
<(printf "\n[SAN]\nsubjectAltName=DNS:$fqdn\n\n")) \
-key intermediate/private/$fqdn.key.pem \
-new -sha256 -out intermediate/csr/$fqdn.csr.pem
openssl ca -config intermediate/openssl.cnf \
-extensions server_cert -days 375 -notext -md sha256 \
-in intermediate/csr/$fqdn.csr.pem \
-out intermediate/certs/$fqdn.cert.pem
chmod 444 intermediate/private/$fqdn.key.pem
chmod 444 intermediate/certs/$fqdn.cert.pem
openssl x509 -noout -text \
-in intermediate/certs/$fqdn.cert.pem
openssl verify -CAfile intermediate/certs/ca-chain.cert.pem \
intermediate/certs/$fqdn.cert.pem
echo "ca-chain: /root/ca/intermediate/certs/ca-chain.cert.pem"
echo "key: /root/ca/intermediate/private/$fqdn.key.pem"
echo "cert: /root/ca/intermediate/certs/$fqdn.cert.pem"
break;
done
break;
done
while [[ $command == 'revoke' ]];do
cert=$2
cd /root/ca
openssl ca -config intermediate/openssl.cnf \
-revoke intermediate/certs/$cert.cert.pem
newCRL
break;
done
while [[ $command == 'newcrl' ]];do
newCRL
while [[ $2 != 'cron' ]];do
echo "CRL should be re-created by cron every 30 days. Example:"
echo "30 12 2 * * /root/ca/cert-admin.sh newcrl cron"
break;
done
break;
done
intermediate/openssl.cnf
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = /root/ca/intermediate
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
RANDFILE = $dir/private/.rand
private_key = $dir/private/intermediate.key.pem
certificate = $dir/certs/intermediate.cert.pem
crlnumber = $dir/crlnumber
crl = $dir/crl/intermediate.crl.pem
crl_extensions = crl_ext
default_crl_days = 30
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 375
preserve = no
policy = policy_loose
[ policy_strict ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_loose ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
string_mask = utf8only
default_md = sha256
x509_extensions = v3_ca
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address
countryName_default = US
stateOrProvinceName_default = Denial
localityName_default = Springfield
0.organizationName_default = MyOrg
organizationalUnitName_default = Research
emailAddress_default = [email protected]
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ usr_cert ]
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
[ server_cert ]
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[ crl_ext ]
authorityKeyIdentifier=keyid:always
[ ocsp ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning
With the intermediate CA trusted in Arch Linux, the certificate doesn't throw any errors.
However, on Android I get errors. I think it has something to do with SAN
as the Bitwarden Android app shows subjectAltNames[]
and Kiwi browser(Chrome Desktop for Android) shows ERR_CERT_COMMON_NAME_INVALID
.
Using -addext "subjectAltName = DNS:www.example.com"
with -config intermediate/openssl.cnf
doesn't work either.
Creating a self signed cert using:
openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \
-addext "subjectAltName = DNS:www.example.com" \
-subj "/C=US/ST=Denial/L=Springfield/O=MyOrg/CN=www.example.com" \
-keyout web.key -out web.crt
works fine.
EDIT: Common Name
is set to the FQDN when prompted.
EDIT2: To clarify, this is after installing the CA chain cert on the Android device. Running Android 10.
EDIT3: I've narrowed the issue down to SAN not being added due to -config <(cat intermediate/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:$fqdn\n\n"))
not working. Is there another way to include SAN while specifying openssl.cnf
? It's not working for me...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我上面的脚本是错误的,我从未解决过它。如果您正在寻找解决方案,则赔率是您的OpenSSL命令和 /或OpenSSL配置有问题。我最终在Docker中使用EJBCA来创建和管理我的CA和证书。到目前为止,EJBCA正在完美地工作(出于安全原因,我建议将其离线)。证书与Android 10到Android 14(14是撰写此答案时的最新测试)。
My script above is at fault, I never ended up fixing it. If you are looking for a solution, odds are you are having issues with your openssl commands and or openssl config. I ended up using EJBCA in docker to create and manage my CA and certificates. So far EJBCA is working flawlessly (I suggest keeping it offline for security reasons). Certificates work well with Android 10 to Android 14 (14 being the latest tested as of writing this answer).