I am trying to encrypt/decrypt file using source code directly. The issue is how to properly do it after reading the file.
int crypto_aead_encrypt(
unsigned char *c, unsigned long long *clen,
const unsigned char *m, unsigned long long mlen,
const unsigned char *ad, unsigned long long adlen,
const unsigned char *nsec,
const unsigned char *npub,
const unsigned char *k
)
Working code: (plaintext is char *)
for (start = 0; start < fileLength; start += 32)
{
int end = (start + 32);
end = end > fileLength ? fileLength : end;
strncpy(msg, plaintext + start, end - start);
// encrypt
crypto_aead_encrypt(ct, &clen, msg, mlen, ad, adlen, NULL, nonce, key);
// decryption
crypto_aead_decrypt(msg2, &mlen2, NULL, ct, clen, ad, adlen, nonce, key);
}
This is the function, and the max limit of the message m
is 32 bits, which would make encrypting/decrypt very long for large files (ex. 1GB). Is there a way to perform the encrypting as fast as if it were from the library. Neglecting the code above, ex. how does OpenSSL do it when -in is provided?
The way I have it is to read the file, save it to an char *
and then take 32 bits and enc each one. So I am wondering if there is a proper more correct way to do it.
Edit: reference implementation like ascon or photon-beetle
-
\$\begingroup\$ Why do you first read the entire file, and more importantly, why do you only encrypt 32 bits / 4 bytes at a time? That don't make no sense at all. \$\endgroup\$Maarten Bodewes– Maarten Bodewes2020年04月15日 22:53:35 +00:00Commented Apr 15, 2020 at 22:53
-
\$\begingroup\$ @MaartenBodewes 32 bits cause that's the max the algorithm accepts (max msg size for encrypting/decrypting blocks). And I'm not sure how else to do it without reading the entire file first, I read it and store it then process the stored \$\endgroup\$dylan solaman– dylan solaman2020年04月16日 01:48:47 +00:00Commented Apr 16, 2020 at 1:48
2 Answers 2
I think you're confused here. The GCM algorithm has a 96 bit nonce, and fills the rest of the 128 bit block size with a 32 bit counter. So you have 2^32 full blocks at your disposal, or about 64 GiB. That's - uh - slightly more than 32 bits (well, OK, the counter starts at 2, so you'd have 48 bytes less than that, better keep it at 32 GiB or 48 GiB).
-
\$\begingroup\$ Thanks! how do you suggest to do it then? I mean encrytping the plaintext directlt? I tried that but I kept getting error due to exceeding the limit. For example I am using photon-beetle and particularly this as a tempalte to do the enc/dec where the max is 32 \$\endgroup\$dylan solaman– dylan solaman2020年04月16日 13:17:38 +00:00Commented Apr 16, 2020 at 13:17
-
\$\begingroup\$ I'm not entirely sure what goes wrong; I'd have to debug the code for that. I can see in the photon code that
size_t Dlen_inblocks = (Dlen_inbytes + RATE_INBYTES - 1) / RATE_INBYTES;
which splits up the input as 4 byte blocks. That's not something you do if the total input can be 32 bits (which makes no sense whatsoever for an AEAD cipher). \$\endgroup\$Maarten Bodewes– Maarten Bodewes2020年04月16日 13:51:52 +00:00Commented Apr 16, 2020 at 13:51 -
\$\begingroup\$ Ah ok, and the other thing that the crypto_aead_encrypt takes in m as a unsigned char so that means after it passes there it's converted to uint8_t (
const uint8_t *Data_in
). In any case, I even tried again sending fill plaintext and the fill length but it's a buffer overflow due to the full plaintext I'm pretty sure Edit: I changed the code and was able to get it to work! however, not for large files (ex. 16mb), a stack overflow. I'm currently really stuck on where or how I could fix it though, tried different ways to debug it but no success so far \$\endgroup\$dylan solaman– dylan solaman2020年04月16日 20:15:52 +00:00Commented Apr 16, 2020 at 20:15 -
\$\begingroup\$ I guess the error shows the place where these kind of questions are more on topic :) Glad you got the initial issue solved. What I wrote was for GCM (which I wrongly assumed was the block cipher), if there is a block of 4 bytes then of course the algorithm may have different limits. You can e.g. split up the file in chunks and encrypt them separately. You'd have to create a MAC over the authentication tags though, otherwise the chunks may be reordere.d by an adversary. \$\endgroup\$Maarten Bodewes– Maarten Bodewes2020年04月17日 00:13:32 +00:00Commented Apr 17, 2020 at 0:13
So I am wondering if there is a proper more correct way to do it.
binary data
An encryption of a file should not assume it is text lacking a '0円'
. As a binary file, data may include null characters which will incorrectly copy using strncpy()
.
// strncpy(msg, plaintext + start, end - start);
memcpy(msg, plaintext + start, end - start);
LARGE files
"for large files (ex. 1GB)" --> 1GB is not so large. Rather than limit file size to the int
range, use size_t
. That is typicality at least 2x the positive range or perhaps billions x. Code is limited in design to size_t
given the usage of a single array. Might as well use as much range as possible.
size_t start;
...
// int end = (start + 32);
size_t end = (start + 32);
Better code would use unsigned long long
like the int crypto_aead_decrypt(unsigned char* m, unsigned long long* mlen, ...)
signature.
-
\$\begingroup\$ Good point about the
int
. It made no sense for 32 bit input, but for larger input e.g. a 2 GiB - 1 max size may be prohibitive. Thestrncpy
is interesting as well; I presumed readable text when I saw that, but that might be a somewhat presumptuous :) \$\endgroup\$Maarten Bodewes– Maarten Bodewes2020年04月18日 14:14:33 +00:00Commented Apr 18, 2020 at 14:14
Explore related questions
See similar questions with these tags.