2016-03-03 156 views
3

我正在迁移整个PHP API,虽然之前我使用过PyCrypto,但我不确定如何翻译下面的加密调用,因为我需要完全相同的结果。 PHP的调用是:在Python(PyCrypto)和PHP(OpenSSL)中使RSA加密兼容

define('KEY', "-----BEGIN PUBLIC KEY----- 
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC81t5iu5C0JxYq5/XNPiD5ol3Z 
w8rw3LtFIUm7y3m8o8wv5qVnzGh6XwQ8LWypdkbBDKWZZrAUd3lybZOP7/82Nb1/ 
noYj8ixVRdbnYtbsSAbu9PxjB7a/7LCGKsugLkou74PJDadQweM88kzQOx/kzAyV 
bS9gCCVUguHcq2vRRQIDAQAB 
-----END PUBLIC KEY-----"); 
$cypher = ""; 
$result = openssl_public_encrypt($plain, $cypher, KEY, OPENSSL_PKCS1_PADDING); 
echo bin2hex($cypher); 

假设一切顺利,这个打印从$cypher内容,传递到十六进制。对于示例输入"azzzzzzzzzzzzdfdf",我得到类似于:"2281aeebc1166cdfb2f17a0a0775d927ca5a9ad999bae0e4954f58bd8082fdf7efe1fd284876530341f714456d7eb8cd44c57b20ab27029b84d5dc77a674bede3fe9065282931404286082e9df8607bdcff0818b90324dfee7d76b566d0f99bebc5cc913372c276ba373712128f1bcc226b59367cff93f7cdd6dbde25b366863"

我必须将此值视为正确,因为代码是从正在迁移的现有API中获取的。然而,试图同用PyCrypto(是的,我迁移API是在Python可用),我使用下面的代码:

def bin2hex(s): 
    return "".join([hex(ord(c))[2:].zfill(2) for c in s]) 

KEY = """-----BEGIN PUBLIC KEY----- 
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC81t5iu5C0JxYq5/XNPiD5ol3Z 
w8rw3LtFIUm7y3m8o8wv5qVnzGh6XwQ8LWypdkbBDKWZZrAUd3lybZOP7/82Nb1/ 
noYj8ixVRdbnYtbsSAbu9PxjB7a/7LCGKsugLkou74PJDadQweM88kzQOx/kzAyV 
bS9gCCVUguHcq2vRRQIDAQAB 
-----END PUBLIC KEY-----""" 

from Crypto.Cipher import PKCS1_v1_5 
from Crypto.PublicKey import RSA 
encrypter = PKCS1_v1_5.new(RSA.importKey(KEY)) 
print bin2hex(encrypter.encrypt("azzzzzzzzzzzzdfdf")); 

虽然我期待相同的值返回和打印,价值最终是"3dd94ffabd01bb0e94010c0fedbcd4eb648f12e5d9e6d934b77ae86f76681d8a1b790cad9fddf6e6720415b4d645e525c33c402fa9778739b8e461790387e9508f7158a5fdc5723f5fc26d166b11a00759f0e0ee3ba6719a2e7c6b918f66e1311d1fff878ee2ca8762e1d6120f1e9585a76cdc7719ca20129ae76182b4277170"

使用PKCS1_OAEP输出"290f60f37088c2cb46ae9221b01ff46a463f270ef7cf70bbea49de0b5ae43aec34a0eb46e694cf22f689eb77e808c590fdc30eda09f9d3f3cb8c15e0505bf5a984c2a121bc9fa83c6b5ccf50235f072467b4ae9cdf0f0ee2e486626ffa62ad1aa715fbe29e8afe4ceab3ca5a5df4c1dc75d7f258285d7ff1f4f2b4dcb7a8413a"

很容易知道我必须修复我的python代码。如何修复我的python代码,以便返回与给定的PHP调用完全相同的结果?

+0

'OPENSSL_PKCS1_PADDING'等于'PKCS1_v1_5'吗? – Halcyon

+0

这是我不知道的部分,我需要帮助。让我编辑... –

+1

OPENSSL_PKCS1_PADDING是PKCS1_v1_5,FWIW你应该避免使用[因为它有一个已知的弱点](http://crypto.stackexchange.com/questions/12688/can-you-explain-bleichenbachers-cca -attack-on-pkcs1-v1-5),可以在某些情况下利用。 –

回答

3

你的代码很好。 pyCrypto中的PKCS#1 v1.5填充是随机的(source)。因此,即使使用相同的密钥和明文,加密也将始终不同。这是一个理想的财产。

如果你想检查pyCrypto和PHP的OpenSSL扩展之间的兼容性,那么你需要在一个中进行加密,在另一个中进行解密,并检查你是否得到了你的预期。


现在不应该使用PKCS#1 v1.5填充,因为对它有效的攻击。 OAEP是一个更好的选择。

+1

* PKCS#1 v1.5填充现在不应该使用,因为有效的攻击它。 OAEP是一个更好的选择。*请告诉我如何在PHP中使用OAEP,以便我可以建议API的所有者。 API传输相当敏感的数据。 –

+1

'OPENSSL_PKCS1_OAEP_PADDING'应该这样做,但我不知道散列函数和MGF1的默认值是什么。在pyCrypto中默认设置为SHA-256,但可以自由更改。 MGF1可以设置为SHA1,但另一个应该设置为SHA-256。等一下,[这里](http://php.net/manual/de/function.openssl-public-encrypt.php#118466)是一些额外的信息。 –