2017-06-21 35 views
3

我試圖用公鑰加密消息,並使用加密++用私鑰解密密這樣的外殼:RSA加密和解密期間的RandomNumberGenerator要求?

openssl rsautl -encrypt -inkey id_rsa.pub.pem -pubin -in message -out message.enc 

openssl rsautl -decrypt -inkey id_rsa.pem -in message.enc -out message.dec 

加密/解密完成在不同的應用程序我從https://www.cryptopp.com/wiki/RSA_Cryptography開始。 我的代碼:

std::string publicEncrypt(std::string const& plain) { 
    auto cipher = std::string{}; 
    CryptoPP::RSAES_OAEP_SHA_Encryptor e(getPublicKey()); 
    CryptoPP::StringSource(plain, true, 
     new CryptoPP::PK_EncryptorFilter(CryptoPP::NullRNG(), e, 
       new CryptoPP::StringSink(cipher))); 
    return cipher; 
} 

std::string privateDecrypt(std::string const& cipher) { 
    auto decrypted = std::string{}; 
    CryptoPP::RSAES_OAEP_SHA_Decryptor d(getPrivateKey()); 
    CryptoPP::StringSource(cipher, true, 
     new CryptoPP::PK_DecryptorFilter(CryptoPP::NullRNG(), d, 
       new CryptoPP::StringSink(decrypted))); 
    return decrypted; 
} 

我的問題:

  1. 爲什麼需要EncryptorFilter/DecryptorFilter隨機數發生器(RNG)?
  2. 對於加密/解密,RNG必須相同,對嗎?那麼,如何在流程之間分享?

使用NullRNG()爲Unable to do RSA Encrption/Decryption using Crypto++ (isValidCoding is false)建議https://stackoverflow.com/users/608639/jww導致

std::exception NullRNG: NullRNG should only be passed to functions that don't need to generate random bytes. 

我想我根本想念的東西。感謝提示和建議。

如果我在一個全局RNG的單元測試中使用這段代碼,一切正常。

+0

需要RNG,因爲[OAEP填充](https://en.wikipedia.org/wiki/Optimal_asymmetric_encryption_padding)要求生成隨機比特串(如果不使用隨機值,例如NullRNG,則會失去RSA OAEP的一些主要安全屬性)。我不確定爲什麼解碼需要RNG,儘管隨機字符串被算法恢復,所以不需要生成新的隨機位。 – puzzlepalace

+2

@puzzlepalace - *「我不知道爲什麼解碼需要RNG,但隨機字符串是由算法恢復的......」 - 在私鑰操作期間致盲。 – jww

+0

是的,這將是,很好的捕獲。 – puzzlepalace

回答

2

爲什麼EncryptorFilter/DecryptorFilter需要隨機數生成器(RNG)?

簽名和驗證類是在cryptlib.h中設置的抽象接口。一些密碼系統使用它們,而其他密碼系統不使用它一個班會專門學習,可以放棄使用發電機。有時候一個類不需要一個生成器來執行其中一個操作。如果不需要,可以使用NullRNG

RSA在公鑰操作期間需要RNG的原因是消息填充。填充通常是消息格式化功能的一部分。正如@PuzzlePalace指出的那樣,OAEP填充是隨機的,而不是確定性的。

RSA在私鑰操作期間需要RNG的原因是致盲。對於RSA和其他類似RSA的方案(如Rabin-Williams),致盲僅僅是一個隨機值的乘法,以掩蓋通過priavte鍵進行的倒轉以恢復原始值。之後,在簽名或解密後,隱藏的值將被刪除,操作的結果仍然存在。

相關,原因DSA或ECDSA將需要在私鑰操作的RNG是RFC 6979, Deterministic Usage of the Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA)。確定性簽名不使用隨機格式或隨機k's。

公鑰和私鑰操作需要RNG的另一個原因是對密鑰進行驗證檢查。例如,可以檢查密鑰以確保特定的約束條件成立,比如它的素數或具有特定的雅可比符號。


的RNG必須是用於加密/解密一樣的吧?那麼,如何在流程之間分享?

不,發電機可以不同。唯一的要求是它們會產生一個隨機流,用於合理定義「隨機」意味着什麼。沒有分割太多頭髮,這意味着發生器產生均勻的分佈。

您可以在wiki上找到更多關於Crypto ++生成器的文章RandomNumberGenerator


如果我在單元測試中使用此代碼與全球RNG,一切工作正常。

一句小心的是...... GlobalRNGTest命名空間的一部分。它在test.cpp : 115定義:

NAMESPACE_BEGIN(CryptoPP) 
NAMESPACE_BEGIN(Test) 

ANONYMOUS_NAMESPACE_BEGIN 
OFB_Mode<AES>::Encryption s_globalRNG; 
NAMESPACE_END 

RandomNumberGenerator & GlobalRNG() 
{ 
    return dynamic_cast<RandomNumberGenerator&>(s_globalRNG); 
} 

NAMESPACE_END // Test 
NAMESPACE_END // CryptoPP 

GlobalRNG是一個確定性的發電機及其不正確的庫的一部分。如果你依賴它,你的代碼將無法在現場編譯。

使用wiki上RandomNumberGenerator上討論的其他生成器之一。 AutoSeededRandomPool是個不錯的選擇。


使用NullRNG()中無法做到用加密+(isValidCoding是假的),RSA Encrption /解密建議https://stackoverflow.com/users/608639/jww導致

std::exception NullRNG: NullRNG should only be passed to functions that don't need to generate random bytes. 

這些信息是不正確。我需要修復它。謝謝。


有趣的(在一種病態的方式排序),加密++了CVE-2015-2141由於拉賓 - 威廉姆斯致盲。致盲的價值需要是一個二次剩餘;否則攻擊者可能會準備特殊消息來揭示私鑰。

Evgeny Sidorov的論文全文可在Breaking the Rabin-Williams digital signature system implementation in the Crypto++ library。這裏是新的和改進反函數是什麼樣的固定西多羅夫的攻擊(從rw.cpp)後:如果你讀西多羅夫的文件第6

ModularArithmetic modn(m_n), modp(m_p), modq(m_q); 
Integer r, rInv; 

do 
{ 
    // Do this in a loop for people using small numbers for testing 
    r.Randomize(rng, Integer::One(), m_n - Integer::One()); 
    // Fix for CVE-2015-2141. Thanks to Evgeny Sidorov for reporting. 
    // Squaring to satisfy Jacobi requirements suggested by Jean-Pierre Munch. 
    r = modn.Square(r); 
    rInv = modn.MultiplicativeInverse(r); 
} while (rInv.IsZero()); 

,他建議產生一個隨機r,然後檢查r雅可比符號以確保其二次剩餘。如果它不是QR,則嘗試新的隨機r。分類法使用了這種方法,但它顯示該方案顯着減慢,因爲隨機r滿足條件的概率爲1/16。

然而,我們知道平方r確保我們滿足雅可比在第一次嘗試,因爲[R 模N始終是一個二次剩餘。平方/乘法只需要log (exp)(而不是n log (n)),所以它實際上比試驗和錯誤顯着加速。在我們發佈下一個版本的庫之前,我們切換到了平方法。

+0

'AutoSeededRandomPool'工作。非常感謝。 – maersk