RSA加密和解密期间的RandomNumberGenerator要求?
我试图用公钥加密消息,并使用加密++用私钥解密密这样的外壳: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;
}
我的问题:
- 为什么需要EncryptorFilter/DecryptorFilter随机数发生器(RNG)?
- 对于加密/解密,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的单元测试中使用这段代码,一切正常。
为什么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,一切工作正常。
一句小心的是...... GlobalRNG
是Test
命名空间的一部分。它在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)
),所以它实际上比试验和错误显着加速。在我们发布下一个版本的库之前,我们切换到了平方法。
'AutoSeededRandomPool'工作。非常感谢。 – maersk
需要RNG,因为[OAEP填充](https://en.wikipedia.org/wiki/Optimal_asymmetric_encryption_padding)要求生成随机比特串(如果不使用随机值,例如NullRNG,则会失去RSA OAEP的一些主要安全属性)。我不确定为什么解码需要RNG,尽管随机字符串被算法恢复,所以不需要生成新的随机位。 – puzzlepalace
@puzzlepalace - *“我不知道为什么解码需要RNG,但随机字符串是由算法恢复的......” - 在私钥操作期间致盲。 – jww
是的,这将是,很好的捕获。 – puzzlepalace