backport CipherKey digest changes and tests from develop

This commit is contained in:
Alex Fabijanic 2017-09-26 11:38:53 -05:00
parent b4f1427725
commit dc2c4dcd27
6 changed files with 88 additions and 6 deletions

View File

@ -61,7 +61,8 @@ public:
CipherKey(const std::string& name,
const std::string& passphrase,
const std::string& salt = "",
int iterationCount = DEFAULT_ITERATION_COUNT);
int iterationCount = DEFAULT_ITERATION_COUNT,
const std::string& digest = "md5");
/// Creates a new CipherKeyImpl object using the given
/// cipher name, passphrase, salt value and iteration count.

View File

@ -54,7 +54,8 @@ public:
CipherKeyImpl(const std::string& name,
const std::string& passphrase,
const std::string& salt,
int iterationCount);
int iterationCount,
const std::string& digest);
/// Creates a new CipherKeyImpl object, using
/// the given cipher name, passphrase, salt value
/// and iteration count.
@ -116,6 +117,7 @@ private:
private:
const EVP_CIPHER* _pCipher;
const EVP_MD* _pDigest;
std::string _name;
ByteVec _key;
ByteVec _iv;

View File

@ -19,8 +19,12 @@ namespace Poco {
namespace Crypto {
CipherKey::CipherKey(const std::string& name, const std::string& passphrase, const std::string& salt, int iterationCount):
_pImpl(new CipherKeyImpl(name, passphrase, salt, iterationCount))
CipherKey::CipherKey(const std::string& name,
const std::string& passphrase,
const std::string& salt,
int iterationCount,
const std::string &digest):
_pImpl(new CipherKeyImpl(name, passphrase, salt, iterationCount, digest))
{
}

View File

@ -28,8 +28,10 @@ namespace Crypto {
CipherKeyImpl::CipherKeyImpl(const std::string& name,
const std::string& passphrase,
const std::string& salt,
int iterationCount):
int iterationCount,
const std::string& digest):
_pCipher(0),
_pDigest(0),
_name(name),
_key(),
_iv()
@ -40,6 +42,12 @@ CipherKeyImpl::CipherKeyImpl(const std::string& name,
if (!_pCipher)
throw Poco::NotFoundException("Cipher " + name + " was not found");
_pDigest = EVP_get_digestbyname(digest.c_str());
if (!_pDigest)
throw Poco::NotFoundException("Digest " + name + " was not found");
_key = ByteVec(keySize());
_iv = ByteVec(ivSize());
generateKey(passphrase, salt, iterationCount);
@ -50,6 +58,7 @@ CipherKeyImpl::CipherKeyImpl(const std::string& name,
const ByteVec& key,
const ByteVec& iv):
_pCipher(0),
_pDigest(0),
_name(name),
_key(key),
_iv(iv)
@ -65,6 +74,7 @@ CipherKeyImpl::CipherKeyImpl(const std::string& name,
CipherKeyImpl::CipherKeyImpl(const std::string& name):
_pCipher(0),
_pDigest(0),
_name(name),
_key(),
_iv()
@ -157,7 +167,7 @@ void CipherKeyImpl::generateKey(
// Now create the key and IV, using the MD5 digest algorithm.
int keySize = EVP_BytesToKey(
_pCipher,
EVP_md5(),
_pDigest ? _pDigest : EVP_md5(),
(salt.empty() ? 0 : saltBytes),
reinterpret_cast<const unsigned char*>(password.data()),
static_cast<int>(password.size()),

View File

@ -18,6 +18,7 @@
#include "Poco/Crypto/CryptoStream.h"
#include "Poco/StreamCopier.h"
#include "Poco/Base64Encoder.h"
#include "Poco/HexBinaryEncoder.h"
#include <sstream>
@ -124,6 +125,39 @@ void CryptoTest::testEncryptDecryptWithSalt()
}
void CryptoTest::testEncryptDecryptWithSaltSha1()
{
Cipher::Ptr pCipher = CipherFactory::defaultFactory().createCipher(
CipherKey("aes256", "simplepwd", "Too much salt", 2000, "sha1"));
Cipher::Ptr pCipher2 = CipherFactory::defaultFactory().createCipher(
CipherKey("aes256", "simplepwd", "Too much salt", 2000, "sha1"));
for (std::size_t n = 1; n < MAX_DATA_SIZE; n++)
{
std::string in(n, 'x');
std::string out = pCipher->encryptString(in, Cipher::ENC_NONE);
std::string result = pCipher2->decryptString(out, Cipher::ENC_NONE);
assert (in == result);
}
for (std::size_t n = 1; n < MAX_DATA_SIZE; n++)
{
std::string in(n, 'x');
std::string out = pCipher->encryptString(in, Cipher::ENC_BASE64);
std::string result = pCipher2->decryptString(out, Cipher::ENC_BASE64);
assert (in == result);
}
for (std::size_t n = 1; n < MAX_DATA_SIZE; n++)
{
std::string in(n, 'x');
std::string out = pCipher->encryptString(in, Cipher::ENC_BINHEX);
std::string result = pCipher2->decryptString(out, Cipher::ENC_BINHEX);
assert (in == result);
}
}
void CryptoTest::testEncryptDecryptDESECB()
{
Cipher::Ptr pCipher = CipherFactory::defaultFactory().createCipher(CipherKey("des-ecb", "password"));
@ -167,6 +201,33 @@ void CryptoTest::testPassword()
}
void CryptoTest::testPasswordSha1()
{
// the test uses 1 iteration, as the openssl executable does not allow to set a custom number
// of iterations
CipherKey key("aes256", "password", "saltsalt", 1, "sha1");
std::ostringstream keyStream;
Poco::HexBinaryEncoder hexKeyEnc(keyStream);
hexKeyEnc.write(reinterpret_cast<const char*>(&key.getKey()[0]), key.keySize());
hexKeyEnc.close();
std::string hexKey = keyStream.str();
std::ostringstream ivStream;
Poco::HexBinaryEncoder hexIvEnc(ivStream);
hexIvEnc.write(reinterpret_cast<const char*>(&key.getIV()[0]), key.ivSize());
hexIvEnc.close();
std::string hexIv = ivStream.str();
// got Hex value for key and iv using:
// openssl enc -e -a -md sha1 -aes256 -k password -S 73616c7473616c74 -P
// (where "salt" == 73616c74 in Hex, doubled for an 8 bytes salt, openssl padds the salt with 0
// whereas Poco's implementation padds with the existing bytes using a modulo operation)
assert (hexIv == "c96049b0edc0b67af61ecc43d3de8898");
assert (hexKey == "cab86dd6261710891e8cb56ee3625691a75df344f0bff4c12cf3596fc00b39c7");
}
void CryptoTest::testEncryptInterop()
{
Cipher::Ptr pCipher = CipherFactory::defaultFactory().createCipher(CipherKey("aes256", "password", "salt"));
@ -268,8 +329,10 @@ CppUnit::Test* CryptoTest::suite()
CppUnit_addTest(pSuite, CryptoTest, testEncryptDecrypt);
CppUnit_addTest(pSuite, CryptoTest, testEncryptDecryptWithSalt);
CppUnit_addTest(pSuite, CryptoTest, testEncryptDecryptWithSaltSha1);
CppUnit_addTest(pSuite, CryptoTest, testEncryptDecryptDESECB);
CppUnit_addTest(pSuite, CryptoTest, testPassword);
CppUnit_addTest(pSuite, CryptoTest,testPasswordSha1);
CppUnit_addTest(pSuite, CryptoTest, testEncryptInterop);
CppUnit_addTest(pSuite, CryptoTest, testDecryptInterop);
CppUnit_addTest(pSuite, CryptoTest, testStreams);

View File

@ -31,9 +31,11 @@ public:
void testEncryptDecrypt();
void testEncryptDecryptWithSalt();
void testEncryptDecryptWithSaltSha1();
void testEncryptDecryptDESECB();
void testStreams();
void testPassword();
void testPasswordSha1();
void testEncryptInterop();
void testDecryptInterop();
void testCertificate();