I am not able to find any bugs..
What I want to do:
Remark:
Here is my code:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/evp.h>
void pad(char *s,int length);
int strcicmp(char const *a, char const *b);
int main(){
int i;
char words[16],t;
FILE *key;
unsigned char outbuf[1024 + EVP_MAX_BLOCK_LENGTH];
unsigned char iv[] = {0xaa,0xbb,0xcc,0xdd,0xee,0xff,0x00,0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11};
int outlen, tmplen;
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
char inText[] = "This is a top secret.";
char cipherTextGiven[] = "764aa26b55a4da654df6b19e4bce00f4ed05e09346fb0e762583cb7da2ac93a2";
key = fopen("wordList.txt","r");
while(fgets(words,16, key)) {
i=strlen(words);
words[i-1]='\0';
i=strlen(words);
if(i<16){
pad(words,16);
}
EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(),NULL, words, iv);
if(!EVP_EncryptUpdate(&ctx, outbuf, &outlen, inText, strlen(inText))){
EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
if(!EVP_EncryptFinal_ex(&ctx, outbuf + outlen, &tmplen)){
EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
outlen += tmplen;
int i;
char* buf_str = (char*) malloc (2*outlen + 1);
char* buf_ptr = buf_str;
for(i=0;i<outlen;i++)
buf_ptr += sprintf(buf_ptr, "%02X", outbuf[i]);
*(buf_ptr + 1) = '\0';
printf("%s\n",buf_str);
if(strcicmp(cipherTextGiven, buf_str) == 0){
printf("Key: %s\nwith corresponding cipher: ", words);
for(i=0; i < outlen; i++)
printf("%02x",outbuf[i]);
printf("\n");
}
}
fclose(key);
return 1;
}
//provide padding function to key
void pad(char *s,int length){
int l;
l = strlen(s);
while(l<length){
s[l] = 0x23;
l++;
}
s[l] = '\0'; //add termination char for the array
}
int strcicmp(char const *a, char const *b){
for(;;a++,b++){
int d = tolower(*a) - tolower(*b);
if(d != 0 || !*a)
return d;
}
}
Change char words[16]
to char words[18]
. You need 18 elements in words
because you want to handle keys of up to 16 characters, because fgets
will read a key plus a new-line character, and the buffer will contain a null character after that.
Change fgets(word,16, key)
to fgets(word, sizeof word, key)
. fgets
needs to know the full size of the available buffer, including space for the new-line character and the terminating null character, not just the number of key characters you want.
Delete *(buf_ptr + 1) = '\0';
. It is unnecessary because sprintf
writes a terminating null character and because the correct location for it would be buf_ptr
, not buf_ptr+1
. So this statement is writing beyond the space allocated for buf_str
.
The following code is not causing whatever problem you are observing, but it could be written better.
Declare main
as int main(void)
or int main(int argc, char *argv[])
, not int main()
.
Do not write s[l] = 0x23;
unless you need to write a program that uses a character set different from the character set of the C implementation it is compiled and executed with. To set a character to “#“, use s[l] = '#';
.
If, in sprintf(buf_ptr, "%02X", outbuf[i]);
, you change %02X
to %02x
, then it will use lowercase for the hexadecimal, and you can use the standard strcmp
to compare the buffer to cipherTextGiven
instead of needing a custom strcicmp
function. Better yet, when the program starts, convert cipherTextGiven
from hexadecimal to raw binary and, when testing candidate keys, compare that raw binary to the computed cipher text using memcmp
.
In this:
i=strlen(words);
words[i-1]='\0';
i=strlen(words);
Change the last line to i = i-1;
, because we know that the previous line decreased the length by one, so we can set the length directly without calling strlen
again. Many programmers would write these lines as something like:
i = strlen(words);
words[--i] = '\0';