Merge branch 'PR#260' into mysql-password-encryption

This commit is contained in:
Mészáros Mihály 2018-08-16 07:40:45 +02:00
commit 91f991a9fe
4 changed files with 394 additions and 118 deletions

View File

@ -276,6 +276,16 @@
#
#mysql-userdb="host=<host> dbname=<database-name> user=<database-user> password=<database-user-password> port=<port> connect_timeout=<seconds> read_timeout=<seconds>"
#If you want to use password as encrpyted in the mysql connection string MySQL encrypted connection, this is key path.
#This is the file path which contain secret key of aes encryption while using password encryption.
#This attribute should be use if allow-encoding-with-aes set to 1.
#secret-key-file=/path/
#If you want to use password as encrpyted in the mysql connection string. Set allow-encoding-with-aes to 1.
#If you want to use clearteaxt password in the mysql connection string. Set allow-encoding-with-aes to 0.
#You have to enable secret-key-file attribute above as a key location.
#allow-encoding-with-aes=1 or 0
# MongoDB database connection string in the case that we are using MongoDB
# as the user database.
# This database can be used for long-term credential mechanism

View File

@ -35,6 +35,7 @@
#if !defined(TURN_NO_MYSQL)
#include <mysql.h>
///////////////////////////////////////////////////////////////////////////////////////////////////////////
static int donot_print_connection_success = 0;
@ -72,6 +73,33 @@ static void MyconninfoFree(Myconninfo *co) {
ns_bzero(co,sizeof(Myconninfo));
}
}
struct ctr_state state;
char* decryptPassword(char* in, const unsigned char* mykey){
char *out;
unsigned char iv[8] = {0}; //changed
AES_KEY key;
unsigned char outdata[256]; //changed
AES_set_encrypt_key(mykey, 128, &key);
int newTotalSize=decodedTextSize(in);
int bytes_to_decode = strlen(in);
unsigned char *encryptedText = base64decode(in, bytes_to_decode); //changed
char last[1024]="";
init_ctr(&state, iv);
memset(outdata,'\0', sizeof(outdata));
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
CRYPTO_ctr128_encrypt(encryptedText, outdata, newTotalSize, &key, state.ivec, state.ecount, &state.num,(block128_f)AES_encrypt);
#else
AES_ctr128_encrypt(encryptedText, outdata, newTotalSize, &key, state.ivec, state.ecount, &state.num);
#endif
strcat(last,(char*)outdata);
out=malloc(sizeof(char)*strlen(last));
strcpy(out,last);
return out;
}
static Myconninfo *MyconninfoParse(char *userdb, char **errmsg) {
Myconninfo *co = (Myconninfo*)turn_malloc(sizeof(Myconninfo));
@ -234,6 +262,11 @@ static MYSQL *get_mydb_connection(void) {
if(co->ca || co->capath || co->cert || co->cipher || co->key) {
mysql_ssl_set(mydbconnection, co->key, co->cert, co->ca, co->capath, co->cipher);
}
if(turn_params.allow_encoding){
co->password = decryptPassword(co->password, turn_params.secret_key);
}
MYSQL *conn = mysql_real_connect(mydbconnection, co->host, co->user, co->password, co->dbname, co->port, NULL, CLIENT_IGNORE_SIGPIPE);
if(!conn) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open MySQL DB connection: <%s>, runtime error\n",pud->userdb);
@ -245,6 +278,10 @@ static MYSQL *get_mydb_connection(void) {
mydbconnection=NULL;
} else if(!donot_print_connection_success) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "MySQL DB connection success: %s\n",pud->userdb);
if(turn_params.allow_encoding)
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Connection is secure.\n");
else
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Connection is not secure.\n");
donot_print_connection_success = 1;
}
}

View File

@ -116,7 +116,7 @@ DEFAULT_STUN_PORT,DEFAULT_STUN_TLS_PORT,0,0,1,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,NULL,NULL,NULL
},
{NULL, 0},{NULL, 0},
NEV_UNKNOWN,
NEV_UNKNOWN,
{ "Unknown", "UDP listening socket per session", "UDP thread per network endpoint", "UDP thread per CPU core" },
//////////////// Relay servers //////////////////////////////////
LOW_DEFAULT_PORTS_BOUNDARY,HIGH_DEFAULT_PORTS_BOUNDARY,0,0,0,"",
@ -650,6 +650,8 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n"
" -I, --list-origins List origin-to-realm relations.\n"
" -g, --set-realm-option Set realm params: max-bps, total-quota, user-quota.\n"
" -G, --list-realm-options List realm params.\n"
" -E, --generate-encrypted-password-aes Generate and print to the standard\n"
" output an encrypted form of password with AES-128\n"
"\nOptions with mandatory values:\n\n"
#if !defined(TURN_NO_SQLITE)
" -b, --db, --userdb SQLite database file, default value is /var/db/turndb or\n"
@ -670,6 +672,9 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n"
" -u, --user Username\n"
" -r, --realm Realm\n"
" -p, --password Password\n"
" -x, --key-path Generates a 128 bit key into the given path.\n"
" -f, --file-key-path Contains a 128 bit key in the given path.\n"
" -v, --verify Verify a given base64 encrypted type password.\n"
#if !defined(TURN_NO_SQLITE) || !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_MONGO) || !defined(TURN_NO_HIREDIS)
" -o, --origin Origin\n"
#endif
@ -682,8 +687,8 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n"
" -h, --help Help\n";
#define OPTIONS "c:d:p:L:E:X:i:m:l:r:u:b:B:e:M:J:N:O:q:Q:s:C:vVofhznaAS"
#define ADMIN_OPTIONS "PgGORIHKYlLkaADSdb:e:M:J:N:u:r:p:s:X:o:h"
#define ADMIN_OPTIONS "PEgGORIHKYlLkaADSdb:e:M:J:N:u:r:p:s:X:o:h:x:v:f:"
enum EXTRA_OPTS {
NO_UDP_OPT=256,
@ -751,7 +756,9 @@ enum EXTRA_OPTS {
SERVER_NAME_OPT,
OAUTH_OPT,
PROD_OPT,
NO_HTTP_OPT
NO_HTTP_OPT,
SECRET_KEY_OPT,
ALLOW_ENCODING_OPT
};
struct myoption {
@ -870,11 +877,14 @@ static const struct myoption long_options[] = {
{ "no-tlsv1", optional_argument, NULL, NO_TLSV1_OPT },
{ "no-tlsv1_1", optional_argument, NULL, NO_TLSV1_1_OPT },
{ "no-tlsv1_2", optional_argument, NULL, NO_TLSV1_2_OPT },
{ "secret-key-file", required_argument, NULL, SECRET_KEY_OPT },
{ "allow-encoding-with-aes", required_argument, NULL, ALLOW_ENCODING_OPT},
{ NULL, no_argument, NULL, 0 }
};
static const struct myoption admin_long_options[] = {
{"generate-encrypted-password", no_argument, NULL, 'P' },
{"generate-encrypted-password-aes", no_argument, NULL, 'E'},
{ "key", no_argument, NULL, 'k' },
{ "add", no_argument, NULL, 'a' },
{ "delete", no_argument, NULL, 'd' },
@ -906,6 +916,9 @@ static const struct myoption admin_long_options[] = {
{ "user", required_argument, NULL, 'u' },
{ "realm", required_argument, NULL, 'r' },
{ "password", required_argument, NULL, 'p' },
{ "file-key-path", required_argument, NULL, 'f' },
{ "verify", required_argument, NULL, 'v' },
{ "key-path", required_argument, NULL, 'x'},
{ "add-origin", no_argument, NULL, 'O' },
{ "del-origin", no_argument, NULL, 'R' },
{ "list-origins", required_argument, NULL, 'I' },
@ -919,6 +932,142 @@ static const struct myoption admin_long_options[] = {
{ NULL, no_argument, NULL, 0 }
};
struct ctr_state state;
int init_ctr(struct ctr_state *state, const unsigned char iv[8]){
state->num = 0;
memset(state->ecount, 0, 16);
memset(state->ivec + 8, 0, 8);
memcpy(state->ivec, iv, 8);
return 1;
}
unsigned char *base64encode (const void *b64_encode_this, int encode_this_many_bytes){
BIO *b64_bio, *mem_bio; //Declares two OpenSSL BIOs: a base64 filter and a memory BIO.
BUF_MEM *mem_bio_mem_ptr; //Pointer to a "memory BIO" structure holding our base64 data.
b64_bio = BIO_new(BIO_f_base64()); //Initialize our base64 filter BIO.
mem_bio = BIO_new(BIO_s_mem()); //Initialize our memory sink BIO.
BIO_push(b64_bio, mem_bio); //Link the BIOs by creating a filter-sink BIO chain.
BIO_set_flags(b64_bio, BIO_FLAGS_BASE64_NO_NL); //No newlines every 64 characters or less.
BIO_write(b64_bio, b64_encode_this, encode_this_many_bytes); //Records base64 encoded data.
BIO_flush(b64_bio); //Flush data. Necessary for b64 encoding, because of pad characters.
BIO_get_mem_ptr(mem_bio, &mem_bio_mem_ptr); //Store address of mem_bio's memory structure.
BIO_set_close(mem_bio, BIO_NOCLOSE); //Permit access to mem_ptr after BIOs are destroyed.
BIO_free_all(b64_bio); //Destroys all BIOs in chain, starting with b64 (i.e. the 1st one).
BUF_MEM_grow(mem_bio_mem_ptr, (*mem_bio_mem_ptr).length + 1); //Makes space for end null.
(*mem_bio_mem_ptr).data[(*mem_bio_mem_ptr).length] = '\0'; //Adds null-terminator to tail.
return (unsigned char*)(*mem_bio_mem_ptr).data; //Returns base-64 encoded data. (See: "buf_mem_st" struct).
}
void encrypt(unsigned char* in, const unsigned char* mykey){
int j=0,k=0;
int totalSize=0;
AES_KEY key;
unsigned char iv[8] = {0}; //changed
unsigned char out[1024]; //changed
AES_set_encrypt_key(mykey, 128, &key);
char total[256];
int size=0;
init_ctr(&state, iv);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
CRYPTO_ctr128_encrypt(in, out, strlen((char*)in), &key, state.ivec, state.ecount, &state.num,(block128_f)AES_encrypt);
#else
AES_ctr128_encrypt(in, out, strlen((char*)in), &key, state.ivec, state.ecount, &state.num);
#endif
totalSize += strlen((char*)in);
size = strlen((char*)in);
for (j = 0; j< size; j++) {
total[k++]=out[j];
}
unsigned char *base64_encoded = base64encode(total, totalSize);
printf("%s\n",base64_encoded);
}
void generate_aes_128_key(char* filePath, unsigned char* returnedKey){
int i;
int part;
FILE* fptr;
char key[16];
struct timespec times;
clock_gettime(CLOCK_REALTIME,&times);
srand(times.tv_nsec);
for (i = 0; i < 16; i++) {
part = (rand() % 3);
if(part == 0){
key[i] = (rand() % 10) + 48;
}
else if(part == 1){
key[i] = (rand() % 26) + 65;
}
else if(part == 2){
key[i] = (rand() % 26) + 97;
}
}
fptr = fopen(filePath, "w");
for(i = 0; i < 16; i++){
fputc(key[i], fptr);
}
strcpy((char*)returnedKey, key);
fclose(fptr);
}
unsigned char *base64decode (const void *b64_decode_this, int decode_this_many_bytes){
BIO *b64_bio, *mem_bio; //Declares two OpenSSL BIOs: a base64 filter and a memory BIO.
unsigned char *base64_decoded = calloc( (decode_this_many_bytes*3)/4+1, sizeof(char) ); //+1 = null.
b64_bio = BIO_new(BIO_f_base64()); //Initialize our base64 filter BIO.
mem_bio = BIO_new(BIO_s_mem()); //Initialize our memory source BIO.
BIO_write(mem_bio, b64_decode_this, decode_this_many_bytes); //Base64 data saved in source.
BIO_push(b64_bio, mem_bio); //Link the BIOs by creating a filter-source BIO chain.
BIO_set_flags(b64_bio, BIO_FLAGS_BASE64_NO_NL); //Don't require trailing newlines.
int decoded_byte_index = 0; //Index where the next base64_decoded byte should be written.
while ( 0 < BIO_read(b64_bio, base64_decoded+decoded_byte_index, 1) ){ //Read byte-by-byte.
decoded_byte_index++; //Increment the index until read of BIO decoded data is complete.
} //Once we're done reading decoded data, BIO_read returns -1 even though there's no error.
BIO_free_all(b64_bio); //Destroys all BIOs in chain, starting with b64 (i.e. the 1st one).
return base64_decoded; //Returns base-64 decoded data with trailing null terminator.
}
int decodedTextSize(char *input){
int i=0;
int result=0,padding=0;
int size=strlen(input);
for (i = 0; i < size; ++i) {
if(input[i]=='='){
padding++;
}
}
result=(strlen(input)/4*3)-padding;
return result;
}
void decrypt(char* in, const unsigned char* mykey){
unsigned char iv[8] = {0};
AES_KEY key;
unsigned char outdata[256];
AES_set_encrypt_key(mykey, 128, &key);
int newTotalSize=decodedTextSize(in);
int bytes_to_decode = strlen(in);
unsigned char *encryptedText = base64decode(in, bytes_to_decode);
char last[1024]="";
init_ctr(&state, iv);
memset(outdata,'\0', sizeof(outdata));
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
CRYPTO_ctr128_encrypt(encryptedText,outdata,newTotalSize,&key, state.ivec, state.ecount, &state.num,(block128_f)AES_encrypt));
#else
AES_ctr128_encrypt(encryptedText, outdata, newTotalSize, &key, state.ivec, state.ecount, &state.num);
#endif
strcat(last,(char*)outdata);
printf("%s\n",last);
}
static int get_int_value(const char* s, int default_value)
{
if (!s || !(s[0]))
@ -1305,6 +1454,12 @@ static void set_option(int c, char *value)
case DH_FILE_OPT:
STRCPY(turn_params.dh_file,value);
break;
case SECRET_KEY_OPT:
STRCPY(turn_params.secret_key_file,value);
break;
case ALLOW_ENCODING_OPT:
turn_params.allow_encoding = atoi(value);
break;
case PKEY_FILE_OPT:
STRCPY(turn_params.pkey_file,value);
break;
@ -1492,6 +1647,8 @@ static int adminmain(int argc, char **argv)
TURNADMIN_COMMAND_TYPE ct = TA_COMMAND_UNKNOWN;
int is_admin = 0;
FILE* fptr;
unsigned char generated_key[16]; //changed
u08bits user[STUN_MAX_USERNAME_SIZE+1]="\0";
u08bits realm[STUN_MAX_REALM_SIZE+1]="\0";
@ -1504,84 +1661,88 @@ static int adminmain(int argc, char **argv)
uo.u.m = admin_long_options;
int print_enc_password = 0;
int print_enc_aes_password = 0;
while (((c = getopt_long(argc, argv, ADMIN_OPTIONS, uo.u.o, NULL)) != -1)) {
switch (c){
case 'P':
if(pwd[0]) {
char result[257];
generate_new_enc_password((char*)pwd, result);
printf("%s\n",result);
exit(0);
}
print_enc_password = 1;
break;
case 'g':
ct = TA_SET_REALM_OPTION;
break;
case 'G':
ct = TA_LIST_REALM_OPTIONS;
break;
case ADMIN_USER_QUOTA_OPT:
po.user_quota = (vint)atoi(optarg);
break;
case ADMIN_TOTAL_QUOTA_OPT:
po.total_quota = (vint)atoi(optarg);
break;
case ADMIN_MAX_BPS_OPT:
po.max_bps = (vint)atoi(optarg);
break;
case 'O':
ct = TA_ADD_ORIGIN;
break;
case 'R':
ct = TA_DEL_ORIGIN;
break;
case 'I':
ct = TA_LIST_ORIGINS;
break;
case 'o':
STRCPY(origin,optarg);
break;
case 'k':
ct = TA_PRINT_KEY;
break;
case 'a':
ct = TA_UPDATE_USER;
break;
case 'd':
ct = TA_DELETE_USER;
break;
case 'A':
ct = TA_UPDATE_USER;
is_admin = 1;
break;
case 'D':
ct = TA_DELETE_USER;
is_admin = 1;
break;
case 'l':
ct = TA_LIST_USERS;
break;
case 'L':
ct = TA_LIST_USERS;
is_admin = 1;
break;
case 's':
ct = TA_SET_SECRET;
STRCPY(secret,optarg);
break;
case 'S':
ct = TA_SHOW_SECRET;
break;
case 'X':
ct = TA_DEL_SECRET;
if(optarg)
STRCPY(secret,optarg);
break;
case DEL_ALL_AUTH_SECRETS_OPT:
ct = TA_DEL_SECRET;
break;
case 'P':
if(pwd[0]) {
char result[257];
generate_new_enc_password((char*)pwd, result);
printf("%s\n",result);
exit(0);
}
print_enc_password = 1;
break;
case 'E':
print_enc_aes_password = 1;
break;
case 'g':
ct = TA_SET_REALM_OPTION;
break;
case 'G':
ct = TA_LIST_REALM_OPTIONS;
break;
case ADMIN_USER_QUOTA_OPT:
po.user_quota = (vint)atoi(optarg);
break;
case ADMIN_TOTAL_QUOTA_OPT:
po.total_quota = (vint)atoi(optarg);
break;
case ADMIN_MAX_BPS_OPT:
po.max_bps = (vint)atoi(optarg);
break;
case 'O':
ct = TA_ADD_ORIGIN;
break;
case 'R':
ct = TA_DEL_ORIGIN;
break;
case 'I':
ct = TA_LIST_ORIGINS;
break;
case 'o':
STRCPY(origin,optarg);
break;
case 'k':
ct = TA_PRINT_KEY;
break;
case 'a':
ct = TA_UPDATE_USER;
break;
case 'd':
ct = TA_DELETE_USER;
break;
case 'A':
ct = TA_UPDATE_USER;
is_admin = 1;
break;
case 'D':
ct = TA_DELETE_USER;
is_admin = 1;
break;
case 'l':
ct = TA_LIST_USERS;
break;
case 'L':
ct = TA_LIST_USERS;
is_admin = 1;
break;
case 's':
ct = TA_SET_SECRET;
STRCPY(secret,optarg);
break;
case 'S':
ct = TA_SHOW_SECRET;
break;
case 'X':
ct = TA_DEL_SECRET;
if(optarg)
STRCPY(secret,optarg);
break;
case DEL_ALL_AUTH_SECRETS_OPT:
ct = TA_DEL_SECRET;
break;
#if !defined(TURN_NO_SQLITE)
case 'b':
STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg);
@ -1612,45 +1773,67 @@ static int adminmain(int argc, char **argv)
turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_REDIS;
break;
#endif
case 'u':
STRCPY(user,optarg);
if(!is_secure_username((u08bits*)user)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong user name structure or symbols, choose another name: %s\n",user);
exit(-1);
}
if(SASLprep((u08bits*)user)<0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong user name: %s\n",user);
exit(-1);
}
break;
case 'r':
set_default_realm_name(optarg);
STRCPY(realm,optarg);
if(SASLprep((u08bits*)realm)<0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong realm: %s\n",realm);
exit(-1);
}
break;
case 'p':
STRCPY(pwd,optarg);
if(SASLprep((u08bits*)pwd)<0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong password: %s\n",pwd);
exit(-1);
}
if(print_enc_password) {
char result[257];
generate_new_enc_password((char*)pwd, result);
printf("%s\n",result);
exit(0);
}
break;
case 'h':
printf("\n%s\n", AdminUsage);
exit(0);
break;
default:
fprintf(stderr,"\n%s\n", AdminUsage);
exit(-1);
case 'u':
STRCPY(user,optarg);
if(!is_secure_username((u08bits*)user)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong user name structure or symbols, choose another name: %s\n",user);
exit(-1);
}
if(SASLprep((u08bits*)user)<0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong user name: %s\n",user);
exit(-1);
}
break;
case 'r':
set_default_realm_name(optarg);
STRCPY(realm,optarg);
if(SASLprep((u08bits*)realm)<0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong realm: %s\n",realm);
exit(-1);
}
break;
case 'p':
STRCPY(pwd,optarg);
if(SASLprep((u08bits*)pwd)<0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong password: %s\n",pwd);
exit(-1);
}
if(print_enc_password) {
char result[257];
generate_new_enc_password((char*)pwd, result);
printf("%s\n",result);
exit(0);
}
if(print_enc_aes_password){
encrypt(pwd, generated_key);
exit(0);
}
break;
case 'x':
generate_aes_128_key(optarg, generated_key);
exit(0);
break;
case 'f':
fptr = fopen((char*)optarg, "r");
if(fptr == NULL){
printf("No such file like %s\n", (char*)optarg);
}
else{
fseek (fptr, 0, SEEK_SET);
fread (generated_key, sizeof(char), 16, fptr);
fclose (fptr);
}
break;
case 'v':
decrypt((char*)optarg, generated_key);
exit(0);
case 'h':
printf("\n%s\n", AdminUsage);
exit(0);
break;
default:
fprintf(stderr,"\n%s\n", AdminUsage);
exit(-1);
}
}
@ -1950,6 +2133,10 @@ int main(int argc, char **argv)
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Domain name: %s\n",turn_params.domain);
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Default realm: %s\n",get_realm(NULL)->options.name);
if(turn_params.allow_encoding){
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "allow-encoding-with-aes activated.\n");
}
if(turn_params.oauth && turn_params.oauth_server_name[0]) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "oAuth server name: %s\n",turn_params.oauth_server_name);
}
@ -2652,6 +2839,21 @@ static void set_ctx(SSL_CTX** out, const char *protocol, const SSL_METHOD* metho
}
}
{//secret key
if(turn_params.secret_key_file[0]) {
FILE *f = fopen(turn_params.secret_key_file, "r");
if (!f) {
perror("Cannot open Secret-Key file");
} else {
fseek (f, 0, SEEK_SET);
fread (turn_params.secret_key, sizeof(char), 16, f);
fclose (f);
}
}
}
{
int op = 0;

View File

@ -77,6 +77,10 @@
#include "ns_ioalib_impl.h"
#include <openssl/aes.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -309,6 +313,11 @@ typedef struct _turn_params_ {
unsigned long cpus;
///////// Encryption /////////
char secret_key_file[1025];
unsigned char secret_key[1025];
int allow_encoding;
} turn_params_t;
extern turn_params_t turn_params;
@ -357,6 +366,24 @@ void set_bps_capacity(band_limit_t value);
band_limit_t get_max_bps(void);
void set_max_bps(band_limit_t value);
///////// AES ENCRYPTION AND DECRYPTION ////////
struct ctr_state {
unsigned char ivec[16];
unsigned int num;
unsigned char ecount[16];
};
void generate_aes_128_key(char* filePath, unsigned char* returnedKey);
unsigned char *base64encode (const void *b64_encode_this, int encode_this_many_bytes);
void encrypt(unsigned char* in, const unsigned char* mykey);
unsigned char *base64decode (const void *b64_decode_this, int decode_this_many_bytes);
void decrypt(char* in, const unsigned char* mykey);
int decodedTextSize(char *input);
char* decryptPassword(char* in, const unsigned char* mykey);
int init_ctr(struct ctr_state *state, const unsigned char iv[8]);
///////////////////////////////
#ifdef __cplusplus