由Android拒绝的自签名的CA证书

发布于 2025-01-29 16:04:44 字数 6736 浏览 1 评论 0原文

我正在使用以下脚本使用自己的内部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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

倦话 2025-02-05 16:04:44

我上面的脚本是错误的,我从未解决过它。如果您正在寻找解决方案,则赔率是您的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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文