Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python PyCrypto与C中的RSA编码——RSA_PKCS1_填充_Python_Rsa_Pycrypto - Fatal编程技术网

Python PyCrypto与C中的RSA编码——RSA_PKCS1_填充

Python PyCrypto与C中的RSA编码——RSA_PKCS1_填充,python,rsa,pycrypto,Python,Rsa,Pycrypto,我的印象是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);

我的印象是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");
}
然后我使用了相同的
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返回同样的东西。在进一步挖掘的过程中,我认为我的问题是需要在Python代码中指定
RSA\u PKCS1\u PADDING
。当我试图在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:
奇怪的是,我在pycrypto API中没有看到任何填充选项

我已经重新生成了我的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-----

为什么Python实现不能产生与C代码相同的结果?因为您使用的是PKCS#1.5签名算法


PKCS#1.5要求在签名之前向消息添加随机填充。因此,对同一条消息多次签名,每次都会给出不同的值——如果反复运行Python版本,就会看到这个值。OpenSSL文档是一个不可逾越的泥潭,因此我不能确切地说为什么每次使用C版本都会得到相同的签名,但我怀疑您未能初始化随机数生成器或其他东西。

您使用OpenSSL和Python执行完全不同的操作。您使用openssl执行RSA签名,但使用PyCrypto执行RSA加密。使用openssl,如文档所述:

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

PKCS1_v1_5用于消息身份验证,而不是C代码中使用的RSA加密。根据说明,C代码应使用
RSA_sign
,以遵循与Python代码相同的RSASSA-PKCS1-v1_5规范。这很公平,但C代码返回的是目标系统能够解密的内容。Python方面不是。。那么,我如何让Python返回与C代码相同的结果呢?我想你是对的,它是签名,但我仍然得到奇怪的不匹配。我试图做的是生成一个远程API将接受的签名MD5。我在这里放了一些代码:--snippet#1,c代码,生成一个有效的签名,并解码回16字节。代码片段#2是引用文档指针的python版本——谢谢!代码片段3,回到C,试图解码python产生的内容,但仍然失败。FWIW我已经在python端尝试了SHA256和MD5,但都没有成功。对不起,错过了显而易见的。。因此,当我解除python字符串的限制时,它会解密,但它返回34个字符,而不是预期的16个字符。。
#include <openssl/rsa.h>
int RSA_private_encrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding);
>>> 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)