使用 java keytool 生成的密钥对中缺少 AuthorityKeyIdentifier

使用 java keytool 生成的密钥对中缺少 AuthorityKeyIdentifier

背景:我正在尝试为一个系统设置 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
]
]

最后,一旦你对结果感到满意,请确保安全地如果有未受保护的私钥,请删除它。

相关内容