如何在 AutoSeededX917RNG 中重新生成值
How to regenerate values in AutoSeededX917RNG
我需要在需要时重新生成伪随机值。我的代码是:
static const unsigned int BLOCKSIZE = 5;
byte scratch[ BLOCKSIZE ];
CryptoPP::AutoSeededX917RNG<CryptoPP::AES> rng;
rng.GenerateBlock(scratch,BLOCKSIZE);
std::cout << "The generated random block is:" << std::endl;
for( unsigned int i = 0; i < BLOCKSIZE; i++ )
{
std::cout << std::setw(2) << std::setfill('0');
std::cout << static_cast<unsigned int>( scratch[ i ] );
}
std::cout << std::endl;
How to regenerate values in AutoSeededX917RNG
你不能,因为你使用的是 AutoSeeded*
生成器。
-----
I need to regenerate the pseuorandom values when I need them...
在那种情况下,我认为您只有两个选择 - LC_RNG
(不安全)或 RandomPool
(更安全,但存在差距)。两者都需要您使用相同的种子 和 来操作生成器以产生相同的比特流。
RandomPool
是一个PGP风格的生成器,它的底层算法是MDC<SHA>
。 它会在给定相同种子的情况下产生相同的比特流。它使用时间,因此它会为每个 运行(即使使用相同的种子)产生不同的流。
不要使用AutoSeeded*
生成器,例如AutoSeededRandomPool
或AutoSeededX917RNG
。 AutoSeeded*
从 OS 的熵池中读取,然后用它读取的位作为生成器的种子。
另请参阅 Crypto++ wiki 上的 RandomNumberGenerator。
-----
UPDATE: RandomPool
使用时间(抱歉,我应该在推荐之前检查一下)。
您可以使用OFB_Mode<T>::Encryption
生成可重现的随机流。 Crypto++ 测试程序使用它(参见 test.cpp
- 它是从 GlobalRNG()
返回的生成器)。示例如下所示。
SecByteBlock seed(32 + 16);
OS_GenerateRandomBlock(false, seed, seed.size());
for(unsigned int i = 0; i < 10; i++)
{
OFB_Mode<AES>::Encryption prng;
prng.SetKeyWithIV(seed, 32, seed + 32, 16);
SecByteBlock t(16);
prng.GenerateBlock(t, t.size());
string s;
HexEncoder hex(new StringSink(s));
hex.Put(t, t.size());
hex.MessageEnd();
cout << "Random: " << s << endl;
}
OFB_mode<T>::Encryption
can be used as a generator because OFB mode uses AdditiveCipherTemplate<T>
,派生自 RandomNumberGenerator
.
运行 它产生类似于下面的结果。
$ ./cryptopp-test.exe
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
-----
您还可以使用下面 AES_RNG.h
中的代码来创建基于 AES-256 的确定性生成器。如果提供相同的种子,它将产生相同的比特流。它比 OFB_Mode<T>::Encryption
更灵活一点,因为它可以接受任意大小的种子。
测试代码如下:
SecByteBlock seed(32);
OS_GenerateRandomBlock(false, seed, seed.size());
for(unsigned int i = 0; i < 10; i++)
{
AES_RNG prng(seed, seed.size());
SecByteBlock t(16);
prng.GenerateBlock(t, t.size());
string s;
HexEncoder hex(new StringSink(s));
hex.Put(t, t.size());
hex.MessageEnd();
cout << "Random: " << s << endl << endl;
}
其输出类似于下图。程序的每个 运行 都会不同,因为每个 运行 使用不同的种子(通过 OS_GenerateRandomBlock
):
$ ./cryptopp-test.exe
Random: D9B48CB7D37C88BDF2A0B0022AB1A812
Random: D9B48CB7D37C88BDF2A0B0022AB1A812
Random: D9B48CB7D37C88BDF2A0B0022AB1A812
Random: D9B48CB7D37C88BDF2A0B0022AB1A812
Random: D9B48CB7D37C88BDF2A0B0022AB1A812
Random: D9B48CB7D37C88BDF2A0B0022AB1A812
Random: D9B48CB7D37C88BDF2A0B0022AB1A812
Random: D9B48CB7D37C88BDF2A0B0022AB1A812
Random: D9B48CB7D37C88BDF2A0B0022AB1A812
Random: D9B48CB7D37C88BDF2A0B0022AB1A812
AES_RNG.h:
#include <cryptopp/cryptlib.h>
using CryptoPP::NotCopyable;
using CryptoPP::BufferedTransformation;
using CryptoPP::BlockCipher;
#include <cryptopp/secblock.h>
using CryptoPP::AlignedSecByteBlock;
using CryptoPP::FixedSizeSecBlock;
#include <cryptopp/smartptr.h>
using CryptoPP::member_ptr;
#include <cryptopp/osrng.h>
using CryptoPP::OS_GenerateRandomBlock;
using CryptoPP::RandomNumberGenerator;
#include <cryptopp/aes.h>
using CryptoPP::AES;
#include <cryptopp/sha.h>
using CryptoPP::SHA512;
class AES_RNG : public RandomNumberGenerator, public NotCopyable
{
public:
explicit AES_RNG(const byte *seed = NULL, size_t length = 0)
: m_pCipher(new AES::Encryption), m_keyed(SeedHelper(seed, length))
{
}
bool CanIncorporateEntropy() const
{
return true;
}
void IncorporateEntropy(const byte *input, size_t length)
{
m_keyed = SeedHelper(input, length, false);
}
void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
{
if (!m_keyed) {
m_pCipher->SetKey(m_key, m_key.size());
m_keyed = true;
}
while (size > 0)
{
m_pCipher->ProcessBlock(m_seed);
size_t len = std::min((size_t)16, (size_t)size);
target.ChannelPut(channel, m_seed, len);
size -= len;
}
}
protected:
// Sets up to use the cipher. Its a helper to allow a throw
// in the contructor during initialization. Returns true
// if the cipher was keyed, and false if it was not.
bool SeedHelper(const byte* input, size_t length, bool ctor = true)
{
// 32-byte key, 16-byte seed
AlignedSecByteBlock seed(32 + 16);
SHA512 hash;
if(ctor)
{
memset(m_key, 0x00, m_key.size());
memset(m_seed, 0x00, m_seed.size());
}
if(input && length)
{
// Use the user supplied seed.
hash.Update(input, length);
}
else
{
// No seed or size. Use the OS to gather entropy.
OS_GenerateRandomBlock(false, seed, seed.size());
hash.Update(seed, seed.size());
}
hash.Update(m_key.data(), m_key.size());
hash.TruncatedFinal(seed.data(), seed.size());
memcpy(m_key.data(), seed.data() + 0, 32);
memcpy(m_seed.data(), seed.data() + 32, 16);
// Return false. This allows the constructor to complete
// before the pointer m_pCipher is used.
return false;
}
private:
FixedSizeSecBlock<byte, 32> m_key;
FixedSizeSecBlock<byte, 16> m_seed;
member_ptr<BlockCipher> m_pCipher;
bool m_keyed;
};
我需要在需要时重新生成伪随机值。我的代码是:
static const unsigned int BLOCKSIZE = 5;
byte scratch[ BLOCKSIZE ];
CryptoPP::AutoSeededX917RNG<CryptoPP::AES> rng;
rng.GenerateBlock(scratch,BLOCKSIZE);
std::cout << "The generated random block is:" << std::endl;
for( unsigned int i = 0; i < BLOCKSIZE; i++ )
{
std::cout << std::setw(2) << std::setfill('0');
std::cout << static_cast<unsigned int>( scratch[ i ] );
}
std::cout << std::endl;
How to regenerate values in AutoSeededX917RNG
你不能,因为你使用的是 AutoSeeded*
生成器。
-----
I need to regenerate the pseuorandom values when I need them...
在那种情况下,我认为您只有两个选择 - LC_RNG
(不安全)或 RandomPool
(更安全,但存在差距)。两者都需要您使用相同的种子 和 来操作生成器以产生相同的比特流。
RandomPool
是一个PGP风格的生成器,它的底层算法是MDC<SHA>
。 它会在给定相同种子的情况下产生相同的比特流。它使用时间,因此它会为每个 运行(即使使用相同的种子)产生不同的流。
不要使用AutoSeeded*
生成器,例如AutoSeededRandomPool
或AutoSeededX917RNG
。 AutoSeeded*
从 OS 的熵池中读取,然后用它读取的位作为生成器的种子。
另请参阅 Crypto++ wiki 上的 RandomNumberGenerator。
-----
UPDATE: RandomPool
使用时间(抱歉,我应该在推荐之前检查一下)。
您可以使用OFB_Mode<T>::Encryption
生成可重现的随机流。 Crypto++ 测试程序使用它(参见 test.cpp
- 它是从 GlobalRNG()
返回的生成器)。示例如下所示。
SecByteBlock seed(32 + 16);
OS_GenerateRandomBlock(false, seed, seed.size());
for(unsigned int i = 0; i < 10; i++)
{
OFB_Mode<AES>::Encryption prng;
prng.SetKeyWithIV(seed, 32, seed + 32, 16);
SecByteBlock t(16);
prng.GenerateBlock(t, t.size());
string s;
HexEncoder hex(new StringSink(s));
hex.Put(t, t.size());
hex.MessageEnd();
cout << "Random: " << s << endl;
}
OFB_mode<T>::Encryption
can be used as a generator because OFB mode uses AdditiveCipherTemplate<T>
,派生自 RandomNumberGenerator
.
运行 它产生类似于下面的结果。
$ ./cryptopp-test.exe
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
Random: DF3D3F8E8A21C39C0871B375013AA2CD
-----
您还可以使用下面 AES_RNG.h
中的代码来创建基于 AES-256 的确定性生成器。如果提供相同的种子,它将产生相同的比特流。它比 OFB_Mode<T>::Encryption
更灵活一点,因为它可以接受任意大小的种子。
测试代码如下:
SecByteBlock seed(32);
OS_GenerateRandomBlock(false, seed, seed.size());
for(unsigned int i = 0; i < 10; i++)
{
AES_RNG prng(seed, seed.size());
SecByteBlock t(16);
prng.GenerateBlock(t, t.size());
string s;
HexEncoder hex(new StringSink(s));
hex.Put(t, t.size());
hex.MessageEnd();
cout << "Random: " << s << endl << endl;
}
其输出类似于下图。程序的每个 运行 都会不同,因为每个 运行 使用不同的种子(通过 OS_GenerateRandomBlock
):
$ ./cryptopp-test.exe
Random: D9B48CB7D37C88BDF2A0B0022AB1A812
Random: D9B48CB7D37C88BDF2A0B0022AB1A812
Random: D9B48CB7D37C88BDF2A0B0022AB1A812
Random: D9B48CB7D37C88BDF2A0B0022AB1A812
Random: D9B48CB7D37C88BDF2A0B0022AB1A812
Random: D9B48CB7D37C88BDF2A0B0022AB1A812
Random: D9B48CB7D37C88BDF2A0B0022AB1A812
Random: D9B48CB7D37C88BDF2A0B0022AB1A812
Random: D9B48CB7D37C88BDF2A0B0022AB1A812
Random: D9B48CB7D37C88BDF2A0B0022AB1A812
AES_RNG.h:
#include <cryptopp/cryptlib.h>
using CryptoPP::NotCopyable;
using CryptoPP::BufferedTransformation;
using CryptoPP::BlockCipher;
#include <cryptopp/secblock.h>
using CryptoPP::AlignedSecByteBlock;
using CryptoPP::FixedSizeSecBlock;
#include <cryptopp/smartptr.h>
using CryptoPP::member_ptr;
#include <cryptopp/osrng.h>
using CryptoPP::OS_GenerateRandomBlock;
using CryptoPP::RandomNumberGenerator;
#include <cryptopp/aes.h>
using CryptoPP::AES;
#include <cryptopp/sha.h>
using CryptoPP::SHA512;
class AES_RNG : public RandomNumberGenerator, public NotCopyable
{
public:
explicit AES_RNG(const byte *seed = NULL, size_t length = 0)
: m_pCipher(new AES::Encryption), m_keyed(SeedHelper(seed, length))
{
}
bool CanIncorporateEntropy() const
{
return true;
}
void IncorporateEntropy(const byte *input, size_t length)
{
m_keyed = SeedHelper(input, length, false);
}
void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
{
if (!m_keyed) {
m_pCipher->SetKey(m_key, m_key.size());
m_keyed = true;
}
while (size > 0)
{
m_pCipher->ProcessBlock(m_seed);
size_t len = std::min((size_t)16, (size_t)size);
target.ChannelPut(channel, m_seed, len);
size -= len;
}
}
protected:
// Sets up to use the cipher. Its a helper to allow a throw
// in the contructor during initialization. Returns true
// if the cipher was keyed, and false if it was not.
bool SeedHelper(const byte* input, size_t length, bool ctor = true)
{
// 32-byte key, 16-byte seed
AlignedSecByteBlock seed(32 + 16);
SHA512 hash;
if(ctor)
{
memset(m_key, 0x00, m_key.size());
memset(m_seed, 0x00, m_seed.size());
}
if(input && length)
{
// Use the user supplied seed.
hash.Update(input, length);
}
else
{
// No seed or size. Use the OS to gather entropy.
OS_GenerateRandomBlock(false, seed, seed.size());
hash.Update(seed, seed.size());
}
hash.Update(m_key.data(), m_key.size());
hash.TruncatedFinal(seed.data(), seed.size());
memcpy(m_key.data(), seed.data() + 0, 32);
memcpy(m_seed.data(), seed.data() + 32, 16);
// Return false. This allows the constructor to complete
// before the pointer m_pCipher is used.
return false;
}
private:
FixedSizeSecBlock<byte, 32> m_key;
FixedSizeSecBlock<byte, 16> m_seed;
member_ptr<BlockCipher> m_pCipher;
bool m_keyed;
};