mirror of
https://github.com/moparisthebest/ImageDownloader
synced 2024-11-26 19:22:16 -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
|
# 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.
|
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.
|
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 <unistd.h>
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
#define TAG_IV_LENGTH 16
|
#define TAG_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
|
||||||
|
|
||||||
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 *dst = *dst_p;
|
||||||
unsigned char *end = dst + (strlen(src)/2);
|
unsigned char *end = dst + (strlen(src)/2);
|
||||||
unsigned int u;
|
unsigned int u;
|
||||||
@ -18,6 +19,7 @@ void hex2string(char *src, unsigned char **dst_p)
|
|||||||
*dst++ = u;
|
*dst++ = u;
|
||||||
src += 2;
|
src += 2;
|
||||||
}
|
}
|
||||||
|
return byte_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
@ -35,7 +37,16 @@ int main(int argc, char **argv)
|
|||||||
if (argc > 2 && strcmp("enc", argv[2]) == 0)
|
if (argc > 2 && strcmp("enc", argv[2]) == 0)
|
||||||
decrypt = 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);
|
gcm_ct = malloc(total_size);
|
||||||
|
|
||||||
@ -53,9 +64,9 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(decrypt)
|
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();
|
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);
|
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, TAG_IV_LENGTH, NULL);
|
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_length, NULL);
|
||||||
|
|
||||||
if(decrypt) {
|
if(decrypt) {
|
||||||
/* Specify key and IV */
|
/* 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. */
|
/* 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 */
|
/* Decrypt plaintext */
|
||||||
EVP_DecryptUpdate(ctx, gcm_pt, &outlen, gcm_ct, actual_size);
|
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);
|
rv = EVP_DecryptFinal_ex(ctx, gcm_pt, &final_outlen);
|
||||||
} else {
|
} else {
|
||||||
/* Specify key and IV */
|
/* 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 */
|
/* Encrypt plaintext */
|
||||||
EVP_EncryptUpdate(ctx, gcm_pt, &outlen, gcm_ct, actual_size);
|
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);
|
rv = EVP_EncryptFinal_ex(ctx, gcm_pt, &final_outlen);
|
||||||
|
|
||||||
/* Get expected tag value. */
|
/* 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);
|
EVP_CIPHER_CTX_free(ctx);
|
||||||
@ -100,7 +111,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
if (rv > 0) {
|
if (rv > 0) {
|
||||||
// success!
|
// 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);
|
free(gcm_pt);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user