Add encryption ability to aesgcm.c

This commit is contained in:
Travis Burtrum 2017-01-20 01:21:17 -05:00
parent 168e77099c
commit 5f0ee16b28
2 changed files with 43 additions and 18 deletions

View File

@ -5,8 +5,10 @@ The anchor is made of 96 characters which represent 48 bytes in HEX. The first 1
The encryption mode is ```aes-256-gcm```. The authentication tag of 16 bytes is appended to the file. The encryption mode is ```aes-256-gcm```. The authentication tag of 16 bytes is appended to the file.
This C project provides sample code on how to decrypt a file. Output is to stdout. Redirect to file or pipe to image viewer. This C project provides sample code on how to decrypt and encrypt a file. Output is to stdout. Redirect to file or pipe to image viewer.
Compile with ```gcc aesgcm.c -lcrypto -o aesgcm```, openbrowser.sh also tries to compile it if the executable not already exist. Compile with ```gcc aesgcm.c -lcrypto -o aesgcm```, openbrowser.sh also tries to compile it if the executable not already exist.
Set openbrowser.sh as your browser in gajim or another XMPP client to automatically decrypt http uploads encrypted with OMEMO or PGP with Conversations. Set openbrowser.sh as your browser in gajim or another XMPP client to automatically decrypt http uploads encrypted with OMEMO or PGP with Conversations.
You can also encrypt data with aesgcm by sending in `enc` as the second parameter.

View File

@ -3,6 +3,7 @@
#include <unistd.h> #include <unistd.h>
#include <openssl/evp.h> #include <openssl/evp.h>
#define TAG_IV_LENGTH 16
#define BYTES_PER_READ 32 * 1024 // 32kb #define BYTES_PER_READ 32 * 1024 // 32kb
#define INITIAL_BUFFER_SIZE 256 * 1024 // 256kb, must be at least 2*BYTES_PER_READ #define INITIAL_BUFFER_SIZE 256 * 1024 // 256kb, must be at least 2*BYTES_PER_READ
@ -22,14 +23,18 @@ void hex2string(char *src, unsigned char **dst_p)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
unsigned char *gcm_ivkey, *gcm_ct, *gcm_pt; unsigned char *gcm_ivkey, *gcm_ct, *gcm_pt;
int outlen, rv, final_outlen; int outlen, rv = 0, final_outlen, decrypt = 1;
size_t read, actual_size = 0, total_size = INITIAL_BUFFER_SIZE; size_t read, actual_size = 0, total_size = INITIAL_BUFFER_SIZE;
if (argc < 2) { if (argc < 2) {
printf("Usage: %s <key>\n", argv[0]); fprintf(stderr, "Usage: %s <key> [enc]\n", argv[0]);
return 1; return 1;
} }
// this means we want to encrypt, not decrypt
if (argc > 2 && strcmp("enc", argv[2]) == 0)
decrypt = 0;
hex2string(argv[1], &gcm_ivkey); hex2string(argv[1], &gcm_ivkey);
gcm_ct = malloc(total_size); gcm_ct = malloc(total_size);
@ -42,34 +47,52 @@ int main(int argc, char **argv)
} }
} }
if (actual_size < 32) { if (actual_size < (decrypt ? 17 : 1)) {
fprintf(stderr, "File too small for decryption\n"); fprintf(stderr, "File too small for %scryption\n", decrypt ? "de" : "en");
return 1; return 1;
} }
actual_size -= 16; if(decrypt)
actual_size -= TAG_IV_LENGTH;
gcm_pt = malloc(actual_size); gcm_pt = malloc(decrypt ? actual_size : (actual_size + TAG_IV_LENGTH));
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
/* Select cipher */ /* Select cipher */
EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); if(decrypt)
EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
else
EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
/* Set IV length, omit for 96 bits */ /* Set IV length, omit for 96 bits */
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL); EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, TAG_IV_LENGTH, NULL);
/* Specify key and IV */ if(decrypt) {
EVP_DecryptInit_ex(ctx, NULL, NULL, gcm_ivkey+16, gcm_ivkey); /* Specify key and IV */
EVP_DecryptInit_ex(ctx, NULL, NULL, gcm_ivkey + TAG_IV_LENGTH, gcm_ivkey);
/* Decrypt plaintext */ /* Set expected tag value. */
EVP_DecryptUpdate(ctx, gcm_pt, &outlen, gcm_ct, actual_size); EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, TAG_IV_LENGTH, gcm_ct + actual_size);
/* Set expected tag value. */ /* Decrypt plaintext */
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, gcm_ct + actual_size); EVP_DecryptUpdate(ctx, gcm_pt, &outlen, gcm_ct, actual_size);
/* Finalise: note get no output for GCM */ /* Finalise: note get no output for GCM */
rv = EVP_DecryptFinal_ex(ctx, gcm_pt, &final_outlen); rv = EVP_DecryptFinal_ex(ctx, gcm_pt, &final_outlen);
} else {
/* Specify key and IV */
EVP_EncryptInit_ex(ctx, NULL, NULL, gcm_ivkey + TAG_IV_LENGTH, gcm_ivkey);
/* Encrypt plaintext */
EVP_EncryptUpdate(ctx, gcm_pt, &outlen, gcm_ct, actual_size);
/* Finalise: note get no output for GCM */
rv = EVP_EncryptFinal_ex(ctx, gcm_pt, &final_outlen);
/* Get expected tag value. */
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, TAG_IV_LENGTH, gcm_pt + actual_size);
}
EVP_CIPHER_CTX_free(ctx); EVP_CIPHER_CTX_free(ctx);
free(gcm_ivkey); free(gcm_ivkey);
@ -77,7 +100,7 @@ int main(int argc, char **argv)
if (rv > 0) { if (rv > 0) {
// success! // success!
fwrite(gcm_pt, 1, outlen, stdout); fwrite(gcm_pt, 1, decrypt ? outlen : (outlen + TAG_IV_LENGTH), stdout);
free(gcm_pt); free(gcm_pt);
return 0; return 0;
} else { } else {