32 #include <openssl/aes.h>
33 #include <openssl/bio.h>
34 #include <openssl/evp.h>
35 #include <openssl/buffer.h>
41 #define DBG_PRE __FILE__ << ":" << __LINE__ << ": "
42 #define DBG_FCT(fct) if(m_debug) cout << DBG_PRE << "FCT " << fct << endl
43 #define DBG_TDUMP(v) if(m_debug) tdump(__FILE__,__LINE__,#v,v)
44 #define DBG_PKV(v) if(m_debug) vdump(__FILE__,__LINE__,#v,v)
45 #define DBG_PKVR(k,v) if(m_debug) vdump(__FILE__,__LINE__,k,v)
46 #define DBG_BDUMP(a,x) if(m_debug) bdump(__FILE__,__LINE__,#a,a,x)
47 #define DBG_MDUMP(a) if(m_debug) bdump(__FILE__,__LINE__,#a,(unsigned char*)a.c_str(),a.size())
48 #define DBG_MADEIT cout << DBG_PRE << "MADE IT" << endl
49 #define PKV(v) vdump(__FILE__,__LINE__,#v,v)
51 #define SALTED_PREFIX "Salted__"
59 template<
typename T>
void vdump(
const string& fn,
64 cout << fn <<
":" << ln <<
": " << prefix <<
"\t" << d << endl;
76 cout << fn <<
":" << ln <<
": "
78 << left << setw(64) << d
79 <<
" (" << d.size() <<
")"
86 template<
typename T>
void tdump(
const string& fn,
91 cout << fn <<
":" << ln <<
": " << prefix <<
"\t";
92 for(uint i=0;i<
sizeof(T);++i) {
102 if (prefix.size()<4) {
112 cout << setw(2) << setfill(
'0') << hex << right << uint(d[i]) << dec << setfill(
' ');
114 cout <<
" (" <<
sizeof(T) <<
")" << endl;
122 const string& prefix,
126 cout << fn <<
":" << ln <<
": " << prefix;
127 for(uint i=0;i<len;++i) {
140 cout << setw(2) << hex << right << uint(a[i]) << dec;
142 cout <<
" (" << len <<
")" << endl;
162 const std::string& digest,
192 uint ctlen = x.second;
211 string ciphertext =
encrypt(plaintext,pass,salt);
226 uint ctlen = x.second;
254 string plaintext =
decrypt(ciphertext,pass,salt);
262 uint ciphertext_len)
const
265 BIO* b64 = BIO_new(BIO_f_base64());
266 BIO* bm = BIO_new(BIO_s_mem());
267 b64 = BIO_push(b64,bm);
268 if (BIO_write(b64,ciphertext,ciphertext_len)<2) {
269 throw runtime_error(
"BIO_write() failed");
271 if (BIO_flush(b64)<1) {
272 throw runtime_error(
"BIO_flush() failed");
275 BIO_get_mem_ptr(b64,&bptr);
276 uint len=bptr->length;
277 char* mimetext =
new char[len+1];
278 memcpy(mimetext, bptr->data, bptr->length-1);
279 mimetext[bptr->length-1]=0;
282 string ret = mimetext;
294 int SZ=mimetext.size();
295 x.first =
new uchar[SZ];
296 char* tmpbuf =
new char[SZ+1];
297 strcpy(tmpbuf,mimetext.c_str());
298 BIO* b64 = BIO_new(BIO_f_base64());
308 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
311 BIO* bm = BIO_new_mem_buf(tmpbuf,mimetext.size());
312 bm = BIO_push(b64,bm);
313 x.second = BIO_read(bm,x.first,SZ);
325 uint SZ=plaintext.size()+AES_BLOCK_SIZE+20;
327 bzero(ciphertext,SZ);
328 uchar* pbeg = ciphertext;
338 memcpy(&ciphertext[8],
m_salt,8);
343 int ciphertext_len=0;
344 int ciphertext_padlen=0;
346 EVP_CIPHER_CTX_init(&ctx);
348 if (!EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL,
m_key,
m_iv)) {
349 throw runtime_error(
"EVP_EncryptInit_ex() failed");
351 EVP_CIPHER_CTX_set_key_length(&ctx, EVP_MAX_KEY_LENGTH);
354 uint plen = plaintext.size();
355 if (!EVP_EncryptUpdate(&ctx,ciphertext,&ciphertext_len,p,plen)) {
356 throw runtime_error(
"EVP_EncryptUpdate() failed");
359 uchar* pbuf = ciphertext+ciphertext_len;
360 if (!EVP_EncryptFinal_ex(&ctx,pbuf,&ciphertext_padlen)) {
361 throw runtime_error(
"EVP_EncryptFinal_ex() failed");
364 ciphertext_len += ciphertext_padlen + off;
365 return kv1_t(pbeg,ciphertext_len);
372 uint ciphertext_len)
const
375 uint SZ = ciphertext_len+20;
378 int plaintext_len = 0;
380 EVP_CIPHER_CTX_init(&ctx);
382 if (!EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL,
m_key,
m_iv)) {
383 throw runtime_error(
"EVP_DecryptInit_ex() failed");
385 EVP_CIPHER_CTX_set_key_length(&ctx, EVP_MAX_KEY_LENGTH);
387 if (!EVP_DecryptUpdate(&ctx,plaintext,&plaintext_len,ciphertext,ciphertext_len)) {
388 throw runtime_error(
"EVP_DecryptUpdate() failed");
391 int plaintext_padlen=0;
392 if (!EVP_DecryptFinal_ex(&ctx,plaintext+plaintext_len,&plaintext_padlen)) {
393 throw runtime_error(
"EVP_DecryptFinal_ex() failed");
395 plaintext_len += plaintext_padlen;
396 plaintext[plaintext_len] = 0;
398 string ret = (
char*)plaintext;
409 if (salt.length() == 0) {
415 else if (salt.length() == 8) {
416 memcpy(
m_salt,salt.c_str(),8);
418 else if (salt.length()<8) {
419 throw underflow_error(
"init(): salt is too short, must be 8 characters");
421 else if (salt.length()>8) {
422 throw overflow_error(
"init(): salt is too long, must be 8 characters");
437 char a[] = {
' ',
'd',
'e',
'F',
'a',
'u',
'1',
't',
' ',
438 'p',
'A',
'S',
's',
'w',
'0',
'r',
'D',0};
445 OpenSSL_add_all_algorithms();
446 const EVP_CIPHER* cipher = EVP_get_cipherbyname(
m_cipher.c_str());
447 const EVP_MD* digest = EVP_get_digestbyname(
m_digest.c_str());
449 string msg =
"init(): cipher does not exist "+
m_cipher;
450 throw runtime_error(msg);
453 string msg =
"init(): digest does not exist "+
m_digest;
454 throw runtime_error(msg);
457 int ks = EVP_BytesToKey(cipher,
466 throw runtime_error(
"init() failed: "
467 "EVP_BytesToKey did not return a 32 byte key");
485 ifstream ifs(fn.c_str());
487 string msg=
"Cannot read file '"+fn+
"'";
488 throw runtime_error(msg);
490 string str((istreambuf_iterator<char>(ifs)),
491 istreambuf_iterator<char>());
501 ofstream ofs(fn.c_str());
503 string msg=
"Cannot write file '"+fn+
"'";
504 throw runtime_error(msg);
std::string decrypt(const std::string &ciphertext, const std::string &pass="", const std::string &salt="")
Decrypt a buffer using AES 256 CBC (SHA1).
std::pair< uchar *, uint > kv1_t
void encrypt_file(const std::string &ifn, const std::string &ofn, const std::string &pass="", const std::string &salt="")
Encrypt a file.
void file_write(const std::string &fn, const std::string &data, bool nl=false) const
Write ASCII data to a file.
void vdump< string >(const string &fn, uint ln, const string &prefix, const string &d)
std::string encrypt(const std::string &plaintext, const std::string &pass="", const std::string &salt="")
Encrypt buffer using AES 256 CBC (SHA1).
void vdump(const string &fn, uint ln, const string &prefix, const T &d)
#define CIPHER_DEFAULT_COUNT
#define CIPHER_DEFAULT_DIGEST
std::string decode_cipher(uchar *ciphertext, uint ciphertext_len) const
Cipher decode.
std::string file_read(const std::string &fn) const
Read a file into a buffer.
void set_salt(const std::string &salt)
Convert string salt to internal format.
#define CIPHER_DEFAULT_CIPHER
void init(const std::string &pass)
Initialize the cipher: set the key and IV values.
kv1_t encode_cipher(const std::string &plaintext) const
Cipher encode.
std::string encode_base64(uchar *ciphertext, uint ciphertext_len) const
Base64 encode.
kv1_t decode_base64(const std::string &mimetext) const
Base64 decode.
void decrypt_file(const std::string &ifn, const std::string &ofn, const std::string &pass="", const std::string &salt="")
Decrypt a file.
void bdump(const string &fn, uint ln, const string &prefix, unsigned char *a, unsigned int len)
void tdump(const string &fn, uint ln, const string &prefix, const T &d)