背景:我正在尝试为一个系统设置 QA/测试环境,该系统包括 (1) 为 HTTPS 连接配置的 Web 应用程序,以及 (2) 在移动设备上运行的基于 Python 的客户端应用程序。Web 应用程序的安装程序请求一个 JKS 文件,该文件包含服务器将提供给其客户端进行验证和加密的密钥对。
免责声明:在 SSL 证书和相关主题方面,我完全是业余爱好者,采用边学边做的方式。请尽量将回答简化到普通人能理解的水平。
问题:
我一直在努力使用 java keytool,试图让它为 Web 应用程序生成可用的 JKS 条目。问题是我生成的任何条目都缺少 AuthorityKeyIdentifier 元素。它有一个 SubjectKeyIdentifier(当然),并且使用 本文档我已经找到了如何添加 SubjectAlternativeName 和其他元素......但我找不到任何信息告诉我如何获取 AuthorityKeyIdentifier。
我怀疑实现此目的的正常方法是生成 CSR 并让 CA 对其进行签名,但由于这严格来说是内部 QA 环境,我更愿意坚持使用自签名。据我了解,自签名 JKS 条目可以(并且应该)具有 AuthorityKeyIdentifier,其 KeyIdentifier 与 SubjectKeyIdentifier 中的 KeyIdentifier 重复。但就像我说的那样,我不知道如何使用 java keytool 获取它。
有人可以建议或指导如何获得它吗?
答案1
看来keytool
可能的扩展列表是有限的,并且不包含您需要的权威密钥标识符。
因此,改为使用openssl
创建自签名证书;将证书和私钥转换为 PKCS#12 文件;最后,如果需要,将其转换为 JKS。
首先,创建一个配置文件openssl
并将其保存openssl.conf
在当前目录中:
[ req ]
# The size of the keys in bits:
default_bits = 2048
# The message digest for self-signing the certificate
# sha1 or sha256 for best compatability, although most
# OpenSSL digest algorithm can be used.
# md4,md5,mdc2,rmd160,sha1,sha256
default_md = sha256
# Don't prompt for the DN, use configured values instead
# This saves having to type in your DN each time.
prompt = no
string_mask = default
distinguished_name = req_dn
# Extensions added while singing with the `openssl req -x509` command
x509_extensions = x509_ext
[ req_dn ]
countryName = GB
stateOrProvinceName = Somewhere
organizationName = Example
commonName = Example Web Service
[ x509_ext ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
subjectAltName = @alt_names
# No basicConstraints extension is equal to CA:False
# basicConstraints = critical, CA:False
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[alt_names]
DNS.1 = example.org
DNS.2 = www.example.org
接下来,创建自签名证书和私钥:
注意:该-nodes
选项允许您创建未受保护私钥没有密码,因为 PKCS#12 会有一个密码。如果您需要私钥有密码,只需删除此选项即可。
openssl req -x509 -new -nodes -days 720 -keyout selfsigned.key -out selfsigned.pem -config openssl.conf
将这两个转换为单个 PKCS#12:
注意:该-name
选项应该是密钥库别名。
openssl pkcs12 -export -out selfsigned.p12 -in selfsigned.pem -inkey selfsigned.key -name MyApp
Java 可以使用 PKCS#12 作为密钥库,但如果您坚持使用 JKS,请使用以下命令进行转换:
keytool -importkeystore -srckeystore selfsigned.p12 -srcstoretype pkcs12 -destkeystore selfsigned.jks -deststoretype jks
keytool
会警告你 JKS 是专有格式,并建议使用 PKCS#12,然后要求新的首先输入 JKS 密码(两次),然后提示输入 PKCS#12 密码。
您可以通过导出来确认证书包含您需要的所有内容:
keytool -exportcert -keystore selfsigned.jks -alias SelfSigned -file selfsigned.crt
最后检查一下:
keytool -printcert -file selfsigned.crt
应该显示类似以下内容的内容:
Owner: CN=Example Web Service, O=Example, ST=Somewhere, C=GB
Issuer: CN=Example Web Service, O=Example, ST=Somewhere, C=GB
Serial number: 1fc84b98026e8b0b6d276ecbfc309dd7201bbb08
Valid from: Fri May 01 20:13:04 BST 2020 until: Thu Apr 21 20:13:04 BST 2022
Certificate fingerprints:
SHA1: B4:F0:A3:26:C8:7A:75:B1:32:55:0A:EC:31:4F:93:20:53:35:3E:A6
SHA256: F4:97:EA:08:52:03:4B:F4:FB:9F:64:88:69:E6:81:1E:28:95:F8:E3:39:FE:24:C0:48:40:70:33:70:4E:94:0B
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3
Extensions:
#1: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: F7 7F AA 69 52 DF 41 25 F2 F2 AC E7 5E D8 A7 43 ...iR.A%....^..C
0010: EF C9 92 50 ...P
]
]
#2: ObjectId: 2.5.29.37 Criticality=false
ExtendedKeyUsages [
serverAuth
]
#3: ObjectId: 2.5.29.15 Criticality=true
KeyUsage [
DigitalSignature
Key_Encipherment
]
#4: ObjectId: 2.5.29.17 Criticality=false
SubjectAlternativeName [
DNSName: www.example.com
DNSName: www.example.org
]
#5: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: F7 7F AA 69 52 DF 41 25 F2 F2 AC E7 5E D8 A7 43 ...iR.A%....^..C
0010: EF C9 92 50 ...P
]
]
最后,一旦你对结果感到满意,请确保安全地如果有未受保护的私钥,请删除它。