1

我知道有很多关于同一主题的问题。不幸的是,没有什么能解决我的确切问题。所以让我具体一点。我正在开发一组需要证书身份验证的 REST API(很奇怪,但就是这样)。因此,为了进行测试,我们创建了自签名证书,openssl如下所示:

openssl req -x509 -sha256 -newkey rsa:4096 -keyout ca.key -out ca.crt -days 356 -nodes -subj '/CN=Lead Services'
openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj '/CN=*.lservices.eu'
openssl x509 -req -sha256 -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out services/server.crt
openssl x509 -req -sha256 -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 02 -out services/client.crt

现在,一个 nginx 设置为使用这些 ssl 证书运行,需要客户端身份验证。nginx 配置如下所示:

    listen 443 ssl;
    server_name  lacs.lservices.eu localhost;

    ssl_protocols TLSv1.1 TLSv1.2;
    ssl_certificate certs/server.crt;
    ssl_certificate_key certs/server.key;
    ssl_client_certificate certs/ca.crt;
    ssl_verify_client on;

postman使用上面生成的客户端证书测试 API工作正常。到目前为止一切都很好。我们创建了一个 swagger-ui,它提供了一个直接从浏览器测试的选项。但是这里的客户端身份验证不起作用。

我尝试在我的 Windows 10 中将 CA 证书导入受信任的 CA 存储,并将客户端证书导入个人,并尝试从 Chrome 和 Edge 进行测试,但服务器拒绝使用400 No required SSL certificate was sent.

更新

添加的输出openssl s_client -connect localhost:443

CONNECTED(00000218)
depth=0 CN = *.lservices.eu
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = *.lservices.eu
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
 0 s:/CN=*.lservices.eu
   i:/CN=Lead Services
---
Server certificate
-----BEGIN CERTIFICATE-----
......certificate content removed ---
-----END CERTIFICATE-----
subject=/CN=*.lservices.eu
issuer=/CN=Lead Services
---
Acceptable client certificate CA names
/CN=Lead Services
Client Certificate Types: RSA sign, DSA sign, ECDSA sign
Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:0x07+0x08:0x08+0x08:0x09+0x08:0x0A+0x08:0x0B+0x08:0x04+0x08:0x05+0x08:0x06+0x08:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:ECDSA+SHA1:RSA+SHA224:RSA+SHA1:DSA+SHA224:DSA+SHA1:DSA+SHA256:DSA+SHA384:DSA+SHA512
Shared Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:ECDSA+SHA1:RSA+SHA224:RSA+SHA1:DSA+SHA224:DSA+SHA1:DSA+SHA256:DSA+SHA384:DSA+SHA512
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 2245 bytes and written 455 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 4096 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: C2A281888B9899B68D6734DBDACE351F7975709F887FDD1EC011419D25F67B36
    Session-ID-ctx:
    Master-Key: CE307DF955A22CA2F901E95078DDEFF5AB8668B4789B7979504DC054E1DA8400B244B10C825DB899F713BE9E3665C63A
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
    0000 - 5c 99 a8 3c e8 e4 c2 f3-ce 19 db fd c7 35 4f f0   \..<.........5O.
    0010 - 80 6f b7 59 19 c6 50 9c-c1 ad 2c 5c 06 30 94 05   .o.Y..P...,\.0..
    0020 - 95 02 2b af 80 07 c4 0b-fd b2 64 a3 7c 2b d7 91   ..+.......d.|+..
    0030 - 33 d0 65 3a 47 23 2c 07-6a c6 62 7f 90 bb 75 50   3.e:G#,.j.b...uP
    0040 - 18 35 ae 08 38 59 ec 59-9c 6e 77 69 40 16 49 46   .5..8Y.Y.nwi@.IF
    0050 - ce 5f b8 35 88 e1 d9 7a-6b e5 21 db 30 83 c0 b8   ._.5...zk.!.0...
    0060 - 72 37 91 d9 ce e4 e8 d4-88 e0 b0 10 2c cc c2 c6   r7..........,...
    0070 - ac 39 da 68 de cb 92 be-6c 61 77 cc cd 10 0b 47   .9.h....law....G
    0080 - ae 0b 97 40 0b 41 46 98-5b fe 1e 17 a2 40 4a 2a   ...@.AF.[....@J*
    0090 - c8 d1 02 2e 3e 73 df 8e-ac 5c 3e 85 54 a2 ee 68   ....>s...\>.T..h
    00a0 - 05 3f 76 2f 5a e4 36 dc-c4 1b c2 f1 81 70 b3 63   .?v/Z.6......p.c

    Start Time: 1577357945
    Timeout   : 300 (sec)
    Verify return code: 21 (unable to verify the first certificate)
---

我怎样才能让它工作?自签名证书有什么限制不能这样使用吗?任何帮助表示赞赏!

4

2 回答 2

0

一般来说:

1.) 验证服务器是否接受来自您的 CA 的客户端证书。检查Acceptable client certificate CA来自:

openssl s_client -connect <server:tls-port>

2.)验证导入的个人证书是否符合Acceptable client certificate CA1 中的要求。)

目前尚不清楚您是如何创建client.csr的 - 可能存在问题。我希望你使用了不同的密钥。

于 2019-12-26T09:03:16.657 回答
0

在尝试了几种openssl调用组合之后,我终于想出了一个序列,可以让我生成一个 Chrome 可以接受的客户端证书。然后,我创建了两个 shell 脚本来处理该过程,一个负责生成兼作 CA 的自签名服务器证书,另一个负责生成用它签名的客户端证书。

create_server_certificate.sh

#!/bin/bash

# Generate a self-signed certificate and validating private key.
#
# See: https://serverfault.com/a/870832/486539

FILE_PREFIX="server"
SERVER_NAME="$HOSTNAME"

# See: https://stackoverflow.com/a/14203146/476920
for i in "$@"
do
  case $i in
    --host=*)
      SERVER_NAME="${i#*=}"
    ;;
    --name=*)
      FILE_PREFIX="${i#*=}"
    ;;
    *)
      echo "Unkwnown option: \""$i'"'
      exit 1
    ;;
  esac
done

CONFIG="
[ req ]
prompt = no
distinguished_name = req_distinguished_name
x509_extensions = san_self_signed
[ req_distinguished_name ]
CN=$SERVER_NAME
[ san_self_signed ]
subjectAltName = DNS:$SERVER_NAME, DNS:localhost
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = CA:true
keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment, keyCertSign, cRLSign
extendedKeyUsage = serverAuth, clientAuth, timeStamping
"

SERVER_CERT="$OUTPUT_DIR/${FILE_PREFIX}_crt.pem"
SERVER_KEY="$OUTPUT_DIR/${FILE_PREFIX}_key.pem"

openssl req \
  -newkey rsa:2048 -nodes \
  -keyout "$SERVER_KEY" \
  -x509 -sha256 -days 3650 \
  -config <(echo "$CONFIG") \
  -out "$SERVER_CERT"

openssl x509 -noout -text -in "$SERVER_CERT"

create_client_certificate.sh

#!/bin/bash

# Generate a client SSL certificate and validating private key for client-side
# authentication on web browsers.
#
# See:
#
# * https://serverfault.com/a/870832/486539
# * https://blog.devolutions.net/2020/07/tutorial-how-to-generate-secure-self-signed-server-and-client-certificates-with-openssl

CLIENT_ID="client"
CLIENT_PREFIX="client"
ROOT_PREFIX="server"

# See: https://stackoverflow.com/a/14203146/476920
for i in "$@"
do
  case $i in
    --id=*)
      CLIENT_ID="${i#*=}"
    ;;
    --root=*)
      ROOT_PREFIX="${i#*=}"
    ;;
    --out=*)
      CLIENT_PREFIX="${i#*=}"
    ;;
    *)
      echo "Unkwnown option: \""$i'"'
      exit 1
    ;;
  esac
done

CLIENT_CRT="${CLIENT_PREFIX}_crt.pem"
CLIENT_REQ="${CLIENT_PREFIX}_csr.pem"
CLIENT_KEY="${CLIENT_PREFIX}_key.pem"

ROOT_CRT="${ROOT_PREFIX}_crt.pem"
ROOT_KEY="${ROOT_PREFIX}_key.pem"

CONFIG="
[ req ]
prompt = no
distinguished_name = req_distinguished_name
[ req_distinguished_name ]
CN=$CLIENT_ID
"

# Generate client private key.
openssl ecparam -name prime256v1 -genkey -noout -out "$CLIENT_KEY"

# Generate client certificate request.
openssl req -new -sha256 -key "$CLIENT_KEY" -out "$CLIENT_REQ" -config <(echo "$CONFIG")

# Generate client certificate.
openssl x509 -req -in "$CLIENT_REQ" -CA "$ROOT_CRT" -CAkey "$ROOT_KEY" -CAcreateserial -out "$CLIENT_CRT" -days 1000 -sha256

# Generate a PFX certificate that can be imported to Google Chrome.
openssl pkcs12 -inkey "$CLIENT_KEY" -in "$CLIENT_CRT" -export -out "${CLIENT_PREFIX}.pfx"

openssl x509 -noout -text -in "$CLIENT_CRT"

rm "$CLIENT_REQ"

先运行create_server_certificate.sh生成服务器/CA证书,再create_client_certificate.sh生成前者签名的客户端证书。接下来server_crt.pem在Chrome 的“管理证书”屏幕的“权限”选项卡和“您的证书”选项卡中导入。client.pfx

要测试您的证书,请使用以下命令运行测试 OpenSSL 服务器:

openssl s_server -cert server_crt.pem -key server_key.pem -CAfile client_crt.pem -accept 4443 -www -Verify 1

并将 Chrome 定向到合适的本地地址,例如https://localhost:4443.

于 2021-02-05T16:20:59.090 回答