2017-03-06 63 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] –