我正在尝试实现 PKI 验证方案,其中消息字符串在服务器上使用私钥签名,签名与消息字符串一起存储在客户端上。然后客户端使用公钥验证签名。
我的环境限制是,服务器是Google App Engine,客户端是Java程序。我玩过 PKI 验证的纯 Java 和纯 Python 解决方案并让它们工作,但是当在 Python 中执行一个操作而在 Java 中执行另一个操作时会出现问题,这主要是由于 key 文件格式限制和我对密码学术语的有限理解.
最大的限制之一是 GAE 中的加密支持。唯一支持的库是 PyCrypto,该库无法读取以 PEM、DER 或 X509 格式存储的公钥/私钥。据我所知,只有 M2Crypto 支持从这些文件中读取,但它不能在 GAE 内部使用,因为它是 openssl 的包装器,所以不是纯 python 解决方案。即使我能找到一种方法将公钥/私钥从 PEM/DER/X509 转换为 PyCrypto 可以理解的格式,这对我来说也行得通。但是我找不到任何方法来做到这一点。有什么想法吗?
我以 tlslite 的形式找到了一种可能的解决方案。 tlslite 可以从 PEM 文件中读取私钥并创建签名。这是代码。
from tlslite.utils.cryptomath import bytesToBase64
from tlslite.utils.keyfactory import parsePEMKey
s = open('private.pem').read()
key = parsePEMKey(s)
doc = 'Sample text'
bytes = array('B')
bytes.fromstring(doc)
print bytesToBase64(key.sign(bytes))
我用来验证签名对应的Java代码是。
String signAlgo = "SHA1WithRSAEncryption";
// read public key from public.der
byte[] encodedKey = new byte[294]; // shortcut hardcoding
getAssets().open("public.der").read(encodedKey);
// create public key object
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedKey);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pk = kf.generatePublic(publicKeySpec);
// read signature (created by python code above)
byte[] encodedSig = new byte[345];
getAssets().open("signature.txt").read(encodedSig);
byte[] decodedSig = Base64.decodeBase64(encodedSig);
// Do verification
Signature verifyalg = Signature.getInstance(signAlgo);
verifyalg.initVerify(pk);
verifyalg.update(message.getBytes());
Log.d(TAG, "Verif : "+verifyalg.verify(decodedSig));
验证失败。
我怀疑 tlslite 是否使用与 java 代码预期不同的算法来创建签名。
所以我试图找出答案。
在 python 方面
print key.getSigningAlgorithm()
给我
pkcs1-sha1
在 Java 方面,我试图用这段代码找到所有支持的算法:
Set<String> algos = java.security.Security.getAlgorithms("Signature");
for(String algo : algos) {
Log.d(TAG, algo);
}
这给了我
MD4WithRSAEncryption
RSASSA-PSS
SHA1withDSA
SHA1withRSA/ISO9796-2
1.2.840.113549.1.1.10
SHA512withRSA/PSS
MD5withRSA/ISO9796-2
DSA
SHA512WithRSAEncryption
SHA224withRSA/PSS
NONEWITHDSA
SHA256withRSA/PSS
SHA224WithRSAEncryption
SHA256WithRSAEncryption
SHA1withRSA/PSS
SHA1WithRSAEncryption
SHA384withRSA/PSS
SHA384WithRSAEncryption
MD5WithRSAEncryption
我在 Java 端尝试了所有 SHA1 值。但是没有人帮助验证 tlslite 使用 pkcs1-sha1 算法生成的签名。对这个映射有什么想法吗?
最佳答案
这些是不同的操作。在 Python 中,您需要使用 hashAndSign
。默认恰好是 SHA1 哈希。
关于java - 跨 Java 和 Python 的 PKI 验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1867355/