【问题标题】:How to regenerate values in AutoSeededX917RNG如何在 AutoSeededX917RNG 中重新生成值
【发布时间】:2015-02-14 12:48:10
【问题描述】:

我需要在需要时重新生成伪随机值。我的代码是:

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;

【问题讨论】:

  • 你为什么把它发在这里?

标签: c++ random crypto++


【解决方案1】:

如何在 AutoSededX917RNG 中重新生成值

您不能,因为您使用的是AutoSeeded* 生成器。

-----

我需要在需要时重新生成伪随机值...

在这种情况下,我认为您只有两个选择 - LC_RNG(不安全)或RandomPool(更安全,但有差距)。两者都需要您使用相同的种子来操作生成器以生成相同的比特流。

RandomPool 是一个 PGP 风格的生成器,其底层算法是 MDC&lt;SHA&gt;给定相同的种子,它会产生相同的比特流。它使用时间,因此每次运行都会产生不同的流(即使是相同的种子)。

不要使用AutoSeeded* 生成器,例如AutoSeededRandomPoolAutoSeededX917RNGAutoSeeded* 从操作系统的熵池中读取数据,然后使用它读取的位为生成器播种。

另请参阅 Crypto++ wiki 上的 RandomNumberGenerator

-----

更新RandomPool 使用时间(抱歉,我应该在推荐之前检查一下)。

可以使用OFB_Mode&lt;T&gt;::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&lt;T&gt;::Encryption 可以用作生成器,因为 OF​​B 模式使用 AdditiveCipherTemplate&lt;T&gt;,它派生自 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&lt;T&gt;::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;
};

【讨论】:

  • 5 年后,谢谢!
猜你喜欢
  • 2017-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-09
  • 2014-06-18
  • 1970-01-01
相关资源
最近更新 更多