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.
Related
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 new with cryptography, so I decided to create simple program that would open a file encrypt data, put it in etest.txt, then open this file decrypt it and put it indetest.txt. I know it sounds really weired but its for educational purposes. so here is my code.
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <stdio.h>
#include <string.h>
int main(void) {
size_t pri_len; // Length of private key
size_t pub_len; // Length of public key
char *pri_key; // Private key
char *pub_key; // Public key
char *msg = malloc(256); // Message to encrypt
char *encrypt = NULL; // Encrypted message
char *decrypt = NULL; // Decrypted message
char *err; // Buffer for any error messages
// Generate key pair
RSA *keypair = RSA_generate_key(2048, 3, NULL, NULL);
FILE *in = fopen("test.txt", "rb");
FILE *out = fopen("etest.txt", "wb");
if(in == NULL)
{
printf("in Error is %d (%s).\n", errno, strerror(errno));
}
if(out == NULL)
{
printf("out Error is %d (%s).\n", errno, strerror(errno));
}
encrypt = malloc(RSA_size(keypair));
for(;;)
{
//213 because of padding
memset(msg, '\0', 256);
memset(encrypt, '\0', 256);
fread(msg, 213, 1, in);
if((RSA_public_encrypt(strlen(msg), (unsigned char*)msg, (unsigned char*)encrypt,
keypair, RSA_PKCS1_OAEP_PADDING)) == -1) {
ERR_load_crypto_strings();
ERR_error_string(ERR_get_error(), err);
fprintf(stderr, "Error encrypting message: %s\n", err);
}
if(fwrite(encrypt, 256, 1, out) != 1)
{
printf("fwrite Error is %d (%s).\n", errno, strerror(errno));
}
if(feof(in))
{
break;
}
}
fclose(in);
fclose(out);
in = fopen("etest.txt", "rb");
out = fopen("dtest.txt", "wb");
if(in == NULL)
{
printf("in Error is %d (%s).\n", errno, strerror(errno));
}
if(out == NULL)
{
printf("out Error is %d (%s).\n", errno, strerror(errno));
}
decrypt = malloc(RSA_size(keypair));
for(;;)
{
//I use malloc because if i didnt it would from file and if it filled the msg and if this function would execute second time it would not overwrite the whole buffer and would cause problem
memset(decrypt, '\0', 256);
memset(msg, '\0', 256);
fread(msg, 256, 1, in);
if(RSA_private_decrypt(256, (unsigned char*)msg, (unsigned char*)decrypt,
keypair, RSA_PKCS1_OAEP_PADDING) == -1) {
ERR_load_crypto_strings();
ERR_error_string(ERR_get_error(), err);
fprintf(stderr, "Error decrypting message: %s\n", err);
}
fwrite(decrypt, 256, 1, out);
if(feof(in))
{
break;
}
}
fclose(in);
fclose(out);
RSA_free(keypair);
return 0;
}
When I run code it gives me back error saying:Error decrypting message: error:0407A079:rsa routines:RSA_padding_check_PKCS1_OAEP:oaep decoding error but if i delete this codememset(msg, '\0', 256); it shows that everything works fine but it causes problems because msg buffer is overwritten with first few bytes that second fread() function overwrote.
Sorry if my questions sound silly. Hope you can help. thanks.
Your are using fwrite(decrypt, 256, 1, out); which is wrong.size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) Second parameter is the size in bytes of each element to be read And the third one is number of elements, each one with a size of size bytes.
I need to read data from the serial port, but the read() function always return 8 bytes or less, how can I do to get all data
the c code:
readbytes = read(f, bufptr, sizeof(buffer));
buffer[readbytes]='\0';
printf("number of bytes read is %d\n", readbytes);
printf("buffer %s\n", buffer);
I try to use the do while, but i still have the same result.
[too long for a comment]
Try this code:
char buffer[256];
memset(buffer, 0, 256);
size_t bytes_read= 0, bytes_expected = 11;
do {
ssize_t result = read(f, buffer + bytes_read, bytes_expected - bytes_read);
if (0 >= result)
{
if (0 > result)
{
perror("read()");
}
break;
}
bytes_read+= result;
} while (bytes_read < bytes_expected)
fprintf(stderr, "Read %zu out of %zu expected bytes: `%s`\n", bytes_read, bytes_expected, buffer);
below is my code
void encrypt(){
//Opening files where text plain text is read and ciphertext stored
fp=fopen("input.txt","rb");
op=fopen("output.txt","wb");
if (fp==NULL) {fputs ("File error",stderr); exit (1);}
if (op==NULL) {fputs ("File error",stderr); exit (1);}
//Initializing the encryption KEY
AES_set_encrypt_key(ckey, 128, &key);
//Encrypting Blocks of 16 bytes and writing the output.txt with ciphertext
while (1) {
init_ctr(&state, iv); //Counter call
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, fp);
AES_ctr128_encrypt(indata, outdata, bytes_read, &key, state.ivec, state.ecount, &state.num);
bytes_written = fwrite(outdata, 1, bytes_read, op);
if (bytes_read < AES_BLOCK_SIZE)
break;
}
fclose (fp);
fclose (op);
free (buffer);
}
int main(int argc, char *argv[]){
encrypt();
//decrypt();
system("PAUSE");
return 0;
}
I referenced this link: AES CTR 256 Encryption Mode of operation on OpenSSL
But I found 2 error that explain _AES_set_encrpyt_key and _AES_Crt128-encrpyt weren't found in external symbol error code is LNK2019.
How to deal with this?