l使用Java创建了一个pkcs12密钥库,其中存储了两个密钥,现在我想使用python检索这些密钥。在Java中,加载密钥库并使用keystore.getkey(keyalias)。我怎么用python做到这一点?
# load OpenSSL.crypto
from OpenSSL import crypto
# open it, using password. Supply/read your own from stdin.
p12 = crypto.load_pkcs12(open("/path/to/cert.p12", 'rb').read(), passwd)
# get various properties of said file.
# note these are PyOpenSSL objects, not strings although you
# can convert them to PEM-encoded strings.
p12.get_certificate() # (signed) certificate object
p12.get_privatekey() # private key.
p12.get_ca_certificates() # ca chain.
,但是 get_privatekey()不接受args,这意味着无法设置l想要检索的别名别名,就像我在java中一样:
public static SecretKey getEntry(KeyStore keyStore, String keyAlias, Optional<String> password) {
SecretKey key = null;
try {
key = (SecretKey) keyStore.getKey(keyAlias, password.orElse("").toCharArray());
} catch (Exception e) {
e.printStackTrace();
}
return key;
}
答案 0 :(得分:0)
在我开始之前的一个问题是,您是用“秘密密钥”(又称对称密钥)开头的两个密钥,还是“私钥”?
如果您的密钥是“私有密钥”,则应该能够将PKCS12密钥库转换为JKS密钥库,并可以使用pyjks读取私有密钥。
要从RHEL7上的命令行转换密钥库格式,请使用以下命令:
keytool -importkeystore -srckeystore <path_to_your_pkcs12_keystore> -srcstoretype PKCS12 -deststoretype JKS -destkeystore <path_to_new_jks_keystore>
如果您的密钥是“秘密密钥”,则JKS格式不支持“秘密密钥”条目类型。因此,尝试将您的密钥库从PKCS12格式转换为JCEKS格式的密钥库。 JCEKS格式是
要从RHEL7上的命令行转换密钥库格式,请使用以下命令:
keytool -importkeystore -srckeystore <path_to_your_pkcs12_keystore> -srcstoretype PKCS12 -deststoretype JCEKS -destkeystore <path_to_new_jceks_keystore>
这个新的JCEKS格式密钥库现在应该可以使用pyjks通过python读取
答案 1 :(得分:0)
我知道这是一篇较旧的帖子,但我想回答以下直接问题 - 如何将别名传递给 pyopenssl 以获取私钥。我仍然认为另一个答案是一个可行的解决方案,但也许更多的上下文对某些人会有所帮助。
不幸的是,简短的回答是您无法使用 python 为 openssl
中的特定键指定别名。 PyOpenSSL
在下面使用 cryptography
加载 pkcs12
文件
def load_pkcs12(buffer, passphrase=None):
"""
Load pkcs12 data from the string *buffer*. If the pkcs12 structure is
encrypted, a *passphrase* must be included. The MAC is always
checked and thus required.
See also the man page for the C function :py:func:`PKCS12_parse`.
:param buffer: The buffer the certificate is stored in
:param passphrase: (Optional) The password to decrypt the PKCS12 lump
:returns: The PKCS12 object
"""
... (omitting a lot of code) ...
if cert[0] == _ffi.NULL:
pycert = None
friendlyname = None
else:
pycert = X509._from_raw_x509_ptr(cert[0])
friendlyname_length = _ffi.new("int*")
friendlyname_buffer = _lib.X509_alias_get0(
cert[0], friendlyname_length
)
friendlyname = _ffi.buffer(
frien
dlyname_buffer, friendlyname_length[0]
)[:]
if friendlyname_buffer == _ffi.NULL:
friendlyname = None
... (more code to omit) ...
lib.X509_alias_get0(X509*, int*)
函数来自 cryptography
库(据我所知,它实际上是来自 C
的 _openssl.lib
函数。这是它在 { {3}} 和 openssl code base)。
无论如何,pyOpenSSL
的 API 似乎不允许指定别名。他们的文档中没有任何提示,他们的问题跟踪器中也没有。
但是直接使用 cryptography
怎么样。 PyOpenSSL 确实警告我们在任何情况下使用直接 api 是个好主意...
<stdin>:1: DeprecationWarning: PKCS#12 support in pyOpenSSL is deprecated. You should use the APIs in cryptography.
当然,我们可以重新执行 pyOpenSSL 执行的步骤并加载我们的 .p12
文件,但是哦不...
definition here 向我们发出警告
<块引用>此时解析 PKCS12 文件时,密码学仅支持单个私钥和相关证书。
事实上,我们目前似乎无法通过这些库加载具有不同别名的不同键。
我只能假设这样做的原因是因为大多数 .p12
用户只有一个证书和一个私钥,与他们文件中的一个别名相匹配。也就是说,他们不使用这个特定标准的功能来保存多对。
我是根据 cryptography documentations
来判断的 <块引用>但实际上它通常只用于存储一个私钥及其相关的证书链。
PKCS #12 文件通常使用 OpenSSL 创建,它仅支持来自命令行界面的单个私钥。
但是 - 如果您只有一个私钥和证书,并且您仍想确保它们的别名正确无误,pyOpenSSL
确实有一个方法 get_friendlyname()
,它返回加载文件的别名。这对您的具体情况 (OP) 来说真的没有多大帮助,但可以作为额外检查来完成。