2017-03-06 302 views
2

在以下示例中,我们使用一个RSA 256-bitprivate key来加密不带填充的32字节消息,并将结果存储在同一个内存块中。RSA_private_encrypt中的可能错误

#include <openssl/ssl.h> 
unsigned char err[256], 
       msg[] = "This is a message of some sort.", 
       key[] = "-----BEGIN RSA PRIVATE KEY-----\n"\ 
"MIGrAgEAAiEA6sZFpHqqFkpskc2GNMl6RHdiEuOqlX3LcW1TnYVgQFECAwEAAQIh\n"\ 
"AKqoe8FHJVJUwTzvMAo5FrU/t6Cc6GwYDELpU3xxs4nBAhEA+TwHM5ArwBgTtB2y\n"\ 
"AKlEKQIRAPElwlKWyde1KqHRCjOWX+kCEQDqWYZP9rUcp8cHKpDwTDiZAhBPldOd\n"\ 
"KDCzJRJN10yTm/RJAhANYsX4BteC/W7VRUjV5jSH\n"\ 
"-----END RSA PRIVATE KEY-----\n"; 
void main() 
{ 
    //msg[0] = 255; 
    if (RSA_private_encrypt(32, msg, msg, 
    PEM_read_bio_RSAPrivateKey(BIO_new_mem_buf(key, -1), NULL, NULL, NULL), 
    RSA_NO_PADDING) != 32) 
    { 
     ERR_load_crypto_strings(); 
     ERR_error_string(ERR_get_error(), err); 
     puts(err); 
    } 
} 

当我们通过删除注释改变0个信息字符的值,加密失败消息:

rsa routines:RSA_EAY_PRIVATE_ENCRYPT:data too large for modulus 

注意,很短的RSA键和硬编码的消息长度仅用于证明问题。密钥是使用openssl二进制生成的,而function也会因不同大小的密钥而失败(对于4096位密钥,the msg[0] = 192会导致失败)。

似乎函数将消息的开头解释为长度描述符,即使明确指出了RSA_NO_PADDING。这是一个错误?

+1

您没有256位模数,您的模数为255.875位。 –

回答

5

在RSA中,模数组和数据数组被解释为大整数。数据整数必须小于模数整数。否则,加密值无法恢复。

我已将您的private key解码。你的模数的第一个字节是0xEA。这意味着您签名的数据不能以大于0xEA的字节开始(234)。如果您分配msg[0] = 235;它将再次导致错误。

这就是填充来的地方。填充数据的第一个字节通常是0x00(或甚至是0x0001,具体取决于填充方案),这使填充数据在数值上不可能大于模数。

所以,不,你还没有找到一个错误。你只是使用加密错误。我建议你使用一些更高级别的API来签署消息。


请注意,填充对于RSA至关重要。没有它,就有办法恢复明文或伪造签名。请使用OAEP进行加密,并使用PSS进行签名。而且,密钥的大小也很重要。如今,应该使用4096位密钥。 256位密钥是一种玩具尺寸,现在可能会被智能手机破坏。

+0

请您指点一下解释在不使用填充时恢复明文的方法的源代码? – Ulrik

+1

你需要某种填充,即使它是你自己的。如果没有填充任意数据,这是不可解的。请注意,填充方案有一些开销。因此,如果您使用OAEP,那么您的模数必须至少比数据大42个字节。可能有一些解决方案,但这取决于你为什么要这样做,它会扩大这个问题的范围太多,我建议你问一个新问题,详细说明你为什么需要这个问题。如果它不是编程相关的,你应该问[crypto.se] –