我们有一个用Java编写的系统,该系统将编写需要由Python系统解密的加密文件。我试图弄清楚我需要哪种可以同时被Java和Python API使用的密钥,以及如何生成它们。计划是使用Java中的公钥来加密文件,并使用Python中的私钥来解密文件。
我尝试用gpg --generate-key
生成RSA密钥,并在装甲文件中获得一个看起来像这样的文件:
-----BEGIN PGP PRIVATE KEY BLOCK-----
... encoded key ...
-----END PGP PRIVATE KEY BLOCK-----
并根据如下内容创建一个公共密钥:
-----BEGIN PGP PUBLIC KEY BLOCK-----
... encoded key ...
-----END PGP PUBLIC KEY BLOCK-----
我可以用PGPUtil.getDecoderStream()
用Java中的Bouncy Castle解析公共密钥文件,获得PGPPublicKeyRingCollection
和PGPPublicKey
,它们可以转换为java.security.PublicKey
。
[在Python方面,我尝试使用cryptography.hazmat
和PyCrypto
API,但无法弄清楚如何导入私钥文件。当我尝试
from Crypto.PublicKey import RSA
RSA.importKey(open('/path/to/private/key/file').read())
我得到RSA key format is not supported
。
我一直在阅读不同类型的键和算法,但是我认为持有这样的键的ASCII文件应该可以工作,但是显然我缺少某些东西。
我也尝试过另一种方法,并使用PyCrypto
生成类似以下内容的新密钥:
from Crypto.PublicKey import RSA
key = RSA.generate(2048)
f = open('/tmp/private.pem','wb')
f.write(key.exportKey('PEM'))
f.close()
f = open('/tmp/public.pem','wb')
f.write(key.publickey().exportKey('PEM'))
f.close
然后像这样通过Bouncy Castle的API读取它:
PemReader reader = new PemReader(new FileReader("/tmp/public.pem"));
Object publicKey = RSAPublicKey.getInstance(reader.readPemObject().getContent());
但是那给了我:
java.lang.IllegalArgumentException: illegal object in getInstance: org.bouncycastle.asn1.DLSequence
at org.bouncycastle.asn1.ASN1Integer.getInstance(Unknown Source)
at org.bouncycastle.asn1.pkcs.RSAPublicKey.<init>(Unknown Source)
[Bouncy Castle提供了两个RSAPublicKey
类,我都尝试了两个,但是得到了相同的结果。
似乎不应该这么难,所以我试图找出我所缺少的。感谢您的帮助。
不幸的是,在公用密钥密码软件中,同一基本事物有许多不同的格式。大多数软件包都尝试支持最受欢迎的软件包。公钥更普遍的格式之一是SubjectPublicKeyInfo
or SPKI格式。如RFC 5280中所定义,该格式是SubjectPublicKeyInfo
Asn.1结构的DER编码,这是二进制编码,对于某些应用程序来说不方便。通过使用base64编码和带有页眉和页脚的换行,我们得到了所谓的SubjectPublicKeyInfo
。 Pycryptodome就是这种格式。使用Bouncycastle(BC)提供程序和pkix库,可以相对容易地在Java中对其进行处理。仅使用标准Java SE类来处理它就有点困难。
以下是一些代码片段,展示了如何解析PEM SPKI数据以在Java中生成公共密钥对象。
使用Java SE,BC prov和BC pkix:
"PEM" encoding of public keys
仅使用Java SE:
File pemPubFile = new File("/tmp/public.pem");
PEMParser pemParser = new PEMParser(new FileReader(pemPubFile));
SubjectPublicKeyInfo spki = (SubjectPublicKeyInfo) pemParser.readObject();
PublicKey publicKey = new JcaPEMKeyConverter().getPublicKey(spki);
System.out.println(publicKey);