在 iOS 与 macOS 上配置客户端 TLS 证书

折腾一下午不如半夜 02:23 的随手一敲。

重要的几点是关于支持的椭圆曲线,以及打包 PKCS#12 格式的密钥与证书时必须使用 OpenSSL 1。所以在这里我们以 OpenSSL 1.1 举例,当然关于命令的使用两者都是差不多的。

1
2
3
4
$ export PATH="/opt/homebrew/opt/[email protected]/bin:$PATH"

$ openssl version
OpenSSL 1.1.1u 30 May 2023

生成 CA 证书与客户端证书

创建一个 ca.cnf,内容如下。关于各配置项的意义,见 man x509v3_config

ca.cnf
1
2
3
4
5
basicConstraints = critical, CA:TRUE, pathlen:3
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid, issuer:always
keyUsage = digitalSignature
keyUsage = critical, keyCertSign

然后生成 CA 证书。

对于 RSA,最大 8192,最小 512,在这之间的任何 bit 数都是可以的(奇数自动调整),你甚至可以生成一个 2984 bits 的 key。

对于 ECDSA,目前 iOS 与 macOS 仅支持 4 种类型的椭圆曲线:secp192r1secp256r1secp384r1secp521r1

CA 证书和客户端证书都需要满足这些条件。

1
2
3
4
5
6
7
8
openssl genpkey -algorithm RSA -out ca.key \
-pkeyopt rsa_keygen_bits:2048

openssl req -new -key ca.key -out ca.csr \
-subj "/C=CN/O=45gfg9/CN=Client Cert CA"

openssl x509 -req -days 1460 -extfile ca.cnf \
-signkey ca.key -in ca.csr -out ca.pem

genrsa 子命令已经被弃用(虽然很方便),genpkey 是新的用于统一生成所有类型的私钥的子命令。关于 genpkey 的用法,以及 -pkeyopt 选项,可以查询 man openssl-genpkey

-subj 可以按需求设置,FQDN 不需要设置为域名(甚至可以不设置)。

对于客户端证书,需要一个类似如下的 client.cnf

client.cnf
1
2
3
4
5
basicConstraints = critical, CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid, issuer:always
keyUsage = digitalSignature, keyEncipherment, dataEncipherment, keyAgreement
extendedKeyUsage = clientAuth

keyUsage 那一块最少需要哪些信息我也没搞懂,但是这样写肯定能用喵 (∠·ω< )⌒★

extendedKeyUsage = clientAuth 是重要的。如果没有,这个证书就无法用于客户端认证。

然后 CA 给客户端 CSR 签发证书就可以了。

1
2
3
4
5
6
7
8
9
openssl genpkey -algorithm EC -out client.key \
-pkeyopt ec_paramgen_curve:prime256v1

openssl req -new -key client.key -out client.csr \
-subj "/C=CN/O=45gfg9/OU=Devices/CN=45gfg9's iPhone"

openssl x509 -req -days 1460 -extfile client.cnf \
-CA ca.pem -CAkey ca.key \
-in client.csr -out client.pem

椭圆曲线 secp256r1!

打包 PKCS#12 并安装至客户端

请再次确保正在使用 OpenSSL 1!OpenSSL 3 所生成的 PKCS#12 文件无法导入 Apple 设备!

1
2
3
openssl pkcs12 -export -out client.p12 \
-in client.pem -inkey client.key \
-chain -CAfile ca.pem

这样就得到了一个 PKCS#12 文件。Export password 可以随意设置,但不能为空,否则无法导入 iOS / iPadOS。

macOS

可以直接打开 client.p12 文件导入哦。CA 证书 ca.pem 也需要导入,密码就是刚才输入的 Export password。

或者,如果你更喜欢命令行的话:

1
2
3
$ security import client.p12
1 identity imported.
1 certificate imported.

最后的结果应该像这样。

iOS / iPadOS

client.p12ca.pem 都需要传输到设备上(AirDrop / iCloud 云盘 / 本地起个服务器通过 http 下载)。虽然 CA 证书已经打包进 client.p12 文件了但 iOS 似乎不能处理这种情况的说。

按照安装配置描述文件的步骤走就可以了。密码也是刚才的 Export password。

完成!

服务器的配置就不写了,在网上很多地方都可以找到(笑)

现在访问新鲜配置的服务器!如果一切顺利的话就会有这样的弹窗。大功告成!
Safari @ macOS
Firefox @ macOS

curl 也可以哦!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ curl -I https://45gfg9-kali.local
HTTP/1.1 400 Bad Request
Server: nginx/1.22.1
Date: Fri, 21 Jul 2023 15:57:23 GMT
Content-Type: text/html
Content-Length: 237
Connection: close


$ curl -I https://45gfg9-kali.local -E client.pem --key client.key
HTTP/1.1 200 OK
Server: nginx/1.22.1
Date: Fri, 21 Jul 2023 15:57:32 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive


后记

这么简单的东西折腾了好几天(瘫)
只用调库不用学数学的感觉真好

为什么 0721 日的我在做这种事啊(望天)


在 iOS 与 macOS 上配置客户端 TLS 证书
https://heap.45gfg9.net/t/1bea40b8171d/
作者
45gfg9
发布于
2023-07-21
许可协议