OpenSSL AES XTS usage
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ssl-encrypt: ssl-encrypt.c | |
gcc -O2 ssl-encrypt.c -lcrypto -o ssl-encrypt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <openssl/conf.h> | |
#include <openssl/evp.h> | |
#include <openssl/err.h> | |
#include <string.h> | |
void handleErrors(void) | |
{ | |
ERR_print_errors_fp(stderr); | |
abort(); | |
} | |
int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, | |
unsigned char *iv, unsigned char *ciphertext) | |
{ | |
EVP_CIPHER_CTX *ctx; | |
int len; | |
int i; | |
int ciphertext_len; | |
/* Create and initialise the context */ | |
if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); | |
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_xts(), NULL, key, NULL)) | |
handleErrors(); | |
for (i = 0; i < 1000000; i++) { | |
/* Initialise the encryption operation. IMPORTANT - ensure you use a key | |
* and IV size appropriate for your cipher | |
* In this example we are using 256 bit AES (i.e. a 256 bit key). The | |
* IV size for *most* modes is the same as the block size. For AES this | |
* is 128 bits */ | |
if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv)) | |
handleErrors(); | |
/* Provide the message to be encrypted, and obtain the encrypted output. | |
* EVP_EncryptUpdate can be called multiple times if necessary | |
*/ | |
if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) | |
handleErrors(); | |
ciphertext_len = len; | |
/* Finalise the encryption. Further ciphertext bytes may be written at | |
* this stage. | |
*/ | |
if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors(); | |
ciphertext_len += len; | |
} | |
/* Clean up */ | |
EVP_CIPHER_CTX_free(ctx); | |
return ciphertext_len; | |
} | |
int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, | |
unsigned char *iv, unsigned char *plaintext) | |
{ | |
EVP_CIPHER_CTX *ctx; | |
int len; | |
int plaintext_len; | |
/* Create and initialise the context */ | |
if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); | |
/* Initialise the decryption operation. IMPORTANT - ensure you use a key | |
* and IV size appropriate for your cipher | |
* In this example we are using 256 bit AES (i.e. a 256 bit key). The | |
* IV size for *most* modes is the same as the block size. For AES this | |
* is 128 bits */ | |
if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_xts(), NULL, key, iv)) | |
handleErrors(); | |
/* Provide the message to be decrypted, and obtain the plaintext output. | |
* EVP_DecryptUpdate can be called multiple times if necessary | |
*/ | |
if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) | |
handleErrors(); | |
plaintext_len = len; | |
/* Finalise the decryption. Further plaintext bytes may be written at | |
* this stage. | |
*/ | |
if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) handleErrors(); | |
plaintext_len += len; | |
/* Clean up */ | |
EVP_CIPHER_CTX_free(ctx); | |
return plaintext_len; | |
} | |
int main (void) | |
{ | |
/* Set up the key and iv. Do I need to say to not hard code these in a | |
* real application? :-) | |
*/ | |
/* A 256 bit key */ | |
unsigned char *key = (unsigned char *)"0123456789012345678901234567890123456789012345678901234567890123"; | |
/* A 128 bit IV */ | |
unsigned char *iv = (unsigned char *)"0123456789012345"; | |
/* Message to be encrypted */ | |
unsigned char plaintext[8192]; | |
/* Buffer for ciphertext. Ensure the buffer is long enough for the | |
* ciphertext which may be longer than the plaintext, dependant on the | |
* algorithm and mode | |
*/ | |
unsigned char ciphertext[8192]; | |
/* Buffer for the decrypted text */ | |
unsigned char decryptedtext[8193]; | |
int decryptedtext_len, ciphertext_len; | |
memset(plaintext, 'x', 8192); | |
/* Initialise the library */ | |
ERR_load_crypto_strings(); | |
OpenSSL_add_all_algorithms(); | |
OPENSSL_config(NULL); | |
/* Encrypt the plaintext */ | |
ciphertext_len = encrypt (plaintext, strlen ((char *)plaintext), key, iv, | |
ciphertext); | |
/* Do something useful with the ciphertext here */ | |
printf("Ciphertext is:\n"); | |
BIO_dump_fp (stdout, (const char *)ciphertext, ciphertext_len); | |
/* Decrypt the ciphertext */ | |
decryptedtext_len = decrypt(ciphertext, ciphertext_len, key, iv, | |
decryptedtext); | |
/* Add a NULL terminator. We are expecting printable text */ | |
decryptedtext[decryptedtext_len] = '\0'; | |
/* Show the decrypted text */ | |
printf("Decrypted text is:\n"); | |
printf("%s\n", decryptedtext); | |
/* Clean up */ | |
EVP_cleanup(); | |
ERR_free_strings(); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment