Кодирование RSA в PyCrypto против C - RSA_PKCS1_PADDING - PullRequest
0 голосов
/ 25 декабря 2018

У меня сложилось впечатление, что PyCrypto - это прямая оболочка OpenSSL, но, похоже, я получаю неожиданные результаты.Я написал простой тест на C;

int main() {
    const unsigned char test[] = "TEST_TEST_TEST";
    FILE *privateFile = fopen("private.pem", "r");
    RSA *privateRsa = PEM_read_RSAPrivateKey(privateFile, NULL, NULL, NULL);

    unsigned char *target = malloc(512);
    int len = RSA_private_encrypt(strlen(test), test, target, privateRsa, 1);

    for (int i = 0; i < 256; i++) {
        printf("%02x", target[i]);
    }
    printf("\n");
}

, который дает мне один результат;

a7c5832cf6390bcf75612e46c55759167e02173b2c6741ec4779af5d88488df8bfa6a6ba4c
fbc93d730dd3b4e681fca34d23c862712954ec85c087d9b36efa725b942fa7d8383019bcba
d467a1b31a3b0aeccf85cf1b4e4600801e3d40db75640f7e56f9bbb2a525d58e6decd02400
2049cadef9feea23f72f0fef72e9d2a5e9209011b7726422561f8fdfc7e983c28b600ff875
14b6ea4bb59addfaf8492ba71261d3837d9ae82507ab2f6cb7aaa0fe647f5d8d469b7a5e83
7b3bdf9994be8e621cdb04cec955ddd44170b9899daec891b492562b0df3d30d50367c710d
81400aefadb494d6f13d37237cf015280879d787de4d58ef3a5d61a200dd68642fdf

Затем я использовал тот же private.pem и сделал то, что я считаю эквивалентным в Python;

from Crypto.Cipher import PKCS1_v1_5
from Crypto.PublicKey import RSA

private_key_filename = 'private.pem'
private_key_file = open(private_key_filename, 'rb')
private_key = RSA.importKey(private_key_file.read())
private_key_file.close()
cipher = PKCS1_v1_5.new(private_key)

encrypted = cipher.encrypt(bytes("TEST_TEST_TEST", "ascii"))
print("Encrypted: ", encrypted.hex())

Что дает мне совершенно другой результат;

ac3de0ad667f26912b71baaf3f0c84198482a1822ef05f1d0b339a9e13be0fdc74c446bf74
0e14d07edbff1d893eb9a9745ee42501c50a7a0ec1352f96bf72c603afe6d4709ef3ea936a
4cda182dfc70d0a76967e79120f02e017e8f9aa30b1b444b5fe46396d6908e1e55febb948e
69cc1dcd9f9fbd44f449056d0655489834b564216c81c19f193548a53c77af8683d4c77d06
2f61fc4fe2c9e947f22523e0afb522f7addbedb2b1094c1a76245849d05acf465ba024f2da
77abe5fe6aac5913baf3ca4932806006bd41b82c76bdc328f24d5de9027819888b93a06c2d
2f972b78c775280691b4f53c181cc8d637ace1ea4642d1c510dceada85ae5957006e

Почему оболочка Python не дает того же результата, что и базовая библиотека C?Я предполагаю, что я делаю что-то неправильно на стороне Python, но я не могу понять, что это может быть. РЕДАКТИРОВАТЬ : Для ясности, код C возвращает то, что мне нужно, мне нужно заставить Python возвращать то же самое.Выполняя еще несколько копаний, я думаю, что моя проблема в том, что мне нужно указать RSA_PKCS1_PADDING в моем коде Python.Когда я пытаюсь расшифровать на стороне C, я возвращаюсь;

4144797508:error:0407006A:rsa routines:RSA_padding_check_PKCS1_type_1:block type is not 01:rsa_pk1.c:103:
4144797508:error:04067072:rsa routines:RSA_EAY_PUBLIC_DECRYPT:padding check failed:rsa_eay.c:773:

Как ни странно, я не вижу никаких вариантов заполнения в API Pycrypto ..

У меня естьповторно генерировал мой ключ RSA несколько раз, так что подойдет любой ключ, но на случай, если кто-то захочет воспроизвести локально, вот фиктивный ключ, с которым я тестирую;

-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAt1bExeH8DAuRercWwSxy/ysS9zDNUziJpY00gsESK2TVc6W7
mw8Rmv/RoJPZBH4xsHIeCA3eO36jv6abN9kPWjmn8deI3IG1bz78UUAYSSFrPher
8XtpDLMPqf5D2gqddS9GydroX1TUyxyXeZZXRhFuLQwiu9tqVvr3WJDvpXNUtj8/
O2zfM2UhiKAgOwVRk2h/UX+FVsvck4SYVaJTc+8zcaiUuAVBVwimTLTj6L9jo+wD
TMpWLdjPq1iL9N1SxvJkiPoGyDL73jS9RXvFdDP8uknsid92GtyQLs0g+xCo4Ywp
qml5jWONT7dsL/zly4pagvNrYy9VjCMTGIsDowIDAQABAoIBAQCLoYjh0Nf+cH0P
AgxReUHn9u1N2Bw4qpGixWVdxB/LbtNmba3xTUuySe1kp9Wbp2S+plsa9TzxAOVD
nGcQ5L7dj5XKCcZRcnQ1UromQ3N7lvkvZCXvF3eNVX6zkFQq5vS/AA+gwplBqcEb
JB51WrwDQFkx89EsU9Kshh0FlfT+gweZMDh6WNoF+pfHp6sN2Qv+mRdvPEVFYy93
YAT7UXWK3afJJfCEQKbhImIkMngRx+7V2VVOdivQME8CAjfiC/P8dlSStkWm2+Gs
1l34m0z9a0RODXbf8RaY5os2I2/GPNHx4AlilxEhnRRicwr1TqLRHSp8p2h5m3oM
zagO/q8RAoGBALw8tg/3U+5UWA6vDfoHaxxrbWfbR7S7uud/7J4PZs73Vv7BB1DI
iyKlYd2b8L03zX2QWN1zVHlvtZmFPGjc6U5tXX6Pzk/v2/Gv24r7F4W4lpA/BdSi
DBJeVe0Uuvh8+qaFQQv0ek/JAHGoEgpo7HTIuTAqDtJD78C2o20a/EhrAoGBAPlW
p62ERiKU6hh5nI6rhB+QspgZQf5BQaWfGmDy1CugXNcebm3fqefI55oUux9z95Vj
rB6qNdYlJB+bCbg8d4Mekl1NexZtUn94gd/7U+z4BvfabzJ96JRdIzEbpbZv6rW8
Z4i6RA78S+T/kvjeaHVSEbxJXPU7emwSrt2xPt+pAoGAGRVJ+XSutXp9xW8kQKYO
atoR2R4KPxYpAMI2KJXK0Fd7OzVDoUsn5zT8hohKGxy9gDbk8JV2szvkihGMDDkr
yayfIcdN6a7/swQJEEsHRmVjgtMzFrOFQklZz97MT2JwEBJ/qXUpe0pAieSoisSS
hbldnAJuuSweXaK4wkgvSAMCgYEA8TVLcSkNUFcPQC4lrj9uybqJi2qj1Pv8LeUE
99TyPGIebl0aJ2DAVWKd6wkzHPJrCTIrSF8RReEYWRr7BCg61bW1kl1qPf/0VyyV
N8FDJ3OqCgxellIHtb+EU/WTEjKitL1Wy4amYHjiUt6LqAZAt351edje/L5VaEeK
sxzM3kECgYAjm2igRLqK2SoPSMtrgjjATChYCEkZXE5G86oNjdo5zcd2q+iFMxys
xD1U7taKW1q3mKlOJmzI/04MFdnI+WAUvyRFWuAxiwEqJBB90XfooYe/Pda1Fg1H
mIxuZP5kRx9zYWF1vPzNnEyAn/9yUiap8Gi9DK/YigEOcVrIjnuFMA==
-----END RSA PRIVATE KEY-----

Ответы [ 2 ]

0 голосов
/ 25 декабря 2018

Вы делаете совершенно разные операции с openssl и с Python.Вы выполняете подпись RSA с помощью openssl, но шифрование RSA с помощью PyCrypto.Что касается openssl, как ясно из документации:

#include <openssl/rsa.h>
int RSA_private_encrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding);

RSA_private_encrypt () подписывает байтов flen в from (обычно это дайджест сообщения с идентификатором алгоритма) с использованием закрытого ключаRSA и сохраняет подпись в.должен указывать на байты памяти RSA_size (rsa).

Другими словами, он выполняет RSA PKCS # 1 ver 1.5 подпись типа 1 блока.

При этом в PyCrypto, несмотря на то, чточто вы используете закрытый ключ, метод шифрования обрабатывает его как открытый ключ (закрытый ключ Pycrypto RSA является подклассом открытого ключа RSA) и выполняет шифрование типа 2 блока RSA PKCS # 1 версии 1.5.Поскольку вы не намекаете на то, что вы пытаетесь выполнить, я не могу сказать, какой результат является правильным.

Если вы хотите подписать PyCrypto RSA, в документации есть такой пример :

>>> from Crypto.Signature import pkcs1_15
>>> from Crypto.Hash import SHA256
>>> from Crypto.PublicKey import RSA
>>>
>>> message = 'To be signed'
>>> key = RSA.import_key(open('private_key.der').read())
>>> h = SHA256.new(message)
>>> signature = pkcs1_15.new(key).sign(h)
0 голосов
/ 25 декабря 2018

Почему реализация Python не дает таких же результатов, как код C?Поскольку вы используете алгоритм подписи PKCS # 1.5.

PKCS # 1.5 требует добавления случайного заполнения к сообщению перед его подписанием.Из-за этого, подписывание одного и того же сообщения несколько раз будет давать разное значение каждый раз, что вы увидите, если будете многократно запускать версию Python.Документация OpenSSL - непростая проблема, поэтому я не могу точно сказать, почему вы каждый раз получаете одну и ту же подпись с версией C, но я подозреваю, что вы не можете инициализировать генератор случайных чисел или что-то в этом роде.

...