#ifndef AES_H_
#define AES_H_
#include
"cryptopp/modes.h"
#include
"cryptopp/aes.h"
#include
"cryptopp/osrng.h"
#include
"cryptopp/pwdbased.h"
#include
"cryptopp/hex.h"
#include
"cryptopp/base64.h"
using namespace std;
using namespace
CryptoPP;
class Aes {
public:
Aes();
virtual
~Aes();
private:
string
_cipherText;
string
_recoveredText;
//
secret key
SecByteBlock
_derivedKey; // TODO get better name
//
initialization vector
//
AES IV is 16 bytes, 128 bits
//byte
_iv[AES::BLOCKSIZE];
SecByteBlock
_iv;
public:
void
createRandomIV();
void
createKey();
void
encrypt(string clearText);
void
encrypt(string clearText, byte *iv);
void
encrypt(string clearText, SecByteBlock iv);
void
decrypt();
void
decrypt(string cipherTextHex);
void
decrypt(string cipherTextHex, string ivHex);
const
SecByteBlock& getIv() const {
return
_iv;
}
void
setIv(SecByteBlock iv) {
_iv
= iv;
}
const
SecByteBlock& getDerivedKey() const {
return
_derivedKey;
}
void
setDerivedKey(SecByteBlock derivedKey) {
_derivedKey
= derivedKey;
}
const
string& getCipherText() const {
return
_cipherText;
}
void
setCipherText(const string& cipherText) {
_cipherText
= cipherText;
}
const
string& getRecoveredText() const {
return
_recoveredText;
}
void
setRecoveredText(const string& recoveredText) {
_recoveredText
= recoveredText;
}
};
#endif /* AES_H_ */
#include "Aes.h"
Aes::Aes() {
}
Aes::~Aes() {
}
void
Aes::createRandomIV() {
AutoSeededRandomPool
rnd;
SecByteBlock
iv(AES::BLOCKSIZE);
rnd.GenerateBlock(iv,
AES::BLOCKSIZE);
setIv(iv);
}
void Aes::createKey() {
string
password = "This is my password";
byte
*passwordBytes = (byte *) password.data();
//
128 bit/16 byte salt
//
AES::DEFAULT_KEYLENGTH = 16
// salt
modified for post
byte
salt[] = { (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte)
0x04,
(byte)
0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08, (byte) 0x09,
(byte)
0x0a, (byte) 0x0b, (byte) 0x0c, (byte) 0x0d, (byte) 0x0e,
(byte)
0x0f, (byte) 0x10 };
//
number of iterations for key derivation
int
iterations = 65536;
//
derive key from password and salt
//SecByteBlock
derivedKey(32); // 256 bits, default is 128 bits/16 bytes
SecByteBlock
derivedKey(AES::DEFAULT_KEYLENGTH);
PKCS5_PBKDF2_HMAC<SHA1>
pbkdf;
pbkdf.DeriveKey(derivedKey,
derivedKey.size(), 0x00, passwordBytes,
password.size(),
salt, sizeof(salt), iterations);
setDerivedKey(derivedKey);
}
void
Aes::encrypt(string clearText) {
SecByteBlock
key = getDerivedKey();
string
cipherText;
CBC_Mode<AES>::Encryption
encryptor(key, key.size(), getIv());
StringSource(clearText,
true,
new
StreamTransformationFilter(encryptor,
new
StringSink(cipherText)));
setCipherText(cipherText);
}
void
Aes::encrypt(string clearText, SecByteBlock iv) {
SecByteBlock
key = getDerivedKey();
string
cipherText;
CBC_Mode<AES>::Encryption
encryptor(key, key.size(), iv);
StringSource(clearText,
true,
new
StreamTransformationFilter(encryptor,
new
StringSink(cipherText)));
setCipherText(cipherText);
}
void Aes::decrypt() {
SecByteBlock
key = getDerivedKey();
string
recoveredText;
CBC_Mode<AES>::Decryption
decryptor(key, key.size(), getIv());
StringSource(getCipherText(),
true,
new
StreamTransformationFilter(decryptor,
new
StringSink(recoveredText)));
setRecoveredText(recoveredText);
}
void
Aes::decrypt(string cipherTextHex) {
SecByteBlock
key = getDerivedKey();
string
recoveredText;
CBC_Mode<AES>::Decryption
decryptor(key, key.size(), getIv());
StringSource(cipherTextHex,
true,
new
HexDecoder(
new
StreamTransformationFilter(decryptor,
new
StringSink(recoveredText))));
setRecoveredText(recoveredText);
}
// not working
void
Aes::decrypt(string cipherTextHex, string ivHex) {
string
recoveredText;
SecByteBlock
recoverediv(AES::BLOCKSIZE);
SecByteBlock
key = getDerivedKey();
StringSource
ivDecoder(ivHex, true,
new
HexDecoder(new ArraySink(recoverediv, recoverediv.size())));
CFB_Mode<AES>::Decryption
decryptor(key, key.size(), recoverediv);
StringSource(cipherTextHex,
true,
new
HexDecoder(
new
StreamTransformationFilter(decryptor,
new
StringSink(recoveredText))));
setRecoveredText(recoveredText);
}
#include
<iostream>
#include <string>
#include "Aes.h"
#include
"ServerSocket.h"
#include
"SocketException.h"
int main(int argc, char
*argv[]) {
Aes
*aes = new Aes();
aes->createRandomIV();
SecByteBlock
iv = aes->getIv();
aes->createKey();
// aes->encrypt("Hello!
How are you."); // works
aes->encrypt("Hello!
How are you.", iv); // works
// aes->decrypt();
// works
string
ivHex;
string
cipherHex;
//
both encoders, String or Array Source, work
StringSource(iv,
iv.size(), true,
new
HexEncoder(new StringSink(ivHex), false)
);
// ArraySource(iv,
iv.size(), true,
// new
HexEncoder(new StringSink(ivHex), false)
// );
StringSource(aes->getCipherText(),
true,
new
HexEncoder(new StringSink(cipherHex), false)
);
cout
<< " " << iv.size() << endl;
// cout
<< "iv: " << iv << endl;
cout
<< " " << ivHex.length() << endl;
cout
<< "iv hex: " << ivHex << std::endl;
cout
<< "cipher: " << aes->getCipherText()
<< endl;
cout
<< "ciphHex:" << cipherHex << endl;
aes->decrypt(cipherHex);
// works
cout
<< "Recovered text 1: " <<
aes->getRecoveredText() << std::endl;
aes->decrypt(cipherHex,
ivHex); // fails
cout
<< "Recovered text 2: " <<
aes->getRecoveredText() << std::endl;
delete
(aes);
return
0;
}