BOOL CCryptorAES101::Init(BYTE* pKey, DWORD dwKeySize)
{
ASSERT(pKey);
m_bInit = true;
try
{
CryptoPP::SHA256 hash;
CryptoPP::RandomPool rng;
CryptoPP::MySecByteBlock bufSeedIV(IV_SEED_SIZE);
m_bufSeed.Resize(hash.DigestSize());
m_bufIV .Resize(IV_SIZE);
hash.CalculateDigest(m_bufSeed,pKey,dwKeySize);
rng.Put(pKey,dwKeySize);
rng.GenerateBlock(bufSeedIV,bufSeedIV.Size());
CryptoPP::MySecByteBlock bufHash(hash.DigestSize());
hash.CalculateDigest(bufHash,bufSeedIV.Begin(),bufSeedIV.Size());
ASSERT(2 * m_bufIV.Size() == bufHash.Size());
for (int i = 0; i < m_bufIV.Size(); i++)
m_bufIV[i] = bufHash[i] ^ bufHash[i + 16];
}
catch (CryptoPP::Exception const& e)
{
UNUSED_ALWAYS(e);
m_bInit = false;
return false;
}
return true;
}
BOOL CCryptorAES101::Decrypt(BYTE* pData, DWORD dwSize)
{
if (!m_bInit)
return FALSE;
try
{
#if CRYPTO_VER == 42
CryptoPP::AESEncryption aes(m_bufSeed,m_bufSeed.Size());
CryptoPP::CFBDecryption decryptor(aes,m_bufIV);
#else
CryptoPP::AES::Encryption aes(m_bufSeed,m_bufSeed.size());
CryptoPP::CFB_Mode_ExternalCipher::Decryption decryptor(aes,m_bufIV);
#endif
decryptor.ProcessString(pData,dwSize);
}
catch (CryptoPP::Exception const& e)
{
UNUSED_ALWAYS(e);
return FALSE;
}
return TRUE;
}
The issue you seem to have is that the RNG is, well, actually producing random results.
If you want deterministic behavior, you should avoid RNGs if possible.
To clarify, I'm trying to draw a picture of the old IV generation:
Key -> SHA256 -> RandomPool -> SHA256 -> XOR
"compression" -> IV
| |
+---------------------+
From what I can see, your implementation always tries to produce a static IV, which is only dependent on the key. This is only fine if you never re-use the key, e.g. you never instantiate (and use) a second instance with the same key (for encryption). Otherwise this is an IV re-use which is horribly broken and allows for really easy attacks.
Another issue that I see in this code is the complete absence of
authentication. If an attacker manipulates the cipher text you've
no chance of (cryptographically reliably) detecting it. The fix
would be to use a mode like GCM or EAX.
To fix your current construction (and get the same dangerous behavior back), you can replace RandomPool with HMAC<SHA256> and feed the key in as the key and the hashed key as the message.
To actually fix the problems, you should use
Here are the related wiki pages for EAX and GCM
BR
JPM
--
--
You received this message because you are subscribed to the "Crypto++ Users" Google Group.
To unsubscribe, send an email to cryptopp-user...@googlegroups.com.
More information about Crypto++ and this group is available at http://www.cryptopp.com.
---
You received this message because you are subscribed to the Google Groups "Crypto++ Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cryptopp-user...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
After HMAC is keyed (which you did in the constructor and can also do via SetKey() ) it behaves like a normal hash function, so Update() and Final() or CalculateDigest() are your methods of choice.
So it would be something like:
HMAC<SHA256> hmac(key,keySize); // replace with your parameters hmac.CalculateDigest(target,input,inputSize); // replace with your parametersIf you want to stay with the old style.
CryptoPP::SHA256 hash;
m_bufSeed.Resize(hash.DigestSize());
m_bufIV.Resize(IV_SIZE); //16
hash.CalculateDigest(m_bufSeed, pKey, dwKeySize);
CryptoPP::HMAC<CryptoPP::SHA256> hmac(pKey, dwKeySize);
CryptoPP::MySecByteBlock bufHmac(hmac.DigestSize());
hmac.CalculateDigest(bufHmac, m_bufSeed, m_bufSeed.Size());
for(int i = 0; i < m_bufIV.Size(); i++) {
m_bufIV[i] = bufHmac[i] ^ bufHmac[i + 16];
TRACE("%d ", m_bufIV[i]);
}
The change I proposed tried to maintain the same flow as closely as possible, making HMAC the obvious choice here. If you wanted to exact same results as from 4.2, you'll either have to inspect the 4.2 code and try and reproduce the same results (shouldn't be too hard) or you just copy and paste the implementation from 4.2 into your new project, rename it and be done with it.
BR
JPM
Under cryptopp 4.2, bufSeedIV is always the same, resulting in a bufHash and m_bufIV which are always the same.Under cryptopp 5.6.4 however, bufSeedIV is always different, this is our problem.As far as I can figure, the RandomPool implementation changed over time, but I could be wrong.
Any guidance would be appreciated!
Under cryptopp 4.2, bufSeedIV is always the same, resulting in a bufHash and m_bufIV which are always the same.Under cryptopp 5.6.4 however, bufSeedIV is always different, this is our problem.As far as I can figure, the RandomPool implementation changed over time, but I could be wrong.
Yeah, it changed around May 2007. Here's the [imported] git commit: https://github.com/weidai11/cryptopp/commit/f41245df6fb9b85574260eca9cd32777e8ab5136 .
I'll get the documentation updated. I dont think the sources or Doxygen have a treatment. There's just a blurb on the wiki at https://cryptopp.com/wiki/RandomNumberGenerator#RandomPool.
Apparently the random pool is the cause of our problems. In 5.6.4 it uses time and AES instead of no time and MDC<SHA> in cryptopp 4.2.Is there anyway to replicate the old randpool behaviour, or are there other possible solutions?