openssl encryption and decryption using evp library - security

I have a plain text and I have the cipher text with me and my task is to find the key for the cipher text declared. The key is a word list like a dictionary. I have written the code in c and it compiles perfect and creates the file with all the ciphers.
The problem I am facing is that every time i run the code a cipher text is completely different. I have no clue where I am making a mistake.
The following is the code I had written
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/evp.h>
int main()
{
int i;
char words[32], t;
FILE *key, *outFile;
const char *out = "Output.txt";
unsigned char outbuf[1024 + EVP_MAX_BLOCK_LENGTH];
unsigned char iv[] = "0000000000000000";
int outlen, tmplen;
int num;
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
char inText[] = "This is a top secret.";
char cipherText[] = "8d20e5056a8d24d0462ce74e4904c1b513e10d1df4a2ef2ad4540fae1ca0aaf9";
key = fopen("words.txt", "r");
if( remove("ciphertext.txt") == -1 ) {
perror("Error deleting file");
}
outFile = fopen("ciphertext.txt", "a+");
if( key < 0 || outFile < 0 )
{
perror ("Cannot open file");
exit(1);
}
char pbuffer[1024];
while ( fgets(words,32, key) )
{
i=strlen(words);
words[i-1]='\0';
//printf("%s",words);
i = 0;
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;
print_hex(outbuf, outlen, outFile);
}
fclose(key);
fclose(outFile);
return 1;
}
int print_hex(unsigned char *buf, int len, FILE *outFile)
{
int i,n;
char x='\n';
for ( i = 0; i < len; i++ )
{
fprintf(outFile,"%02x",buf[i]);
}
fprintf(outFile,"%c",x);
return (0);
}
Since the key is a word. The words in the wordlist can be of size < or > 16 bytes and from my research on openssl it was said that there will be a pkcs#5 padding if the block length is does not fit into 16bytes. Is it the same case for the key also.
The cipher text I declared does not match with the cipher text I am generating from the program and I am unable to find the key for the cipher text.
I need help from the experts. I would appreciate if some one helps me in getting out of the trouble
Thanks in advance

What are you actually trying to achieve? Your code looks like an attempt to carry out a brute-force attack using a dictionary of passwords ... I'm not sure I should be trying to help with that!
I'll assume it's just an exercise ...
The first thing that strikes me is that you are setting your initialization vector (the variable iv) to a string of ASCII zeros. That's almost certainly wrong, and you probably need to use binary zeros.
unsigned char iv[16] = { 0 };
I don't know how the ciphertext that you have was generated (by another program, presumably) but I would imagine that that program didn't use the dictionary word itself as a key, but went through some sort of key derivation process first. You are using 128-bit AES as your encryption algorithm, so your keys should be 16 bytes long. You could achieve that by padding, as you suggest, but it's more usual to go through some process that mixes up the bits of the key to make it look more random and to distribute the key bits throughout the whole key. It wouldn't be unusual to hash the word and to use the output of the hash function rather than the word itself as key. Another possibility is that the dictionary word may be used as the input to a passphrase-based key derivation function such as that defined in PKCS#5.
You really need to find out how the word is used to generate a key before you can get any further with this.

Thank you very much for the reply.
Yes it is just an exercise and is like a dictionary attack.
I am supposed to use iv with zeros but not ASCII zero, which is one of the mistakes I had made.
I assume the given cipher text is encrypted purely with a word from the word list without any hashing and might be padding is done but I am not sure because I am supposed to do find the key from the cipher text. The word list might have words less than 16 bytes or words greater than 16 bytes. So the problem I am thinking might be with the padding.
I am thinking may be if the word length is less than 16 bytes, then I have to pad with either ASCII zeros or something like that. Which one do you suggest me to do and with little push may be I am finished.
Thanks

Related

encryption and decryption with openssl AES on Linux

I want to use AES to communicate tcp/ip. However, difficulties arose in making the AES function.
In the process of decoding, dummy values are generated or the values are deleted.
I'd appreciate it if you could give me a little help.
int main(void)
{
unsigned char mykey[] = "01234567890123456789012345678\0";
unsigned char iv[] = "0123456789012\0";
char buf[BUF_SIZE]="hi";
char enc[BUF_SIZE];
char dec[BUF_SIZE];
AES_encryption(buf,enc,mykey,iv);
AES_decryption(enc,dec,mykey,iv);
printf("buf : %s\n",buf);
printf("enc: %s\n",enc);
printf("dec: %s\n", dec);
return 0;
}
void AES_encryption(char plainfn[], char cipherfn[], unsigned char key[],unsigned char iv[])
{
EVP_CIPHER_CTX ctx;
int in_len, out_len=0;
in_len=strlen(plainfn);
EVP_CIPHER_CTX_init(&ctx);
EVP_CipherInit_ex(&ctx,EVP_aes_128_cbc(),NULL,key,iv,AES_ENCRYPT);
EVP_CipherUpdate(&ctx,cipherfn,&out_len,plainfn,in_len);
EVP_CipherFinal_ex(&ctx,cipherfn,&out_len);
EVP_CIPHER_CTX_cleanup(&ctx);
}
void AES_decryption(char cipherfn[], char plainfn[], unsigned char key[], unsigned char iv[])
{
EVP_CIPHER_CTX ctx;
int in_len, out_len=0;
in_len=strlen(cipherfn);
EVP_CIPHER_CTX_init(&ctx);
EVP_CipherInit_ex(&ctx,EVP_aes_128_cbc(),NULL,key,iv,AES_DECRYPT);
EVP_CipherUpdate(&ctx,plainfn,&out_len,cipherfn,in_len);
EVP_CipherFinal_ex(&ctx,plainfn,&out_len);
EVP_CIPHER_CTX_cleanup(&ctx);
}
These results come out.
buf : hi
enc: U▒▒B▒ac▒▒]▒▒▒▒Y▒-
dec: hi▒?!▒
The main problem is that AES_encryption is likely put NULL chars to the enc buffer. You then count the scrambled enc buffer "string length" via strlen() in AES_decryption. This is certainly wrong since decryption can stop too early thus not reading the entire input buffer.
You should probably pass an buffer size argument to encrypt and decrypt functions to properly encrypt/decrypt the buffer(s).
Calculate the string length before encryption and some how pass the same buffer length also to the decryption stage. You probably have to encode the string length in your buf before the actual data.
Also since enc buffer is by definition scrambled you can't just printf("%s",enc) it for the same reason strlen() doesn't work for it. You need to print the chars one by one by putchar() or some other way that is immune to null chars.

Brute Force Attack ( decryption ) AES

I'm trying to programming the brute force attack, the idea is that:
I already have the Cipher text After the encryption
I have the first 4 letter of the plain text ( which is 41 character )
I have the first 12 character of the secret key
What I need is to find the 4 missing characters
Let's assume I have the key :
"ABCDEFGHIJ????"
How can I apply brute force attack to find the missing character ?
There are 2^32 possibilities for the missing 4 key bytes. That fits into an unsigned 32-bit int. So, loop over all possibilities for this unsigned int, taking your four missing bytes from the integer value. In C, something like this:
unsigned int i = 0;
do {
first candidate missing byte for key = i&255;
second candidate missing byte for key = (i>>8)&255;
third candidate missing byte for key = (i>>16)&255;
fourth candidate missing byte for key = (i>>24)i&255;
/* here: try the candidate with your AES encryption, break if it works */
++i;
} while (i != 0);

splitting a line and printing it takes results in a core dumped

When I try to read a line from standard input and split it into words, after removing the /n character, I get a core dumped error. Could anyone explain me the reason? What is the correct way to do this?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LINE_LEN 50
#define MAX_PARTS 50
int main ()
{
char* token;
char *str;
char* arr[MAX_PARTS];
int i,j;
printf("Write a line: \n $:");
fgets(str, LINE_LEN, stdin);
str = strncpy(str, str, strlen(str)-1);
fflush(stdin);
i=0;
token = strtok(str, " ");
while( token != NULL )
{
arr[i] = token;
printf("%s",arr[i]);
i++;
token = strtok(NULL," ");
}
return 0;
}
You are printing the NULL pointer on your last pass through the while() loop. You probably need to reverse the printf() and strtok() calls like this:
while( token != NULL )
{
arr[i] = token;
printf("%s",arr[i]); # Must come first to avoid printing a NULL on final loop
i++;
token = strtok(NULL," ");
}
You are reading into unallocated memory.
char *str;
This declares a pointer str, which is pointing nowhere. (In fact, it points to a random location, but "nowhere" stops the guys who try to second-guess undefined behaviour.)
fgets(str, LINE_LEN, stdin);
This writes to the location str is pointing at, which is nowhere (see above). This is undefined behaviour. If your program happens to survive this (instead of SEGFAULTing right there), you cannot rely on it behaving in any sane manner from this point on.
While we're at it:
fflush(stdin);
Note that the C standard does not define the behaviour of fflush() when called on input streams, i.e. while this is well-defined under Linux (which does define this behaviour), this is a non-standard, non-portable construct that could well crash on other platforms.

What kind of cryptographic mechanism uses repeated xor's?

I'm attempting to analyze a short encryption program and figure out which mechanism it's using.
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char * argv[] ) {
long int key;
char * endptr;
key = strtol( argv[1], &endptr, 10 );
srandom( key );
{ /* now copy input to output through crypt transformation */
char ch;
while (!feof( stdin )) {
putc( (getc(stdin) ^ random())&0xFF, stdout );
}
fclose( stdout );
}
}
I can follow this simply, but I'm having trouble trying to weed out which mechanism it's using..
I'm looking at the following:
http://en.wikipedia.org/wiki/Public-key_cryptography
http://en.wikipedia.org/wiki/Block_cipher
http://en.wikipedia.org/wiki/Stream_cipher
http://en.wikipedia.org/wiki/Diffie-Hellman
I'm leaning towards iterated block cyphers but I really have no idea at this point.
You need to clearly distinguish in your mind the ciphers in categories. There are:
Block ciphers, which operate in fixed-size blocks of input
Stream ciphers, which operate on data streams (i.e. one byte at a time)
The above only distinguishes ciphers by the size of the input they accept; it has nothing to do with the mechanism they use to produce the encrypted text.
Regarding this mechanism, we have:
Substitution ciphers
Transposition ciphers
And many other types which are basically combinations of the above, possibly with many iterations
So try to answer this question first:
Is your example a stream cipher or a block cipher? Remember, this has nothing to do with how it encrypts!
It's a stream cipher. The cipherkey is generated by seeding srandom with the given key.
In cryptography, a stream cipher is a
symmetric key cipher where plaintext
bits are combined with a pseudorandom
cipher bit stream (keystream),
typically by an exclusive-or (xor)
operation. In a stream cipher the
plaintext digits are encrypted one at
a time, and the transformation of
successive digits varies during the
encryption.
Which is what you're doing here. key is the symmetric key, and the cipher stream is generated by random(). The call to srandom(key) assures that the random stream will ke the same as long as your key is the same.

Adding a simple MAC to url parameters?

I want to add a simple kind of MAC to some of my URL parameters. This is only intended as an additional line of defense against application bugs and caching related problems/bugs, and not intended as any form of replacement of the actual login security in the application. A given business-object-id is already protected by backends to be limited to a single user.
So basically I'd like to add a short authentication code to my url parameters, on the size of 2-4 characters. I think I'd like to have a reversible function along the lines of f(business-data-id + logged-on-user-id + ??) = hash, but I am open to suggestions.
The primary intention is to stop id guessing, and to make sure that url's are fairly distinct per logged on user. I also don't want something big and clunky like an MD5.
Since you aren't looking for cryptographic quality, maybe a 24-bit CRC would fit your needs. While MD5 is "fast" in absolute terms, CRC is, relatively, "blindingly fast". Then the 3-byte CRC could be text-encoded into four characters with Base-64 encoding.
Here's a Java implementation of the check used for OpenPGP ASCII-armor checksums:
private static byte[] crc(byte[] data)
{
int crc = 0xB704CE;
for (int octets = 0; octets < data.length; ++octets) {
crc ^= (data[octets] & 0xFF) << 16;
for (int i = 0; i < 8; ++i) {
crc <<= 1;
if ((crc & 0x1000000) != 0)
crc ^= 0x1864CFB;
}
}
byte[] b = new byte[3];
for (int shift = 16, idx = 0; shift >= 0; shift -= 8) {
b[idx++] = (byte) (crc >>> shift);
}
return b;
}
I would hash a secret key (which is known only by the server), together with whatever you want to protect—probably the combination of object identifier and user identifier.
If what you want is basically MD5 but smaller, why not just use MD5 but just the last 4 characters? This doesn't add a huge blob to your urls, it's always 4 nice hex digits.
A quick question for which I'm sure there's a good answer for, but why not store this information in a cookie?
Then you could use something big and clunky like MD5 and your URLs would still be pretty.

Resources