Old RandomPool

From Crypto++ Wiki
Jump to: navigation, search

If you are migrating from an older version of Crypto++, like 4.2, to a newer version of the library then you may need the old RandomPool class. The task comes up from time to time on the mailing list, and its usually in the context of a bad key derivation. For example, see Moving from Crypto++ 4.2 to Crypto++ 5.6.4 and Migrating from Crypto++ 5.2.1 to Crypto++ 5.6.5 on the mailing list.

For Crypto++ 6.0, you can use the OldRandomPool class. For Crypto++ 5.6.5 and earlier, you must apply the 6.0 change yourself. See Commits below. The files that changed are randpool.h, randpool.cpp and mdc.h.

You should avoid OldRandomPool if possible. Migrate to a new random number generator or key derivation function at the earliest opportunity. OldRandomPool has a few technical deficiencies, like producing the same stream during a VM rollback attack.

Also see RandomNumberGenerator on the Crypto++ wiki.

OldRandomPool

In Crypto++ 6.0 you can use the OldRandomPool class similar to the way you used the former RandomPool class in Crypto++ 5.4 and earlier. However, you must usethe modern RandomNumberGenerator interface. That means you use CanIncorporateEntropy, IncorporateEntropy GenerateBlock and GenerateIntoBufferedTransformation.

OldRandomPool prng;
SecByteBlock seed(384), result(32);

for (size_t i=0; i<384; ++i)
    seed[i] = static_cast<byte>(i);
prng.IncorporateEntropy(seed, seed.size());

prng.GenerateBlock(result, result.size());
HexEncoder encoder(new FileSink(std::cout));

std::cout << "OldRandomPool: ";
encoder.Put(result, result.size());
std::cout << std::endl;

The code above produces the following output. If you perform a git checkout CRYPTOPP_5_4 (or other version prior to Crypto++ 5.5), then you will arrive at the same result.

OldRandomPool: 41D1EF8F103CE29447C0C38666BC860957777391574D9366D113E1BA07498F75

Similar code is used in the library's self tests to ensure the generator is in fact the old PGP-style generator.

OldRandomPool prng;
byte actual[32], expected[32] = {
    0x41,0xD1,0xEF,0x8F,0x10,0x3C,0xE2,0x94,
    0x47,0xC0,0xC3,0x86,0x66,0xBC,0x86,0x09,
    0x57,0x77,0x73,0x91,0x57,0x4D,0x93,0x66,
    0xD1,0x13,0xE1,0xBA,0x07,0x49,0x8F,0x75
};

SecByteBlock seed(384);

for (size_t i=0; i<384; ++i)
    seed[i] = static_cast<byte>(i);
prng.IncorporateEntropy(seed, seed.size());

prng.GenerateBlock(actual, sizeof(actual));
fail = (0 != ::memcmp(actual, expected, sizeof(expected)));

Crypto++ 6.0 self tests will output the following:

Testing OldRandomPool generator...
passed:  Expected sequence from PGP-style RandomPool (2007 version)
passed:  100000 generated bytes compressed to 100020 bytes by DEFLATE
passed:  discarded 10000 bytes
passed:  IncorporateEntropy with 128 bytes
passed:  GenerateWord32 and Crop

Commits

The commits for OldRandomPool are as follows. The issue was tracked at Issue 452, Add OldRandomPool for pre-Crypto++ 5.5 compatibility.

The commit below cut-in the modern RandomNumberGenerator interface so CanIncorporateEntropy, IncorporateEntropy and GenerateIntoBufferedTransformation work as expected.

The commit below removed the old pre-Crypto++ 5.5 methods so the new RandomNumberGenerator interface must be used. All that means is you must call IncorporateEntropy instead of Put, and GenerateBlock instead of Get.

Finally, the commit below removed the class' hash member, and called ConditionalByteReverse instead.