2017-06-21 104 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