2012-11-14 24 views
0

我想用C編寫一個簡單的加密程序,使用OpenSSL,我發現了一些奇怪的東西。我不是C大師,也不是OpenSSL專業人員。所以我可能犯了一個錯誤。OpenSSL RSA_public_encrypt奇怪的行爲

功能是如下

char *rsa_encrypt(char *data) 
{ 
    const char xponent_in_hex[] = "010001"; 
    const char modulus_in_hex[] = "D0BA16F11907E7B0819705A15264AC29BEE9F1EC5F22642992 
    D3E27100B7F212864A624A12FFB6D531712B0B0225AAD0C2E313D077A7DB2A5A33483EEFF41A9D";  

    BIGNUM *xponent = NULL; 
    BIGNUM *modulus = NULL; 

    BN_hex2bn(&xponent, xponent_in_hex); 
    BN_hex2bn(&modulus, modulus_in_hex); 

    RSA *rsa = RSA_new(); 
    rsa->e = xponent; 
    rsa->n = modulus; 
    rsa->iqmp = NULL; 
    rsa->d = NULL; 
    rsa->p = NULL; 
    rsa->q = NULL; 

    char encoded[512] = { 0 }; 
    RSA_public_encrypt(
    strlen(data), 
    (const unsigned char *)data, 
    (unsigned char *)encoded, 
    rsa, 
    RSA_PKCS1_OAEP_PADDING 
); 

    RSA_free(rsa); 

    return (encoded); 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    printf("%s\n", base64_encode(rsa_encrypt("ABC"))); 
    printf("%s\n", base64_encode(rsa_encrypt("ABC"))); 
    printf("%s\n", base64_encode(rsa_encrypt("ABC"))); 
} 

我請相同的數據幾次該功能,它在每次調用時產生不同的值。這顯然是錯誤的因爲指數模量創建RSA結構是恆定的輸入數據是在每個呼叫的相同。

那麼爲什麼RSA_public_encrypt的行爲呢?

我該如何生成RSA加密公鑰,基於指數模數

我在哪裏犯錯?

回答

5

這實際上是正確的,你沒有犯錯。你的困惑源於RSA_PKCS1_OAEP_PADDING參數到RSA_public_encrypt

的RSA加密過程實際上是:

  1. 以明文(純)和編碼它,產生encoded_plain。
  2. Encrypt encoded_plain。

(正如您所料,解密過程要求您解密該值,然後解碼該消息)。

RSA_PKCS1_OAEP_PADDING參數指定應如何對明文進行編碼(應使用OAEP編碼)。

簡化的解釋是,OAEP填充使用一些隨機值填充,這樣既xxxxxxxABCyyyyyyyABCzzzzzzzABC都是有效的encoded_plain值的明文,而那些encoded_plain加密爲不同的值。如果您執行相應的解密(並通過將相同的RSA_PKCS1_OAEP_PADDING參數傳遞給RSA_private_decrypt)操作來執行相應的解密操作,則應該仍然將「ABC」作爲每個密文的輸出,因爲填充從三個密文中刪除。

(如果你想準確地來說是原和編碼方案更爲複雜的是,看到RFC 3447 section 7.1.1。但這些都是可能的細節,你不關心。)在結束

+1

真的非常感謝您的答覆。 openssl聽起來很強大但記錄不完整。 – anonim

0

編碼端的範圍rsa_encrypt函數。你的返回指針會指向一個無效的內存區域,這可能不會包含你期望的內容,因爲別人(例如另一個線程)寫了它。解釋填充的答案是正確的。