mirror of
https://github.com/moparisthebest/ImageDownloader
synced 2024-11-23 01:32:18 -05:00
Support new 12-byte IV format and legacy 16-byte IV format
This commit is contained in:
parent
7c8281d7e5
commit
7ce7d25ada
@ -1,7 +1,9 @@
|
||||
# ImageDownloader
|
||||
When [Conversations](https://conversations.im) uploads an encrypted image with [XEP-0363: HTTP Upload](http://xmpp.org/extensions/xep-0363.html) it appends the encryption key as an anchor to the URL.
|
||||
|
||||
The anchor is made of 96 characters which represent 48 bytes in HEX. The first 16 bytes are the IV the last 32 bytes are the key.
|
||||
There are now [2 formats for anchors](https://github.com/siacs/Conversations/issues/2578).
|
||||
*LEGACY FORMAT*: The anchor is made of 96 characters which represent 48 bytes in HEX. The first 16 bytes are the IV the last 32 bytes are the key.
|
||||
*CURRENT FORMAT*: The anchor is made of 88 characters which represent 44 bytes in HEX. The first 12 bytes are the IV the last 32 bytes are the key.
|
||||
|
||||
The encryption mode is ```aes-256-gcm```. The authentication tag of 16 bytes is appended to the file.
|
||||
|
||||
|
35
aesgcm.c
35
aesgcm.c
@ -3,13 +3,14 @@
|
||||
#include <unistd.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#define TAG_IV_LENGTH 16
|
||||
#define TAG_LENGTH 16
|
||||
#define BYTES_PER_READ 32 * 1024 // 32kb
|
||||
#define INITIAL_BUFFER_SIZE 256 * 1024 // 256kb, must be at least 2*BYTES_PER_READ
|
||||
|
||||
void hex2string(char *src, unsigned char **dst_p)
|
||||
unsigned int hex2string(char *src, unsigned char **dst_p)
|
||||
{
|
||||
*dst_p = malloc(strlen(src)/2);
|
||||
unsigned int byte_length = strlen(src)/2;
|
||||
*dst_p = malloc(byte_length);
|
||||
unsigned char *dst = *dst_p;
|
||||
unsigned char *end = dst + (strlen(src)/2);
|
||||
unsigned int u;
|
||||
@ -18,6 +19,7 @@ void hex2string(char *src, unsigned char **dst_p)
|
||||
*dst++ = u;
|
||||
src += 2;
|
||||
}
|
||||
return byte_length;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
@ -35,7 +37,16 @@ int main(int argc, char **argv)
|
||||
if (argc > 2 && strcmp("enc", argv[2]) == 0)
|
||||
decrypt = 0;
|
||||
|
||||
hex2string(argv[1], &gcm_ivkey);
|
||||
unsigned int byte_length = hex2string(argv[1], &gcm_ivkey);
|
||||
unsigned int iv_length;
|
||||
if(byte_length == 48) {
|
||||
iv_length = 16;
|
||||
} else if(byte_length == 44) {
|
||||
iv_length = 12;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid key length %d only 44 or 48 bytes supported\n", byte_length);
|
||||
return 1;
|
||||
}
|
||||
|
||||
gcm_ct = malloc(total_size);
|
||||
|
||||
@ -53,9 +64,9 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if(decrypt)
|
||||
actual_size -= TAG_IV_LENGTH;
|
||||
actual_size -= TAG_LENGTH;
|
||||
|
||||
gcm_pt = malloc(decrypt ? actual_size : (actual_size + TAG_IV_LENGTH));
|
||||
gcm_pt = malloc(decrypt ? actual_size : (actual_size + TAG_LENGTH));
|
||||
|
||||
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
|
||||
|
||||
@ -66,14 +77,14 @@ int main(int argc, char **argv)
|
||||
EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
|
||||
|
||||
/* Set IV length, omit for 96 bits */
|
||||
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, TAG_IV_LENGTH, NULL);
|
||||
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_length, NULL);
|
||||
|
||||
if(decrypt) {
|
||||
/* Specify key and IV */
|
||||
EVP_DecryptInit_ex(ctx, NULL, NULL, gcm_ivkey + TAG_IV_LENGTH, gcm_ivkey);
|
||||
EVP_DecryptInit_ex(ctx, NULL, NULL, gcm_ivkey + iv_length, gcm_ivkey);
|
||||
|
||||
/* Set expected tag value. */
|
||||
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, TAG_IV_LENGTH, gcm_ct + actual_size);
|
||||
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, TAG_LENGTH, gcm_ct + actual_size);
|
||||
|
||||
/* Decrypt plaintext */
|
||||
EVP_DecryptUpdate(ctx, gcm_pt, &outlen, gcm_ct, actual_size);
|
||||
@ -82,7 +93,7 @@ int main(int argc, char **argv)
|
||||
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);
|
||||
EVP_EncryptInit_ex(ctx, NULL, NULL, gcm_ivkey + iv_length, gcm_ivkey);
|
||||
|
||||
/* Encrypt plaintext */
|
||||
EVP_EncryptUpdate(ctx, gcm_pt, &outlen, gcm_ct, actual_size);
|
||||
@ -91,7 +102,7 @@ int main(int argc, char **argv)
|
||||
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_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, TAG_LENGTH, gcm_pt + actual_size);
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
@ -100,7 +111,7 @@ int main(int argc, char **argv)
|
||||
|
||||
if (rv > 0) {
|
||||
// success!
|
||||
fwrite(gcm_pt, 1, decrypt ? outlen : (outlen + TAG_IV_LENGTH), stdout);
|
||||
fwrite(gcm_pt, 1, decrypt ? outlen : (outlen + TAG_LENGTH), stdout);
|
||||
free(gcm_pt);
|
||||
return 0;
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user