Adding AES128 encryption/decryption which works both with gcrypt and openssl. This can be used for encryption of player's cards (not implemented yet).
This commit is contained in:
+104
-24
@@ -231,18 +231,12 @@ CryptHelper::HMACSha1(const unsigned char *keyData, unsigned keySize, const unsi
|
|||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
CryptHelper::AES128Encrypt(const unsigned char *keyData, unsigned keySize, const unsigned char *plainData, unsigned plainSize, std::vector<unsigned char> &outCipher)
|
CryptHelper::BytesToKey(const unsigned char *keyData, unsigned keySize, unsigned char *key, unsigned char *iv)
|
||||||
{
|
{
|
||||||
bool retVal = false;
|
|
||||||
if (keySize && plainSize)
|
|
||||||
{
|
|
||||||
const int AESBlockSize = 16;
|
|
||||||
// The key/iv derivation is kind of like EVP_BytesToKey of OpenSSL with count 2 and no salt.
|
// The key/iv derivation is kind of like EVP_BytesToKey of OpenSSL with count 2 and no salt.
|
||||||
// EVP_BytesToKey is not used because there is nothing like it in GnuTLS or gcrypt.
|
// EVP_BytesToKey is not used because there is nothing like it in GnuTLS or gcrypt.
|
||||||
SHA1Buf tmpBuf1, tmpBuf2, keyBuf1, keyBuf2;
|
SHA1Buf tmpBuf1, tmpBuf2, keyBuf1, keyBuf2;
|
||||||
unsigned char key[AESBlockSize];
|
|
||||||
unsigned char iv[AESBlockSize];
|
|
||||||
// First 20 bytes
|
// First 20 bytes
|
||||||
CryptHelper::SHA1Hash(keyData, keySize, tmpBuf1);
|
CryptHelper::SHA1Hash(keyData, keySize, tmpBuf1);
|
||||||
CryptHelper::SHA1Hash(tmpBuf1.GetData(), tmpBuf1.GetDataSize(), keyBuf1);
|
CryptHelper::SHA1Hash(tmpBuf1.GetData(), tmpBuf1.GetDataSize(), keyBuf1);
|
||||||
@@ -256,43 +250,129 @@ CryptHelper::AES128Encrypt(const unsigned char *keyData, unsigned keySize, const
|
|||||||
CryptHelper::SHA1Hash(tmpBuf2.GetData(), tmpBuf2.GetDataSize(), keyBuf2);
|
CryptHelper::SHA1Hash(tmpBuf2.GetData(), tmpBuf2.GetDataSize(), keyBuf2);
|
||||||
delete[] tmpKeyData;
|
delete[] tmpKeyData;
|
||||||
// Copy the hashes to key/iv.
|
// Copy the hashes to key/iv.
|
||||||
memcpy(key, keyBuf1.GetData(), sizeof(key));
|
memcpy(key, keyBuf1.GetData(), AES_BLOCK_SIZE);
|
||||||
unsigned tmpivBytes = keyBuf1.GetDataSize() - sizeof(key);
|
unsigned tmpivBytes = keyBuf1.GetDataSize() - AES_BLOCK_SIZE;
|
||||||
memcpy(iv, keyBuf1.GetData() + sizeof(key), tmpivBytes);
|
memcpy(iv, keyBuf1.GetData() + AES_BLOCK_SIZE, tmpivBytes);
|
||||||
memcpy(iv + tmpivBytes, keyBuf2.GetData(), sizeof(iv) - tmpivBytes);
|
memcpy(iv + tmpivBytes, keyBuf2.GetData(), AES_BLOCK_SIZE - tmpivBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CryptHelper::AES128Encrypt(const unsigned char *keyData, unsigned keySize, const string &plainStr, std::vector<unsigned char> &outCipher)
|
||||||
|
{
|
||||||
|
bool retVal = false;
|
||||||
|
unsigned plainSize = static_cast<unsigned>(plainStr.size());
|
||||||
|
if (keySize && plainSize)
|
||||||
|
{
|
||||||
|
unsigned char key[AES_BLOCK_SIZE];
|
||||||
|
unsigned char iv[AES_BLOCK_SIZE];
|
||||||
|
BytesToKey(keyData, keySize, key, iv);
|
||||||
|
// Add padding to plain data.
|
||||||
|
unsigned paddedPlainSize = ADD_PADDING(plainSize);
|
||||||
|
unsigned char *paddedPlainStr = new unsigned char[ADD_PADDING(plainSize)];
|
||||||
|
memset(paddedPlainStr, 0, paddedPlainSize);
|
||||||
|
memcpy(paddedPlainStr, plainStr.c_str(), plainSize);
|
||||||
// Perform the encryption.
|
// Perform the encryption.
|
||||||
int cipherSize = plainSize + AESBlockSize; // Maximum possible size + 1
|
int cipherSize = paddedPlainSize;
|
||||||
outCipher.resize(cipherSize);
|
outCipher.resize(cipherSize);
|
||||||
|
|
||||||
#ifdef HAVE_OPENSSL
|
#ifdef HAVE_OPENSSL
|
||||||
EVP_CIPHER_CTX encryptCtx;
|
EVP_CIPHER_CTX encryptCtx;
|
||||||
EVP_CIPHER_CTX_init(&encryptCtx);
|
EVP_CIPHER_CTX_init(&encryptCtx);
|
||||||
EVP_EncryptInit(&encryptCtx, EVP_aes_128_cbc(), key, iv);
|
int outCipherSize = cipherSize;
|
||||||
int updateCipherSize = cipherSize;
|
|
||||||
EVP_EncryptUpdate(&encryptCtx, &outCipher[0], &updateCipherSize, plainData, plainSize);
|
int success = EVP_EncryptInit(&encryptCtx, EVP_aes_128_cbc(), key, iv);
|
||||||
if (updateCipherSize)
|
EVP_CIPHER_CTX_set_padding(&encryptCtx, 0);
|
||||||
|
if (success)
|
||||||
{
|
{
|
||||||
int finalCipherSize = cipherSize - updateCipherSize;
|
success = EVP_EncryptUpdate(&encryptCtx, &outCipher[0], &outCipherSize, paddedPlainStr, paddedPlainSize);
|
||||||
EVP_EncryptFinal(&encryptCtx, &outCipher[updateCipherSize], &finalCipherSize);
|
|
||||||
outCipher.resize(updateCipherSize + finalCipherSize);
|
if (success && outCipherSize)
|
||||||
|
{
|
||||||
|
// Since padding is off, this will not modify the cipher. However, parameters need to be set.
|
||||||
|
EVP_EncryptFinal(&encryptCtx, &outCipher[0], &outCipherSize);
|
||||||
retVal = true;
|
retVal = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
outCipher.clear();
|
outCipher.clear();
|
||||||
#else
|
#else
|
||||||
gcry_cipher_hd_t hd;
|
gcry_cipher_hd_t hd;
|
||||||
gcry_error_t err = gcry_cipher_open (&hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, 0);
|
gcry_error_t err = gcry_cipher_open(&hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, 0);
|
||||||
if (!err)
|
if (!err)
|
||||||
{
|
{
|
||||||
gcry_cipher_setkey(hd, key, sizeof(key));
|
gcry_cipher_setkey(hd, key, sizeof(key));
|
||||||
gcry_cipher_setiv(hd, iv, sizeof(iv));
|
gcry_cipher_setiv(hd, iv, sizeof(iv));
|
||||||
err = gcry_cipher_encrypt(hd, &outCipher[0], cipherSize, plainData, plainSize);
|
err = gcry_cipher_encrypt(hd, &outCipher[0], cipherSize, paddedPlainStr, paddedPlainSize);
|
||||||
if (!err)
|
if (!err)
|
||||||
{
|
|
||||||
retVal = true;
|
retVal = true;
|
||||||
|
else
|
||||||
|
outCipher.clear();
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
outCipher.clear();
|
||||||
|
|
||||||
|
gcry_cipher_close(hd);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CryptHelper::AES128Decrypt(const unsigned char *keyData, unsigned keySize, const unsigned char *cipher, unsigned cipherSize, string &outPlain)
|
||||||
|
{
|
||||||
|
bool retVal = false;
|
||||||
|
if (keySize && cipherSize)
|
||||||
|
{
|
||||||
|
unsigned char key[AES_BLOCK_SIZE];
|
||||||
|
unsigned char iv[AES_BLOCK_SIZE];
|
||||||
|
BytesToKey(keyData, keySize, key, iv);
|
||||||
|
outPlain.resize(cipherSize);
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
EVP_CIPHER_CTX decryptCtx;
|
||||||
|
EVP_CIPHER_CTX_init(&decryptCtx);
|
||||||
|
int outPlainSize = cipherSize;
|
||||||
|
|
||||||
|
int success = EVP_DecryptInit(&decryptCtx, EVP_aes_128_cbc(), key, iv);
|
||||||
|
EVP_CIPHER_CTX_set_padding(&decryptCtx, 0);
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
success = EVP_DecryptUpdate(&decryptCtx, (unsigned char *)&outPlain[0], &outPlainSize, cipher, cipherSize);
|
||||||
|
|
||||||
|
if (success && outPlainSize)
|
||||||
|
{
|
||||||
|
// Since padding is off, this will not modify the plain text. However, parameters need to be set.
|
||||||
|
EVP_DecryptFinal(&decryptCtx, (unsigned char *)outPlain.c_str(), &outPlainSize);
|
||||||
|
retVal = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
outPlain.clear();
|
||||||
|
#else
|
||||||
|
gcry_cipher_hd_t hd;
|
||||||
|
gcry_error_t err = gcry_cipher_open(&hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, 0);
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
gcry_cipher_setkey(hd, key, sizeof(key));
|
||||||
|
gcry_cipher_setiv(hd, iv, sizeof(iv));
|
||||||
|
err = gcry_cipher_decrypt(hd, &outPlain[0], outPlain.size(), cipher, cipherSize);
|
||||||
|
if (!err)
|
||||||
|
retVal = true;
|
||||||
|
else
|
||||||
|
outPlain.clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
outPlain.clear();
|
||||||
|
|
||||||
|
gcry_cipher_close(hd);
|
||||||
|
#endif
|
||||||
|
// Remove trailing zeroes (padding).
|
||||||
|
if (!outPlain.empty())
|
||||||
|
{
|
||||||
|
size_t pos = outPlain.find_first_of('\0');
|
||||||
|
if (pos != string::npos)
|
||||||
|
outPlain = outPlain.substr(0, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,9 @@
|
|||||||
#define MD5_DATA_SIZE 16
|
#define MD5_DATA_SIZE 16
|
||||||
#define SHA1_DATA_SIZE 20
|
#define SHA1_DATA_SIZE 20
|
||||||
|
|
||||||
|
#define AES_BLOCK_SIZE 16
|
||||||
|
#define ADD_PADDING(x) ((((x) + 15) >> 4) << 4)
|
||||||
|
|
||||||
class HashBuf
|
class HashBuf
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -76,7 +79,11 @@ public:
|
|||||||
static bool MD5Sum(const std::string &fileName, MD5Buf &buf);
|
static bool MD5Sum(const std::string &fileName, MD5Buf &buf);
|
||||||
static bool SHA1Hash(const unsigned char *data, unsigned dataSize, SHA1Buf &buf);
|
static bool SHA1Hash(const unsigned char *data, unsigned dataSize, SHA1Buf &buf);
|
||||||
static bool HMACSha1(const unsigned char *keyData, unsigned keySize, const unsigned char *plainData, unsigned plainSize, SHA1Buf &buf);
|
static bool HMACSha1(const unsigned char *keyData, unsigned keySize, const unsigned char *plainData, unsigned plainSize, SHA1Buf &buf);
|
||||||
static bool AES128Encrypt(const unsigned char *keyData, unsigned keySize, const unsigned char *plainData, unsigned plainSize, std::vector<unsigned char> &outCipher);
|
static bool AES128Encrypt(const unsigned char *keyData, unsigned keySize, const std::string &plainStr, std::vector<unsigned char> &outCipher);
|
||||||
|
static bool AES128Decrypt(const unsigned char *keyData, unsigned keySize, const unsigned char *cipher, unsigned cipherSize, std::string &outPlain);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void BytesToKey(const unsigned char *keyData, unsigned keySize, unsigned char *key, unsigned char *iv);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user