i'm try to get a bowfish function working for simple char buffers. The program fails when I try to decrypt an encrypted buffer and fails on the EVP_CipherFinal_ex() call.
#include <string.h>
#include <openssl/evp.h>
#include <openssl/buffer.h>
#include <openssl/blowfish.h>
#include <openssl/evp.h>
int do_crypt(unsigned char *inbuf, int inlen, unsigned char *outbuf, int *outlen, int do_encrypt) {
outbuf=(unsigned char*) malloc(inlen+EVP_MAX_BLOCK_LENGTH);
int tmplen=0;
unsigned char key[] = "0123456789";
unsigned char iv[] = "12345678";
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_CipherInit_ex(&ctx, EVP_bf_cbc(), NULL, NULL, NULL, do_encrypt);
EVP_CIPHER_CTX_set_key_length(&ctx, 10);
EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, do_encrypt);
if(!EVP_CipherUpdate(&ctx, outbuf, outlen, inbuf, inlen)) {
/* Error */
printf("* update failed *\n");
EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
int db=*outlen;
if(!EVP_CipherFinal_ex(&ctx, outbuf+db, &tmplen)) {
/* Error */
ERR_print_errors_fp(stderr);
printf("* finalise failed *\n");
EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
(*outlen)=db+tmplen;
EVP_CIPHER_CTX_cleanup(&ctx);
return 1;
}
int main(int argc, char **argv) {
char *plain="ENCRYPT DECRYPT this string";
int plain_len=strlen(plain);
unsigned char *cipher;
int cipher_len;
printf("***** ENCRYPT *****\n");
if (!do_crypt((unsigned char*) plain, strlen(plain), cipher, &cipher_len, 1)) {
printf("failed to encrypt\n");
return 1;
}
char *decrypt;
int decrypt_len;
printf("***** DECRYPT *****\n");
if(!do_crypt( cipher ,cipher_len , decrypt, &decrypt_len, 0)) {
printf("failed to decrypt\n");
return 1;
}
printf("decrypt=\"%s\"\n",decrypt);
printf("decrypt_len=%d\n",decrypt_len);
return 0;
}
any help would be much appreciated.
You have two problems: The first is that you should not cast the result of malloc in C. This is the most likely reason EVP_CipherUpdate crashes.
The second error is that arguments in C are passed by value, meaning they are copied and the functions only have copies of the arguments passed by the caller. This means that in the do_crypt function when you assign to the argument output you are only assigning to the local copy inside the function, the variable cipher in the main function will not be changed.
The last problem can be solved by imitating pass by reference by passing a pointer to the pointer, and use the address-of operator & and the dereference * operator:
/* Note extra indirection */
/* | */
/* v */
int do_crypt(unsigned char *inbuf, int inlen, unsigned char **outbuf, int *outlen, int do_encrypt) {
...
*output = malloc(...);
...
if(!EVP_CipherUpdate(&ctx, *outbuf, outlen, inbuf, inlen)) { ... }
...
}
You then call it like
do_crypt((unsigned char*) plain, strlen(plain), &cipher, &cipher_len, 1)
Related
Here is the code
#include <stdio.h>
//#include "ConvertEndianess.h"
typedef unsigned char uint8_t;
void ConvertEndianess(uint8_t* buffAddr, uint8_t length);
void ConvertEndianess(uint8_t *buffAddr, uint8_t length)
{
uint8_t i;
uint8_t data;
for (i = 0U; i < (length / 2U); i++)
{
data = buffAddr[i];
buffAddr[i] = buffAddr[(length - 1U) - i];
buffAddr[(length - 1U) - i] = data;
}
}
int main(int argc, char *argv[]){
printf("\nNumber Of Arguments Passed: %d\n",argc);
if(argc < 3){
printf("Too Few Arguments\n");
}
else if(argc > 3){
printf("Too Many Arguments\n");
}
else{
printf("data indianess: %s\n",argv[1]);
ConvertEndianess((uint8_t *)&argv[1], (uint8_t)(*argv[2]));
printf("data indianess: %s\n",argv[1]);
}
}
Here is my argument:
./a 11223344 4
It is printing correctly before going to conversion API but maybe some casting mistake is done by me and I'm not able to identify it.
Can anyone please correct my mistake with explanation?
(uint8_t)(*argv[2])
argv[2] is a char * and according to how your program operates, I assume that is supposed to contain the size of the buffer. Since this is a string (char *), and you want to convert it to a number, you'll need to use sscanf to get this value:
Sample useage:
size_t len;
sscanf(str, "%zu", &len);
Then pass len as the second argument of your conversion function.
The way you are doing it presently passes the ASCII code for the first character of argv[2]. So if the user said the size is "7" you are actually passing the integer 55 to the conversion function.
As a side note, use size_t to represent size, not uint8_t.
The main problem on your code is that you cast &argv[...] with an incompatible type.
argv[...] is a char* so &argv[...] is some char**, and you cast it as a uint8_t* which is incompatible.
Some remarks:
You should not type & before argv[...]:
You can use strlen() instead of passing an argument
You can use strtol() to convert a string into an integer
Indianness or Endianness?
#include <stdio.h>
#include <string.h> /* strlen */
#include <stdlib.h> /* strtol */
typedef unsigned char uint8_t;
void ConvertEndianess(uint8_t *buffAddr, uint8_t length)
{
uint8_t i;
uint8_t data;
for (i = 0U; i < (length / 2U); i++)
{
data = buffAddr[i];
buffAddr[i] = buffAddr[(length - 1U) - i];
buffAddr[(length - 1U) - i] = data;
}
}
int main(int argc, char *argv[]){
printf("\nNumber Of Arguments Passed: %d\n",argc);
if(argc == 2){
/* exemple with strlen */
printf("data Endianess: %s\n",argv[1]);
ConvertEndianess(argv[1], strlen(argv[1]));
printf("data Endianess: %s\n",argv[1]);
}
else if(argc == 3){
/* exemple with strtol */
printf("data Endianess: %s\n",argv[1]);
ConvertEndianess((uint8_t *)argv[1], strtol(argv[2], NULL, 0));
printf("data Endianess: %s\n",argv[1]);
}
}
I'm trying to be able to decode encoded strings that were encoded using a perl script. The reason I can't just change the perl script is because a lot of important data already exists that was saved via the perl script and it would be too much to decode in perl and recode another way. It's easier just to keep things in place (for now). However, the compiled perl code is 2MB. I want to write it in C so the executable will be a smaller size.
What I have so far is below. It won't work though. It basically gives me junk output. The problem I think is that the perl script used a hex-based encryption. How do I go about decoding that? Can someone point me to where I went wrong?
/*
Test to decode perl-encrypted string.
NOTE: Not all code written by me. Function code is either written by or derived
from code from other people in response to similar questions found on the
internet.
Required Lib: crypt (-lcrypt)
Perl Code from existing script (that is being converted to C):
use Crypt::CBC;
use Crypt::DES;
my $text = "thisisalongtest";
my $salt_key = "fOagmJOKu2SF";
my $cipher = Crypt::CBC->new( -key => $salt_key, -cipher => 'DES' -header => 'none');
my $enc_text = $cipher->encrypt_hex($text);
Perl crypt functions require libcrypt-cbc-perl & libcrypt-des-perl
Data:
Original Text: thisisalongtest
Salt Key: fOagmJOKu2SF
Resulting Encrypted String: 53616c7465645f5f167ebac84042fe7ceac836e1d3e7d3aa1dfc27e0e8cad0f1
Resulting output:
Decrypted: (unprintable junk characters)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rpc/des_crypt.h>
#define BUFFSIZE 420
int encrypt(char key[9], char salt[9], char pass[BUFFSIZE], int mode);
void enc_from_hex(const char* st, char ret_result[BUFFSIZE]);
int hex_to_int(char c);
int hex_to_ascii(char c, char d);
int main (int argc, char *argv[]) {
int err;
char passwd[BUFFSIZE];
char result[BUFFSIZE];
char key[13];
sprintf(key,"fOagmJOKu2SF");
/* Change this from hex pairs to ASCII */
sprintf(passwd, "53616c7465645f5f167ebac84042fe7ceac836e1d3e7d3aa1dfc27e0e8cad0f1");
enc_from_hex(passwd, result);
/* Decrypt */
err = encrypt(key, "", result, 1); /* DO NOT use 'NULL' for 2nd parameter! */
if(err != 0) {
printf("Error.\n");
} else {
printf("Decrypted: %s\n", result);
}
return 0;
}
/* Encryption */
int encrypt(char key[13], char salt[13], char pass[BUFFSIZE], int mode){
char temp[13];
strcpy(temp, salt);
int buffsize;
int errcode;
des_setparity(key);
buffsize = strlen(pass);
/* Pad pass to ensure size is divisable by 8.*/
while (buffsize % 8 && buffsize<BUFFSIZE) {
pass[buffsize++] = '\0';
}
/* Determine Function */
if(mode == 1) {
errcode = cbc_crypt(key, pass, buffsize, DES_DECRYPT | DES_SW, temp);
} else {
errcode = cbc_crypt(key, pass, buffsize, DES_ENCRYPT | DES_SW, temp);
}
if (DES_FAILED(errcode) || strcmp(pass, "") == 0) {
return errcode;
}
return errcode;
}
/* Hex conversion functions */
void enc_from_hex(const char* st, char ret_result[BUFFSIZE]) {
char temp[2];
int length = strlen(st);
int i;
char buf = 0;
for(i = 0; i < length; i++) {
if(i % 2 != 0) {
sprintf(temp, "%c", hex_to_ascii(buf, st[i]));
strcat(ret_result, temp);
} else {
buf = st[i];
}
}
}
int hex_to_int(char c) {
int first = c / 16 - 3;
int second = c % 16;
int result = first*10 + second;
if(result > 9) result--;
return result;
}
int hex_to_ascii(char c, char d) {
int high = hex_to_int(c) * 16;
int low = hex_to_int(d);
return high+low;
}
As #ikegami points out in the comments the value passed to key Crypt::CBC is not really a key. This value is passed to another function which combines it with a random salt then hashes it to generate the real key and initialization vector. The random salt is saved with the cypher text the idea being if you encrypt the same data with the same key more than once the output will be different every time.
If you convert your encrypted string to ascii you will notice the first eight characters spell Salted__, this corresponds to the format used by OpenSSL.
See below for a somewhat crude example using OpenSSL's EVP api:
//
// compile with: gcc -o crypt crypt.c -lssl -lcrypto
//
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
int main(int argc, char *argv[]){
char pass[]="fOagmJOKu2SF";
char text[]="53616c7465645f5f167ebac84042fe7ceac836e1d3e7d3aa1dfc27e0e8cad0f1";
int i = 0;
char *pos=text;
while(*pos){ // converts hex string to binary in place
sscanf(pos, "%2hhx", &text[i++]);
pos += 2;
} text[i]=0;
EVP_CIPHER_CTX ctx;
unsigned char key[8] = {0};
unsigned char iv[8] = {0};
int len;
char *clear = malloc(strlen(text));
// v-> First Charicter after 'Salted__'
EVP_BytesToKey(EVP_des_cbc(), EVP_md5(), &text[8], pass, strlen(pass), 1, key, iv);
EVP_DecryptInit(&ctx, EVP_des_cbc(), key, iv);
// v-> Cypertext starts after salt
EVP_DecryptUpdate(&ctx, clear, &len, &text[16], strlen(text)-15);
EVP_DecryptFinal(&ctx, clear, &len);
printf("%s\n", clear);
return 0;
}
http://www.ict.griffith.edu.au/anthony/info/crypto/openssl.hints
https://www.openssl.org/docs/manmaster/crypto/EVP_BytesToKey.html
https://www.openssl.org/docs/manmaster/crypto/EVP_EncryptInit.html
Here is a snippet of my code:
#include <stdio.h>
#include "uhash.h"
#include <openssl/evp.h>
char * hash(item a)
{
const char * str= a.k;
int len= strlen(str);
int md_len;
unsigned char md_value[EVP_MAX_MD_SIZE]; /* Buff to store change result */
EVP_MD_CTX *mdctx; /* Digest data structure declaration */
const EVP_MD *md;
OpenSSL_add_all_digests();
md = EVP_get_digestbyname("SHA256");
mdctx = EVP_MD_CTX_create();
EVP_DigestInit_ex(mdctx, md, NULL);
EVP_DigestUpdate(mdctx, str, len);
EVP_DigestFinal_ex(mdctx, md_value, &md_len);
EVP_MD_CTX_destroy(mdctx);
char md5str[33];
for(int i=0;i<md_len;++i)
{
sprintf(&md5str[i*2],"%02x",(unsigned int)md_value[i]);
}
printf("%s\n", md5str);
return md5str;
}
int main(int argv, char **argc)
{
char *c;
if (argv>0)
{
int i=0;
int s=0;
for(i=1;i<argv;i++)
{
s+=strlen(argc[i]);
}
c=(char *)(malloc(sizeof(char)*s*(argv-2)+1));
s=0;
for(i=1;i<argv;i++)
{
char *t=c+s;
memcpy(t,argc[i],strlen(argc[i]));
if(i!=argv-1){
printf("%d\n", argv);
t[strlen(argc[i])]=' ';
s++;
}
s+=strlen(argc[i]);
}
*(c+s)='\0';
}
printf("%s\n", c);
item * kee= malloc(sizeof(item));
kee->k=c;
kee->v=10;
char *res= hash(*kee);
fflush(stdout);
if(res==NULL)
printf("result is null...");
else
printf("%s\n",res);
fflush(stdout);
}
So the main function takes the arguments fine(tested) and passes it fine(tested) but the hash() function although computing the hash, does not either return the right value or I can't print the result in main. I've been trying to check for errors since yesterday but I'm not very smart so any help would be greatly appreciated!
Root cause: You are returning something that has been created on the stack and once it returns it is wiped. res is pointing into your stack.
Fix: Put the declaration of md5str outside the routine hash or make it static within the routine hash.
Hi hello in C program i am trying to Encryption AES 128 with ECB mode on fedora OS
But i am getting Segmentation fault (core dumped)
i am request to you, kindly help me.
thank you in Advance :-)
before running program
plz save aes.h, aes.c you will find at AES zip
you have to run programlike
gcc main.c aes.c
data is
{"RequestUniqueID":"987654321","MethodName":"DstGenerateSessionID"}
Segmentation fault (core dumped)
i hope you will find my fault in code
My program is
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "aes.h"
#define min(a,b) (((a)<(b))?(a):(b))
unsigned char *aes128_func(unsigned char *in, unsigned char *aes_key, char type, unsigned int *len)
{
unsigned char ptext[KEY_128]={0},ctext[KEY_128]={0},*out=NULL;
unsigned char *temp_in=NULL,*temp_out=NULL;
aes_ctx_t *ctx = NULL;
if(!in || !len || !(aes_key && (strlen(aes_key) < 17))) return NULL;
init_aes();
if(!(ctx = aes_alloc_ctx(aes_key, KEY_128))) {
return NULL;
}
memset(ctx, 0, sizeof(*ctx));
*len = *len + ( (*len % 16) ? (16 - (*len % 16)): 0);
if(!(out =(char *)malloc(sizeof(*len+1))))
{
aes_free_ctx(ctx);
return NULL;
}
memset(out,0,*len+1);
temp_in=in;
temp_out=out;
do{
memset(ptext, 0, sizeof(ptext));
memset(ctext, 0, sizeof(ctext));
if(type==0){
memcpy(ptext, temp_in, min(sizeof(ptext),strlen(temp_in)));
aes_encrypt(ctx, ptext, ctext);
}else{
memcpy(ptext, temp_in, sizeof(ptext));
aes_decrypt(ctx, ptext, ctext);
}
memcpy(temp_out,ctext,KEY_128);
}while(((temp_in += KEY_128) < in+*len) && ((temp_out += KEY_128) < out+*len));
if(ctx) aes_free_ctx(ctx);
if(type==1) *len=strlen(out);
printf ("\nout aes %s\n",out);
return out;
}
unsigned char *process_post_data(unsigned char *in, unsigned char *aes_key, char type, unsigned int *ret_len)
{
unsigned char *step1_buf=NULL, *step2_buf=NULL;
unsigned int len=0;
printf ("at process_post_data \nin=%s\t aes_key=%s\t type=%s\t ret_len=%u\n", in, aes_key, type, ret_len);
if(!in || !aes_key) return NULL;
len = strlen(in);
if(type == 0)
{
if(!(step1_buf = aes128_func(in, aes_key, type, &len)))
return NULL;
printf ("\naes enc data is \"%s\" \n",step1_buf);
}
}
int main(int argc, char *argv[])
{
unsigned int ret_len;
char *data=NULL, *processed_data=NULL, *post_data=NULL;
data="{\"RequestUniqueID\":\"987654321\",\"MethodName\":\"DstGenerateSessionID\"}";
printf ("data is \t %s\n ",data);
if(!(processed_data = process_post_data(data,"1848519011345614",0,&ret_len)))
{
printf ("sorry something worng try again\n");
}
}
Hi finaly i have solved my issue & thank to you for trying to help me :-)
i have changed in code from if(!(out =(char *)malloc(sizeof(*len+1)))) to
if(!(out =malloc(*len+1)))
to print encrypted data we have to use like this after if(!(step1_buf = aes128_func(in, aes_key, type, &len)))
printf ("a4 aes en data is \n");
for(i=0;i<strlen(step1_buf);i++)
printf ("%02x",step1_buf[i]);
printf ("\n");
am trying to implement an application that uses an MD5 hash underneath, i have acquired the MD5 hash program from the internet, but i don't know how to pass the string from my program ( my program written in C) to the program that calculate the MD5 hash.
this is the main of the program that calculate the MD5 hash..
//
// MD5 Hashing Example - Using Windows Crypto API
//
// by Napalm # NetCore2K
//
#include <stdio.h>
#include <string.h>
#include "winmd5.h"
HCRYPTPROV hCryptProv;
int main(int argc, char *argv[])
{
int i;
CryptStartup();
if(argc > 1){
MD5Context ctx;
MD5Init(&ctx);
MD5Update(&ctx, (unsigned char *)argv[1], strlen(argv[1]));
MD5Final(&ctx);
for(i = 0; i < 16; i++)
printf("%02x", ctx.digest[i]);
printf("\n");
}else
printf("Usage: %s <string>\n", argv[0]);
CryptCleanup();
return 0;
}
this is the header file content..
//
// MD5 Hashing Example - Using Windows Crypto API
//
// by Napalm # NetCore2K
//
#include <windows.h>
#include <wincrypt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern HCRYPTPROV hCryptProv;
void PrintMD5(const char *);
typedef struct {
unsigned char digest[16];
unsigned long hHash;
} MD5Context;
BOOL CryptStartup()
{
if(CryptAcquireContext(&hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET) == 0){
if(GetLastError() == NTE_EXISTS){
if(CryptAcquireContext(&hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0) == 0){
return FALSE;
}
}
else return FALSE;
}
return TRUE;
}
void CryptCleanup()
{
if(hCryptProv) CryptReleaseContext(hCryptProv, 0);
hCryptProv = NULL;
}
void inline MD5Init(MD5Context *ctx)
{
CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &ctx->hHash);
}
void inline MD5Update(MD5Context *ctx, unsigned char const *buf, unsigned len)
{
CryptHashData(ctx->hHash, buf, len, 0);
}
void inline MD5Final(MD5Context *ctx)
{
DWORD dwCount = 16;
CryptGetHashParam(ctx->hHash, HP_HASHVAL, ctx->digest, &dwCount, 0);
if(ctx->hHash) CryptDestroyHash(ctx->hHash);
ctx->hHash = 0;
}
void PrintMD5(const char *s)
{
MD5Context ctx;
MD5Init(&ctx);
MD5Update(&ctx, (const unsigned char *)s, strlen(s));
MD5Final(&ctx);
int i;
for (i = 0; i < 16; i++) {
printf("%02x", ctx.hHash[i]);
}
printf("\n");
}
how should i call this Main(), and how to pass the String to it and get the result.?
thanks in advance.
Regards
You don't call main() again. You rather use this program as an example to write a separate function, like this:
void PrintMD5(const char *s)
{
MD5Context ctx;
MD5Init(&ctx);
MD5Update(&ctx, (const unsigned char *)s, strlen(s));
MD5Final(&ctx);
int i;
for (i = 0; i < 16; i++) {
printf("%02x", ctx.digest[i]);
}
printf("\n");
}
Then you can call this from your own program like:
PrintMD5("FooBarHelloWorld42");