Обеспечение совместимости RSA в Python (PyCrypto) и PHP (OpenSSL)

Я переношу весь PHP API, и пока я использовал PyCrypto раньше, я не уверен, как перевести следующий вызов шифрования, так как мне нужен тот же самый результат. Вызов PHP:

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 (да, я 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-вызов?

Ваш код в порядке. PKCS # 1 v1.5 padding in pyCrypto рандомизирован ( источник ). Поэтому шифрование всегда будет отличаться, даже если вы используете один и тот же ключ и открытый текст. Это желаемое свойство.

Если вы хотите проверить совместимость между pyCrypto и расширением OpenSSL PHP, тогда вам нужно будет зашифровать в одном, расшифровать в другом и проверить, что вы получили то, что ожидали.


PKCS # 1 v1.5 padding не следует использовать в настоящее время, потому что есть эффективные атаки против него. OAEP – намного лучшая альтернатива.