/* ** ** Krishna Puttaswamy: created on 29th May 2006 ** description: program to better understand symmetric key encryption */ #include #include #include #include #include #include #include #include #define RAND_SEED_LENGTH 16 #define SYMMETRIC_KEY_LENGTH 16 #define IV_LENGTH 16 #define SYMMETRIC_CYPHER_TYPE "bf-ecb" void get_data_from_random_file (unsigned char *data, int length) { int i, j, fd; if ((fd = open ("/dev/urandom", O_RDONLY)) == -1) perror ("Not able to read the /dev/urandom file"); if ((read (fd, data, length)) == -1) perror ("Error reading data from the random file"); close (fd); } void print_in_hex (unsigned char *data, int length) { int i = 0; for (i = 0; i < length; i++) printf ("%2x", data[i]); printf ("\n"); } unsigned char *symmetric_encrypt (unsigned char *data, int inputlen, unsigned char *key, int keylen, unsigned char *iv, int ivlen, int *outlen) { EVP_CIPHER_CTX ctx; const EVP_CIPHER *cipher_type; EVP_CIPHER_CTX_init (&ctx); OpenSSL_add_all_ciphers (); cipher_type = EVP_get_cipherbyname (SYMMETRIC_CYPHER_TYPE); if (cipher_type == NULL) { fprintf (stderr, "Unknown cipher %s\n", SYMMETRIC_CYPHER_TYPE); return NULL; } EVP_EncryptInit_ex (&ctx, cipher_type, NULL, key, iv); int maxbuffersize = inputlen + EVP_CIPHER_CTX_block_size (&ctx); unsigned char *encrypt = (unsigned char *) malloc (maxbuffersize); int templen = 0; if (EVP_EncryptUpdate (&ctx, encrypt, outlen, data, inputlen) != 1) { printf ("encrypt: error in encrypt update\n"); return 0; } if (EVP_EncryptFinal_ex (&ctx, encrypt + *outlen, &templen) != 1) { printf ("encrypt: error in encrypt final\n"); return 0; } *outlen += templen; printf ("The encrypted length is %d \n", *outlen); EVP_CIPHER_CTX_cleanup (&ctx); return encrypt; } unsigned char *symmetric_decrypt (unsigned char *data, int inputlen, unsigned char *key, int keylen, unsigned char *iv, int ivlen, int *outlen) { EVP_CIPHER_CTX ctx; const EVP_CIPHER *cipher_type; EVP_CIPHER_CTX_init (&ctx); OpenSSL_add_all_ciphers (); cipher_type = EVP_get_cipherbyname (SYMMETRIC_CYPHER_TYPE); if (cipher_type == NULL) { fprintf (stderr, "Unknown cipher %s\n", SYMMETRIC_CYPHER_TYPE); return NULL; } EVP_DecryptInit_ex (&ctx, cipher_type, NULL, key, iv); int maxbuffersize = inputlen + EVP_CIPHER_CTX_block_size (&ctx); unsigned char *encrypt = (unsigned char *) malloc (maxbuffersize); int templen = 0; if (EVP_DecryptUpdate (&ctx, encrypt, outlen, data, inputlen) != 1) { printf ("encrypt: error in encrypt update\n"); return 0; } if (EVP_DecryptFinal_ex (&ctx, encrypt + *outlen, &templen) != 1) { printf ("encrypt: error in encrypt final\n"); return 0; } *outlen += templen; printf ("The decrypted length is %d \n", *outlen); EVP_CIPHER_CTX_cleanup (&ctx); return encrypt; } void generate_symmetric_key (unsigned char *key, int keylen, unsigned char *iv, int ivlen) { RAND_bytes (key, keylen); RAND_pseudo_bytes (iv, ivlen); } int main () { unsigned char data[100], key[SYMMETRIC_KEY_LENGTH], iv[IV_LENGTH]; get_data_from_random_file (data, RAND_SEED_LENGTH); RAND_seed (data, RAND_SEED_LENGTH); if (RAND_status () == 0) printf ("Didn't have enuf randomness \n"); generate_symmetric_key (key, SYMMETRIC_KEY_LENGTH, iv, IV_LENGTH); printf ("The symmetric key is \n"); print_in_hex (key, SYMMETRIC_KEY_LENGTH); printf ("The IV is \n"); print_in_hex (iv, IV_LENGTH); printf ("Enter text to encrypt \n"); scanf ("%s", data); int encryptedlen = 0, decryptedlen = 0; unsigned char *encryptedText = symmetric_encrypt (data, strlen ((const char *) data) + 1, key, SYMMETRIC_KEY_LENGTH, iv, IV_LENGTH, &encryptedlen); unsigned char *decryptedText = symmetric_decrypt (encryptedText, encryptedlen, key, SYMMETRIC_KEY_LENGTH, iv, IV_LENGTH, &decryptedlen); printf ("Original data is of len %d\n%s\n", strlen ((char *) data), data); printf ("Decrypted data is of len %d\n%s\n", strlen ((char *) decryptedText), decryptedText); free (decryptedText); free (encryptedText); }