Related
I'm sending a file from the client to the server.
Client sends filename
Server receives filename
Client sends file size
Server receives file size
Client sends file contents
Server receives file contents
When I print out the file size that I sent, it is the exact number of bytes as the file I wish to send so that's fine. The issue is that the server (receives) doesn't seem to exit the while loop when writing to the new file. I know this because the final print statement printf("The server has received the requested document\n"); is never reached and it just hangs. What could be causing this?
Client snippet (sends):
else if(strcmp(shortCommand, "put") == 0){
char *tmp = buf + 4;
char filename[MAX_BLOCK_SIZE];
size_t size, bytes_read, bytes_written;
int x;
strcpy(filename, "filename ");
strcat(filename, tmp);
FILE *fp;
printf("File name: %s\n", tmp);
fp = fopen(tmp, "rb");
if(fp == NULL){
printf("ERROR: Requested file does not exist.\n");
}
else{
printf("Client sending filename...\n");
if ((x = write(sd, buf, sizeof(buf))) < 0){ //sending the file name to the client first
printf("Error sending client's filename.\n");
}
printf("Client sending file...\n");
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
printf("Sending file size\n");
if((write(sd, &size, sizeof(size))) < 0){ //sending filesize
printf("error sending file size\n");
}
printf("Sending file\n");
while((bytes_read = fread(buf, 1, sizeof(buf), fp)) > 0){ //sending file contents
if ((bytes_written = write(sd, buf, bytes_read)) < 0){
printf("Error sending client file.\n");
}
}
printf("bytes written: %ld\n", bytes_written);
fclose(fp);
}
}
Server snippet (receives):
if(strcmp(shortCommand, "put") == 0){
char *tmp = buf + 4;
char filename2[MAX_BLOCK_SIZE];
size_t filesize;
size_t total_bytes_read = 0;
ssize_t bytes_read = 0;
size_t error;
FILE *fp;
strcpy(filename2, tmp);
printf("Server receiving file name...\n"); //filename is received on the first read before this IF
fp = fopen(filename2, "wb");
if(fp == NULL){
printf("File could not be opened.\n");
exit(1);
}
printf("Server receiving file size...\n");
if((error = read(sd, &filesize, sizeof(filesize))) < 0){ //receiving file size
perror("Error reading filesize\n");
exit(1);
}
printf("Filesize is: %ld \n", filesize);
while(total_bytes_read < filesize){
while((bytes_read = read(sd, buf, sizeof(buf))) > 0){ //receving file contents and writing to file
fwrite(buf, 1, bytes_read, fp);
total_bytes_read += bytes_read;
if(ferror(fp)){
perror("error");
fclose(fp);
}
}
}
printf("The server has received the requested document.\n");
fflush(stdout);
fclose(fp);
}
After I exit the program by force, I can actually see that the file has been copied. Just doesn't exit that while loop to let me go back to the client.
Time for some basic debugging. I'd suggest changing your read loop to something like this:
while (total_bytes_read < filesize) {
printf("DEBUG A: total=%zu, size=%zu\n", total_bytes_read, filesize);
while ((bytes_read = read(sd, buf, sizeof(buf))) > 0) {
printf("DEBUG B: read=%zd\n", bytes_read);
fwrite(buf, 1, bytes_read, fp);
total_bytes_read += bytes_read;
printf("DEBUG C: total=%zu\n", total_bytes_read);
if (ferror(fp))
printf("DEBUG D\n");
perror("error");
fclose(fp);
}
printf("DEBUG E\n");
}
printf("DEBUG F\n");
}
printf("DEBUG G\n");
Then run it, piping the output through less or some other pager, it should then hopefully become clearer what's actually happening.
Feel free to post the output of this modified code (in a comment, or in the actual question), we'll no doubt be able to help with the analysis.
Hello I was studying aes 128 encryption with this link https://www.gurutechnologies.net/blog/aes-ctr-encryption-in-c/.
But to run the example main.c
Compiled as follows
gcc main.c -lm -lcrypto -lssl -o mai.c
Then I get the following error:
main.c: In function ‘fencrypt’:
main.c:83:3: warning: implicit declaration of function ‘AES_ctr128_encrypt’; did you mean ‘AES_cfb128_encrypt’? [-Wimplicit-function-declaration]
AES_ctr128_encrypt(indata, outdata, bytes_read, &key, state.ivec, state.ecount, &state.num);
^~~~~~~~~~~~~~~~~~
AES_cfb128_encrypt
/tmp/cc1Gq6eV.o: In function `fencrypt':
main.c:(.text+0x253): undefined reference to `AES_ctr128_encrypt'
/tmp/cc1Gq6eV.o: In function `fdecrypt':
main.c:(.text+0x449): undefined reference to `AES_ctr128_encrypt'
collect2: error: ld returned 1 exit status
To fix this I go into the directory where openssl is located, and in the aes.h header file
I tried to find the AES_ctr128_encrypt function, but it did not
So I updated the openssl and confirmed that there is a AES_ctr128_encrypt function in aes.h and tried to recompile it, but nothing changed. I will leave a question because I could not find a solution anymore.
This is the code for AES_ctr128_encrypt
void fencrypt(char* read, char* write, const unsigned char* enc_key)
{
if(!RAND_bytes(iv, AES_BLOCK_SIZE))
{
fprintf(stderr, "Could not create random bytes.");
exit(1);
}
readFile = fopen(read,"rb"); // The b is required in windows.
writeFile = fopen(write,"wb");
if(readFile==NULL)
{
fprintf(stderr, "Read file is null.");
exit(1);
}
if(writeFile==NULL)
{
fprintf(stderr, "Write file is null.");
exit(1);
}
fwrite(iv, 1, 8, writeFile); // IV bytes 1 - 8
fwrite("\0\0\0\0\0\0\0\0", 1, 8, writeFile); // Fill the last 4 with null bytes 9 - 16
//Initializing the encryption KEY
if (AES_set_encrypt_key(enc_key, 128, &key) < 0)
{
fprintf(stderr, "Could not set encryption key.");
exit(1);
}
init_ctr(&state, iv); //Counter call
//Encrypting Blocks of 16 bytes and writing the output.txt with ciphertext
while(1)
{
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, readFile);
AES_ctr128_encrypt(indata, outdata, bytes_read, &key, state.ivec, state.ecount, &state.num);
bytes_written = fwrite(outdata, 1, bytes_read, writeFile);
if (bytes_read < AES_BLOCK_SIZE)
{
break;
}
}
fclose(writeFile);
fclose(readFile);
}
void fdecrypt(char* read, char* write, const unsigned char* enc_key)
{
readFile=fopen(read,"rb"); // The b is required in windows.
writeFile=fopen(write,"wb");
if(readFile==NULL)
{
fprintf(stderr,"Read file is null.");
exit(1);
}
if(writeFile==NULL)
{
fprintf(stderr, "Write file is null.");
exit(1);
}
fread(iv, 1, AES_BLOCK_SIZE, readFile);
//Initializing the encryption KEY
if (AES_set_encrypt_key(enc_key, 128, &key) < 0)
{
fprintf(stderr, "Could not set decryption key.");
exit(1);
}
init_ctr(&state, iv);//Counter call
//Encrypting Blocks of 16 bytes and writing the output.txt with ciphertext
while(1)
{
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, readFile);
//printf("%i\n", state.num);
AES_ctr128_encrypt(indata, outdata, bytes_read, &key, state.ivec, state.ecount, &state.num);
bytes_written = fwrite(outdata, 1, bytes_read, writeFile);
if (bytes_read < AES_BLOCK_SIZE)
{
break;
}
}
fclose(writeFile);
fclose(readFile);
}
Thank you in advance.
Assuming you are using openssl 1.1.0, see What is exact alternate API instead of AES_ctr128_encrypt from openssl 1.1.0?
You can use CRYPTO_ctr128_encrypt instead of AES_ctr128_encrypt.
I am trying to encrypt and decrypt a large file (100MB) using aes ctr with a 256-bit key. I downloaded this code from this http://www.gurutechnologies.net/blog/aes-ctr-encryption-in-c/. I am using Xcode to run it, but there is a problem, it give me "Read file is null" as output. I would appreciate if somebody could help me or give me a hint.
Note: I add the text file as shown in the image below:
struct ctr_state{
unsigned char ivec[AES_BLOCK_SIZE];
unsigned int num;
unsigned char ecount[AES_BLOCK_SIZE];};
FILE *readFile;
FILE *writeFile;
AES_KEY key;
int bytes_read, bytes_written;
unsigned char indata[AES_BLOCK_SIZE];
unsigned char outdata[AES_BLOCK_SIZE];
unsigned char iv[AES_BLOCK_SIZE];
struct ctr_state state;
int init_ctr(struct ctr_state *state, const unsigned char iv[16])
{
state->num = 0;
memset(state->ecount, 0, AES_BLOCK_SIZE);
/* Initialise counter in 'ivec' to 0 */
memset(state->ivec + 8, 0, 8);
/* Copy IV into 'ivec' */
memcpy(state->ivec, iv, 8);
return 0;
}
void fencrypt(char* read, char* write, const unsigned char* enc_key)
{
if(!RAND_bytes(iv, AES_BLOCK_SIZE))
{
fprintf(stderr, "Could not create random bytes.");
exit(1);
}
readFile = fopen(read,"rb"); // The b is required in windows.
writeFile = fopen(write,"wb");
if(readFile==NULL)
{
fprintf(stderr, "Read file is null.");
exit(1);
}
if(writeFile==NULL)
{
fprintf(stderr, "Write file is null.");
exit(1);
}
fwrite(iv, 1, 8, writeFile); // IV bytes 1 - 8
fwrite("\0\0\0\0\0\0\0\0", 1, 8, writeFile); // Fill the last 4 with null bytes 9 - 16
//Initializing the encryption KEY
if (AES_set_encrypt_key(enc_key, 128, &key) < 0)
{
fprintf(stderr, "Could not set encryption key.");
exit(1);
}
init_ctr(&state, iv); //Counter call
//Encrypting Blocks of 16 bytes and writing the output.txt with ciphertext
while(1)
{
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, readFile);
AES_ctr128_encrypt(indata, outdata, bytes_read, &key, state.ivec, state.ecount, &state.num);
bytes_written = fwrite(outdata, 1, bytes_read, writeFile);
if (bytes_read < AES_BLOCK_SIZE)
{
break;
}
}
fclose(writeFile);
fclose(readFile);
}
void fdecrypt(char* read, char* write, const unsigned char* enc_key)
{
readFile=fopen(read,"rb"); // The b is required in windows.
writeFile=fopen(write,"wb");
if(readFile==NULL)
{
fprintf(stderr,"Read file is null.");
exit(1);
}
if(writeFile==NULL)
{
fprintf(stderr, "Write file is null.");
exit(1);
}
fread(iv, 1, AES_BLOCK_SIZE, readFile);
//Initializing the encryption KEY
if (AES_set_encrypt_key(enc_key, 128, &key) < 0)
{
fprintf(stderr, "Could not set decryption key.");
exit(1);
}
init_ctr(&state, iv);//Counter call
//Encrypting Blocks of 16 bytes and writing the output.txt with ciphertext
while(1)
{
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, readFile);
//printf("%i\n", state.num);
AES_ctr128_encrypt(indata, outdata, bytes_read, &key, state.ivec, state.ecount, &state.num);
bytes_written = fwrite(outdata, 1, bytes_read, writeFile);
if (bytes_read < AES_BLOCK_SIZE)
{
break;
}
}
fclose(writeFile);
fclose(readFile);
}
int main(int argc, char *argv[])
{
fencrypt("encme.txt", "enced.enc", (unsigned const char*)"1234567812345678");
fdecrypt("enced.enc", "unenced.txt", (unsigned const char*)"1234567812345678");
getc(stdin);
return 0;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm trying to encrypt and decrypt txt file using AES in C.
but I got problem.
I watched binary of plain.txt and decrypted.txt.
so There's not same binary.
I want to make same binary.
How to fix this problem ?
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
void encrypt(FILE *ifp, FILE *ofp)
{
fseek(ifp, 0L, SEEK_END);
int fsize = ftell(ifp);
fseek(ifp, 0L, SEEK_SET);
EVP_CIPHER_CTX ctx;
int outLen1 = 0; int outLen2 = 0;
unsigned char *indata = malloc(fsize);
unsigned char *outdata;
unsigned blocksize;
unsigned char ckey[] = "thiskeyisverybadaaaaaaaaaaaaaaab";
unsigned char ivec[] = "dontusethisinputaaaaaaaaaaaaaaab";
fread(indata, sizeof(unsigned char), fsize, ifp);
EVP_EncryptInit(&ctx, EVP_aes_256_cbc(), ckey, ivec);
blocksize = EVP_CIPHER_CTX_block_size(&ctx);
outdata = malloc(fsize * 2 + blocksize + 15);
EVP_EncryptUpdate(&ctx, outdata, &outLen1, indata, fsize);
EVP_EncryptFinal(&ctx, outdata, &outLen2);
fwrite(outdata, sizeof(unsigned char), fsize, ofp);
free(indata);
free(outdata);
}
void decrypt(FILE *ifp, FILE *ofp)
{
fseek(ifp, 0L, SEEK_END);
int fsize = ftell(ifp);
fseek(ifp, 0L, SEEK_SET);
EVP_CIPHER_CTX ctx;
int outLen1 = 0; int outLen2 = 0;
unsigned char *indata = malloc(fsize);
unsigned char *outdata;
unsigned blocksize;
unsigned char ckey[] = "thiskeyisverybadaaaaaaaaaaaaaaab";
unsigned char ivec[] = "dontusethisinputaaaaaaaaaaaaaaab";
fread(indata, sizeof(unsigned char), fsize, ifp);
EVP_DecryptInit(&ctx, EVP_aes_256_cbc(), ckey, ivec);
blocksize = EVP_CIPHER_CTX_block_size(&ctx);
outdata = malloc(fsize * 2 + blocksize + 15);
EVP_DecryptUpdate(&ctx, outdata, &outLen1, indata, fsize);
EVP_DecryptFinal(&ctx, outdata, &outLen2);
fwrite(outdata, sizeof(unsigned char), fsize, ofp);
free(indata);
free(outdata);
}
int main(int argc, char *argv[])
{
FILE *fIN;
FILE *fOUT;
errno_t error;
char buf[255 + 1];
if ((error =fopen_s(&fIN,"C://Projects/test_curl/Debug/plain.txt","rb"))!=0 {
strerror_s(buf, 255, error);
printf("fopen_s error : \n%s\n", buf);
return 0;
}
if ((error = fopen_s(&fOUT, "C://Projects/test_curl/Debug/cyphertext.txt", "wb")) != 0) {
strerror_s(buf, 255, error);
printf("fopen_s error : \n%s\n", buf);
return 0;
}
encrypt(fIN, fOUT);
fclose(fIN);
fclose(fOUT);
if ((error = fopen_s(&fIN, "C://Projects/test_curl/Debug/cyphertext.txt", "rb")) != 0) {
strerror_s(buf, 255, error);
printf("fopen_s error : \n%s\n", buf);
return 0;
}
if ((error = fopen_s(&fOUT, "C://Projects/test_curl/Debug/decrypted.txt", "wb")) != 0) {
strerror_s(buf, 255, error);
printf("fopen_s error : \n%s\n", buf);
return 0;
}
decrypt(fIN, fOUT);
fclose(fIN);
fclose(fOUT);
return 0;
}
You're basically not following the letter of the instructions on how to invoke the API's you're calling. Among the things wrong:
The EVP_EncryptUpdate function encrypts the given data, storing the size of the encryption output in its size out param, which you're basically ignoring. The same is true on the decryption side.
You blast over the initial encrypted/decrypted data block with your invoke of EVP_EncryptFinal (and EVP_DecryptFinal), in contradiction to precisely what the libcrypto documentation specifically warns you NOT to do.
Your output size in both functions is wrong. You're writing fsize bytes, which was the input size, not the output size. the latter is provided in the output-size params which you're ignoring (see the first item in this list).
The following functions do what you want. Compare them to what you had (wishful thinking on my part). I took the liberty of not using encrypt as the name, as that is a commonly provided DES function in unistd.h.
void encrypt_data(FILE *ifp, FILE *ofp)
{
fseek(ifp, 0L, SEEK_END);
long fsize = ftell(ifp);
fseek(ifp, 0L, SEEK_SET);
EVP_CIPHER_CTX ctx;
int outlen=0;
unsigned char *indata = malloc(fsize);
unsigned char *outdata;
unsigned blocksize;
unsigned char ckey[] = "thiskeyisverybadaaaaaaaaaaaaaaab";
unsigned char ivec[] = "dontusethisinputaaaaaaaaaaaaaaab";
fread(indata, sizeof(unsigned char), fsize, ifp);
EVP_EncryptInit(&ctx, EVP_aes_256_cbc(), ckey, ivec);
// round up to nearest block size, this will add a complete
// block of additional padding if the input size is perfectly
// a factor of the block size
blocksize = EVP_CIPHER_CTX_block_size(&ctx);
outdata = malloc(((fsize + blocksize)/blocksize) * blocksize);
EVP_EncryptUpdate(&ctx, outdata, &outlen, indata, (int)fsize);
fwrite(outdata, 1, outlen, ofp);
EVP_EncryptFinal(&ctx, outdata, &outlen);
fwrite(outdata, 1, outlen, ofp);
free(indata);
free(outdata);
}
void decrypt_data(FILE *ifp, FILE *ofp)
{
fseek(ifp, 0L, SEEK_END);
long fsize = ftell(ifp);
fseek(ifp, 0L, SEEK_SET);
EVP_CIPHER_CTX ctx;
int outlen = 0;
unsigned char *indata = malloc(2 * fsize);
unsigned char *outdata = indata + fsize;
unsigned char ckey[] = "thiskeyisverybadaaaaaaaaaaaaaaab";
unsigned char ivec[] = "dontusethisinputaaaaaaaaaaaaaaab";
fread(indata, 1, fsize, ifp);
EVP_DecryptInit(&ctx, EVP_aes_256_cbc(), ckey, ivec);
EVP_DecryptUpdate(&ctx, outdata, &outlen, indata, (int)fsize);
fwrite(outdata, 1, outlen, ofp);
EVP_DecryptFinal(&ctx, outdata, &outlen);
fwrite(outdata, 1, outlen, ofp);
free(indata);
}
Those will work.
Best of luck.
I'm using the following working code to decrypt a file:
#include <openssl/aes.h>
#include <stdio.h>
#include <string.h>
struct ctr_state {
unsigned char ivec[16];
unsigned int num;
unsigned char ecount[16];
};
FILE *fp;
FILE *rp;
FILE *op;
size_t count;
char * buffer;
AES_KEY key;
int bytes_read, bytes_written;
unsigned char indata[AES_BLOCK_SIZE];
unsigned char outdata[AES_BLOCK_SIZE];
unsigned char ckey[] = "1234567890123456";
unsigned char iv[8] = {0};
struct ctr_state state;
void init_ctr(struct ctr_state *state, const unsigned char iv[8]){
state->num = 0;
memset(state->ecount, 0, 16);
memset(state->ivec + 8, 0, 8);
memcpy(state->ivec, iv, 8);
}
void decrypt(){
//Opening files where text cipher text is read and the plaintext recovered
rp=fopen("c:\\temp\\decrypted.mp3","wb");
op=fopen("c:\\temp\\encrypted.mp3","rb");
if (rp==NULL) {fputs ("File error",stderr); return;}
if (op==NULL) {fputs ("File error",stderr); return;}
//Initializing the encryption KEY
AES_set_encrypt_key(ckey, 128, &key);
init_ctr(&state, iv);//Counter call
//Encrypting Blocks of 16 bytes and writing the output.txt with ciphertext
while (1) {
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, op);
AES_ctr128_encrypt(indata, outdata, bytes_read, &key, state.ivec, state.ecount, &state.num);
bytes_written = fwrite(outdata, 1, bytes_read, rp);
if (bytes_read < AES_BLOCK_SIZE)
break;
}
fclose (rp);
fclose (op);
}
int main(int argc, char *argv[]){
decrypt();
return 0;
}
Is it possible to do the same thing using the openssl command line?
AFAIK, there's no -aes-128-ctr cipher but is there any equivalent in openssl?
No version of the openssl(1) command line tool that I've checked appears to support counter mode for any cipher.