跨Java和Python的PKI验证 [英] PKI verification across Java and Python

查看:295
本文介绍了跨Java和Python的PKI验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图实现一个PKI验证方案,其中消息字符串使用服务器上的私钥签名,签名与消息字符串一起存储在客户端上。然后客户端使用公共密钥验证签名。



我的环境的限制是,服务器是Google App Engine,客户端是Java程序。我使用的是Java-only和Python-only的PKI验证解决方案,并让他们工作,但是当在Python中的一个操作和另一个在Java中提出问题,主要是由于密钥文件格式限制和我有限的理解加密术语。



最大的限制之一是GAE中的加密支持。唯一支持的库是PyCrypto,并且此库不能读取以PEM,DER或X509格式存储的公钥/私钥。就我可以找到,只有M2Crypto支持从这些文件读取,但它不能在GAE内使用,因为它是一个包装openssl,所以不是一个纯python解决方案。即使我可以找到一种方法来将公共/私有密钥从PEM / DER / X509转换为PyCrypto所了解的格式,这对我也有效。但我找不到任何办法。有任何想法吗?



我发现一个可能的解决方案tlslite的形式。 tlslite可以从PEM文件中读取私钥并创建签名。这是代码。

 从tlslite.utils.cryptomath导入bytesToBase64 
从tlslite.utils.keyfactory import parsePEMKey
s = open('private.pem')。read()
key = parsePEMKey(s)

doc ='Sample text'
bytes = array ')
bytes.fromstring(doc)

print bytesToBase64(key.sign(bytes))

我用来验证签名的相应Java代码是。

  String signAlgo =SHA1WithRSAEncryption ; 

//从public.der读取公共密钥
byte [] encodedKey = new byte [294]; // shortcut hardcoding
getAssets()。open(public.der)。read(encodedKey);

//创建公钥对象
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedKey);
KeyFactory kf = KeyFactory.getInstance(RSA);
PublicKey pk = kf.generatePublic(publicKeySpec);

//读签名(由上面的python代码创建)
byte [] encodedSig = new byte [345];
getAssets()。open(signature.txt)。read(encodedSig);
byte [] decodedSig = Base64.decodeBase64(encodedSig);

//验证
签名verifyalg = Signature.getInstance(signAlgo);
verifyalg.initVerify(pk);
verifyalg.update(message.getBytes());
Log.d(TAG,Verif:+ verifyalg.verify(decodedSig));

验证失败。



如果tlslite使用不同于java代码预期的签名创建的算法。



所以我试着找到了。



在python端

  print key.getSigningAlgorithm()
/ pre>

给了我

  pkcs1-sha1 



在Java端,我尝试使用此代码查找所有支持的算法:

 设置< 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 algo生成的签名。关于此映射的任何想法?

解决方案

这些是不同的操作。在Python中,您需要使用 hashAndSign 。默认发生的是SHA1哈希。


I am trying to implement a PKI verification scheme, where a message string is signed with a private key on server, the signature is stored on the client along with the message string. The client then verifies the signature using a public key.

The restrictions of my environment are, the server is Google App Engine and the client is a Java program. I have played with Java-only and Python-only solutions of PKI verification and got them to work, however when doing one operation in Python and another in Java is posing problem, mainly due to Key file format restrictions and my limited understanding of cryptography terminology.

One of the biggest limitations is crypto support in GAE. The only library supported is PyCrypto and this library can't read public/private keys stored in PEM, DER or X509 formats. As far as I could find, only M2Crypto supports reading from these files, but it can't be used inside GAE because it's a wrapper around openssl, so not a pure python solution. Even if I could find a way to translate the public/private keys from PEM/DER/X509 to the format that PyCrypto understands, that will work for me. But I couldn't find any way to do it. Any ideas there?

I found one possible solution in the form of tlslite. tlslite could read a private key from PEM file and create a signature. Here is the code.

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))

The corresponding Java code I used to verify the signature is.

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));

The verification fails.

I suspected if the tlslite is using different algorithm for signature creation than what the java code expects.

So I tried to find that out.

On python side

print key.getSigningAlgorithm()

gave me

pkcs1-sha1

on Java side, I tried to find all supported algorithms with this code:

Set<String> algos = java.security.Security.getAlgorithms("Signature");
for(String algo : algos) {
    Log.d(TAG, algo);
}

That gave me

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

I tried all the SHA1 values on the Java side. But none helped to verify the signature generated by tlslite with pkcs1-sha1 algo. Any idea about this mapping?

解决方案

These are different operations. In Python, you need to use hashAndSign. The default happens to be SHA1 hash.

这篇关于跨Java和Python的PKI验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆