Related
I am working on a project in C to implement CBC mode on top of a skeleton code for DES with OpenSSL. We are not allowed to use a function that does the CBC mode automatically, in the sense that we must implement it ourselves. I am getting output but I have result files and my output is not matching up completely with the intended results. I also am stuck on figuring out how to pad the file to ensure all the blocks are of equal size, which is probably one of the reasons why I'm not receiving the correct output. Any help would be appreciated. Here's my modification of the skeleton code so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/des.h>
#include <sys/time.h>
#include <unistd.h>
#define ENC 1
#define DEC 0
DES_key_schedule key;
int append(char*s, size_t size, char c) {
if(strlen(s) + 1 >= size) {
return 1;
}
int len = strlen(s);
s[len] = c;
s[len+1] = '\0';
return 0;
}
int getSize (char * s) {
char * t;
for (t = s; *t != '\0'; t++)
;
return t - s;
}
void strToHex(const_DES_cblock input, unsigned char *output) {
int arSize = 8;
unsigned int byte;
for(int i=0; i<arSize; i++) {
if(sscanf(input, "%2x", &byte) != 1) {
break;
}
output[i] = byte;
input += 2;
}
}
void doBitwiseXor(DES_LONG *xorValue, DES_LONG* data, const_DES_cblock roundOutput) {
DES_LONG temp[2];
memcpy(temp, roundOutput, 8*sizeof(unsigned char));
for(int i=0; i<2; i++) {
xorValue[i] = temp[i] ^ data[i];
}
}
void doCBCenc(DES_LONG *data, const_DES_cblock roundOutput, FILE *outFile) {
DES_LONG in[2];
doBitwiseXor(in, data, roundOutput);
DES_encrypt1(in,&key,ENC);
printf("ENCRYPTED\n");
printvalueOfDES_LONG(in);
printf("%s","\n");
fwrite(in, 8, 1, outFile);
memcpy(roundOutput, in, 2*sizeof(DES_LONG));
}
int main(int argc, char** argv)
{
const_DES_cblock cbc_key = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};
const_DES_cblock IV = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};
// Initialize the timing function
struct timeval start, end;
gettimeofday(&start, NULL);
int l;
if ((l = DES_set_key_checked(&cbc_key,&key)) != 0)
printf("\nkey error\n");
FILE *inpFile;
FILE *outFile;
inpFile = fopen("test.txt", "r");
outFile = fopen("test_results.txt", "wb");
if(inpFile && outFile) {
unsigned char ch;
// A char array that will hold all 8 ch values.
// each ch value is appended to this.
unsigned char eight_bits[8];
// counter for the loop that ensures that only 8 chars are done at a time.
int count = 0;
while(!feof(inpFile)) {
// read in a character
ch = fgetc(inpFile);
// print the character
printf("%c",ch);
// append the character to eight_bits
append(eight_bits,1,ch);
// increment the count so that we only go to 8.
count++;
const_DES_cblock roundOutput;
// When count gets to 8
if(count == 8) {
// for formatting
printf("%s","\n");
// Encrypt the eight characters and store them back in the char array.
//DES_encrypt1(eight_bits,&key,ENC);
doCBCenc(eight_bits, roundOutput, outFile);
// prints out the encrypted string
int k;
for(k = 0; k < getSize(eight_bits); k++){
printf("%c", eight_bits[k]);
}
// Sets count back to 0 so that we can do another 8 characters.
count = 0;
// so we just do the first 8. When everything works REMOVE THE BREAK.
//break;
}
}
} else {
printf("Error in opening file\n");
}
fclose(inpFile);
fclose(outFile);
// End the timing
gettimeofday(&end, NULL);
// Initialize seconds and micros to hold values for the time output
long seconds = (end.tv_sec - start.tv_sec);
long micros = ((seconds * 1000000) + end.tv_usec) - (start.tv_usec);
// Output the time
printf("The elapsed time is %d seconds and %d microseconds\n", seconds, micros);
}
Your crypto is at least half correct, but you have a lot of actual or potential other errors.
As you identified, raw CBC mode can only encrypt data which is a multiple of the block size, for DES 64 bits or 8 bytes (on most modern computers and all where you could use OpenSSL). In some applications this is okay; for example if the data is (always) an MD5 or SHA-256 or SHA-512 hash, or a GUID, or an IPv6 (binary) address, then it is a block multiple. But most applications want to handle at least any length in bytes, so they need to use some scheme to pad on encrypt and unpad on decrypt the last block (all blocks before the last already have the correct size). Many different schemes have been developed for this, so you need to know which to use. I assume this is a school assignment (since no real customer would set such a stupid and wasteful combination of requirements) and this should either have been specified or clearly left as a choice. One padding scheme very common today (although not for single-DES, because that is broken, unsafe, obsolete, and not common) is the one defined by PKCS5 and generalized by PKCS7 and variously called PKCS5, PKCS7, or PKCS5/7 padding, so I used that as an example.
Other than that:
you try to test feof(inpFile) before doing fgetc(inpFile). This doesn't work in C. It results in your code treating the low 8 bits of EOF (255 aka 0xFF on practically all implementations) as a valid data character added to the characters that were actually in the file. The common idiom is to store the return of getchar/getc/fgetc in a signed int and compare to EOF, but that would have required more changes so I used an alternate.
you don't initialize eight_bits which is a local-scope automatic duration variable, so its contents are undefined and depending on the implementation are often garbage, which means trying to 'append' to it by using strlen() to look for the end won't work right and might even crash. Although on some implementations at least some times it might happen to contain zero bytes, and 'work'. In addition it is possible in C for a byte read from a file (and stored here) to be \0 which will also make this work wrong, although if this file contains text, as its name suggests, it probably doesn't contain any \0 bytes.
once you fill eight_bits you write 'off-the-end' into element [8] which doesn't exist. Technically this is Undefined Behavior and anything at all can happen, traditionally expressed on Usenet as nasal demons. Plus after main finishes the first block it doesn't change anything in eight_bits so all further calls to append find it full and discard the new character.
while you could fix the above points separately, a much simple solution is available: you are already using count to count the number of bytes in the current block, so just use it as the subscript.
roundOutput is also an uninitialized local/auto variable within the loop, which is then used as the previous block for the CBC step, possibly with garbage or wrong value(s). And you don't use the IV at all, as is needed. You should allocate this before the loop (so it retains its value through all iterations) and initialize it to the IV, and then for each block in the loop your doCBCenc can properly XOR it to the new block and then leave the encrypted new block to be used next time.
your code labelled 'prints out the encrypted string' prints plaintext not ciphertext -- which is binary and shouldn't be printed directly anyway -- and is not needed because your file-read loop already echoes each character read. But if you do want to print a (validly null-terminated) string it's easier to just use fputs(s) or [f]printf([f,]"%s",s) or even fwrite(s,1,strlen(s),f).
your doCBCenc has a reference to printvalueofDES_LONG which isn't defined anywhere, and which along with two surrounding printf is clearly not needed.
you should use a cast to convert the first argument to doCBCenc -- this isn't strictly required but is good style and a good compiler (like mine) complains if you don't
finally, when an error occurs you usually print a message but then continue running, which will never work right and may produce symptoms that disguise the problem and make it hard to fix.
The below code fixes the above except that last (which would have been more work for less benefit) plus I removed routines that are now superfluous, and the timing code which is just silly: Unix already has builtin tools to measure and display process time more easily and reliably than writing code. Code I 'removed' is under #if 0 for reference, and code I added under #else or #if 1 except for the cast. The logic for PKCS5/7 padding is under #if MAYBE so it can be either selected or not. Some consider it better style to use sizeof(DES_block) or define a macro instead of the magic 8's, but I didn't bother -- especially since it would have required changes that aren't really necessary.
// SO70209636
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/des.h>
#include <sys/time.h>
#include <unistd.h>
#define ENC 1
#define DEC 0
DES_key_schedule key;
#if 0
int append(char*s, size_t size, char c) {
if(strlen(s) + 1 >= size) {
return 1;
}
int len = strlen(s);
s[len] = c;
s[len+1] = '\0';
return 0;
}
int getSize (char * s) {
char * t;
for (t = s; *t != '\0'; t++)
;
return t - s;
}
void strToHex(const_DES_cblock input, unsigned char *output) {
int arSize = 8;
unsigned int byte;
for(int i=0; i<arSize; i++) {
if(sscanf(input, "%2x", &byte) != 1) {
break;
}
output[i] = byte;
input += 2;
}
}
#endif
void doBitwiseXor(DES_LONG *xorValue, DES_LONG* data, const_DES_cblock roundOutput) {
DES_LONG temp[2];
memcpy(temp, roundOutput, 8*sizeof(unsigned char));
for(int i=0; i<2; i++) {
xorValue[i] = temp[i] ^ data[i];
}
}
void doCBCenc(DES_LONG *data, const_DES_cblock roundOutput, FILE *outFile) {
DES_LONG in[2];
doBitwiseXor(in, data, roundOutput);
DES_encrypt1(in,&key,ENC);
#if 0
printf("ENCRYPTED\n");
printvalueOfDES_LONG(in);
printf("%s","\n");
#endif
fwrite(in, 8, 1, outFile);
memcpy(roundOutput, in, 2*sizeof(DES_LONG));
}
int main(int argc, char** argv)
{
const_DES_cblock cbc_key = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};
const_DES_cblock IV = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};
#if 0
// Initialize the timing function
struct timeval start, end;
gettimeofday(&start, NULL);
#endif
int l;
if ((l = DES_set_key_checked(&cbc_key,&key)) != 0)
printf("\nkey error\n");
#if 1
DES_cblock roundOutput; // must be outside the loop
memcpy (roundOutput, IV, 8); // and initialized
#endif
FILE *inpFile;
FILE *outFile;
inpFile = fopen("test.txt", "r");
outFile = fopen("test.encrypt", "wb");
if(inpFile && outFile) {
unsigned char ch;
// A char array that will hold all 8 ch values.
// each ch value is appended to this.
unsigned char eight_bits[8];
// counter for the loop that ensures that only 8 chars are done at a time.
int count = 0;
#if 0
while(!feof(inpFile)) {
// read in a character
ch = fgetc(inpFile);
#else
while( ch = fgetc(inpFile), !feof(inpFile) ){
#endif
// print the character
printf("%c",ch);
#if 0
// append the character to eight_bits
append(eight_bits,1,ch);
// increment the count so that we only go to 8.
count++;
#else
eight_bits[count++] = ch;
#endif
#if 0
const_DES_cblock roundOutput;
#endif
// When count gets to 8
if(count == 8) {
// for formatting
printf("%s","\n");
// Encrypt the eight characters and store them back in the char array.
//DES_encrypt1(eight_bits,&key,ENC);
doCBCenc((DES_LONG*)eight_bits, roundOutput, outFile);
#if 0
// prints out the encrypted string
int k;
for(k = 0; k < getSize(eight_bits); k++){
printf("%c", eight_bits[k]);
}
#endif
// Sets count back to 0 so that we can do another 8 characters.
count = 0;
// so we just do the first 8. When everything works REMOVE THE BREAK.
//break;
}
}
#if MAYBE
memset (eight_bits+count, 8-count, 8-count); // PKCS5/7 padding
doCBCenc((DES_LONG*)eight_bits, roundOutput, outFile);
#endif
} else {
printf("Error in opening file\n");
}
fclose(inpFile);
fclose(outFile);
#if 0
// End the timing
gettimeofday(&end, NULL);
// Initialize seconds and micros to hold values for the time output
long seconds = (end.tv_sec - start.tv_sec);
long micros = ((seconds * 1000000) + end.tv_usec) - (start.tv_usec);
// Output the time
printf("The elapsed time is %d seconds and %d microseconds\n", seconds, micros);
#endif
}
PS: personally I wouldn't put the fwrite in doCBCenc; I would only do the encryption and let the caller do whatever I/O is appropriate which might in some cases not be fwrite. But what you have is not wrong for the requirements you apparently have.
i use this part of code to read float value from OSC message on my microcontroller. However i get "dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]" error and no value is showed on printf. Is there any workaround for this one? marker is in struct as:
char *marker; // the current read head
float tosc_getNextFloat(tosc_message *o) {
// convert from big-endian (network btye order)
const uint32_t i = ntohl(*((uint32_t *) o->marker));
o->marker += 4;
return *((float *) (&i)); <---- this line of code does the error
}
EDIT :
So, i recieve data from microcontrollers internet chip over udp using function:
datasize_t recvfrom(uint8_t sn, uint8_t * buf, datasize_t len, uint8_t * addr, uint16_t *port, uint8_t *addrlen) //<- general
then i run another function to parse osc message:
tosc_parseMessage(&A, (char*) buf, received_size); //<- how i wrote parameters
where A is structure:
typedef struct tosc_message {
char *format; // a pointer to the format field
char *marker; // the current read head
char *buffer; // the original message data (also points to the address)
uint32_t len; // length of the buffer data
} tosc_message;
and tosc_parseMessage is:
int tosc_parseMessage(tosc_message *o, char *buffer, const int len) {
// NOTE(mhroth): if there's a comma in the address, that's weird
int i = 0;
while (buffer[i] != '\0') ++i; // find the null-terimated address
while (buffer[i] != ',') ++i; // find the comma which starts the format string
if (i >= len) return -1; // error while looking for format string
// format string is null terminated
o->format = buffer + i + 1; // format starts after comma
while (i < len && buffer[i] != '\0') ++i;
if (i == len) return -2; // format string not null terminated
i = (i + 4) & ~0x3; // advance to the next multiple of 4 after trailing '\0'
o->marker = buffer + i;
o->buffer = buffer;
o->len = len;
return 0;
}
and then i print that out with :
void tosc_printMessage(tosc_message *osc) {
printf("[%i bytes] %s %s",
osc->len, // the number of bytes in the OSC message
tosc_getAddress(osc), // the OSC address string, e.g. "/button1"
tosc_getFormat(osc)); // the OSC format string, e.g. "f"
for (int i = 0; osc->format[i] != '\0'; i++) {
switch (osc->format[i]) {
case 'f': printf(" %g", tosc_getNextFloat(osc)); break;
case 'd': printf(" %g", tosc_getNextDouble(osc)); break;
case 'i': printf(" %d", tosc_getNextInt32(osc)); break;
default: printf(" Unknown format: '%c'", osc->format[i]); break;
}
}
printf("\n");
}
where my problem is in function:
float tosc_getNextFloat(tosc_message *o) {
// convert from big-endian (network btye order)
const uint32_t i = ntohl(*((uint32_t *) o->marker));
o->marker += 4;
return *((float *) (&i)); <---- this line of code does the error
}
I hope this gives you better view on problem... Im not skilled programmer so i appreciate any help. Full code for this "library" could be found here https://github.com/mhroth/tinyosc , Im just trying to implement that in my microcontroller
float tosc_getNextFloat(tosc_message *o) {
// convert from big-endian (network btye order)
const uint32_t i = ntohl(*((uint32_t *) o->marker));
o->marker += 4;
float tmp = 0;
memcpy((void *)&tmp, (void *)&i, sizeof(uint32_t));
return tmp;
}
If type punning is required, it is better to use a compiler that is configured to support it (which on some non-commercially-designed compilers, but not commercially-designed ones, means using -fno-strict-aliasing) than to jump through hoops to accommodate compiler writers that refuse to recognize type punning via pointers that are visibly freshly derived.
C implementations are sometimes used for purposes where type punning is useful, and sometimes for purposes where it isn't. The authors of the Standard recognized that compiler writers should know more about their individual customers' needs than the Committee possibly could, and thus allowed implementations to support whatever combinations of constructs would best fit their customers' needs. Somehow a myth has emerged that Standard characterizes as "broken" programs which relies upon implementations to process them "In a documented fashion characteristic of the environment", but any such reading directly contradicts the stated intentions of the Standard's authors.
After all it wasnt code problem. Yes, i still get that warning ( BUT CODE WORKS ). Actual problem was in IDE. In linker setting inside builder settings this was needed to be added : -u _printf_float . That took like month of my life figuring out what's happening. Thank you all for answering
Good afternoon, I'm having an issue today where I'm creating a device driver, where I can get it to read the dice_read function perfectly, but when I try to use dice_write, it seems like it doesn't do anything at all. I've even added printk's to try to Troubleshoot and it seems like it never gets there anyways. not quite sure why. I'm just trying to use the line "echo -ne \x8\x4 > /dev/dice" and it's supposed to take the byte with "4" and put it in an int. I've added my dice_write below. Thanks! (sides is a global variable)
static ssize_t dice_write(struct file * file, const char * buf,
size_t count, loff_t *ppos)
{
char *data = kmalloc(sizeof(buf), GFP_KERNEL);
copy_from_user(data, &buf, count);
int i = sizeof(data);
sides = 0;
char digit = data[i - 1];
if(digit >= '0' && digit <= '9'){
sides = digit - '0';
}
kfree(data);
return count;
}
I am using following api to initialize sockfd at client side:(sockfd=3)
if ((sockfd = socket(p->ai_family, p->ai_socktype,p->ai_protocol)) == -1) {
perror("client: socket");
continue;
}
& initializing my TPKT_Buff to {3,0,0,0} value by using function :
if(Fill_TPKT(PStack,TPKT_Buff) != 0)
{
printf("Error while filling TPKT Buffer");
return 1;
}printf("tpkt/2_Buff%x %x\n",TPKT_Buff[0],TPKT_Buff[1]);printf("sockfd=%d\n",sockfd);
But, after calling function :
if(Fill_COTP(PStack,&cotp) != 0)
{
printf("Error while filling COTP Structure!");
return 1;
}
my socfd & TPKT_Buff values changed to zero TPKT_Buff={0,0,0,0} & sockfd=0 :
printf("sockfd=%d\n",sockfd);
printf("TPKT/2_Buff=%x %x\n",TPKT_Buff[0],TPKT_Buff[1]);
Definitions of functions Fill_COTP & Fill_TPKT are as follows :
int Fill_TPKT(FILE *fptr,unsigned char *buf)
{
fseek(fptr,14,SEEK_SET);
fscanf(fptr,"%d",buf+0);
fseek(fptr,15,SEEK_CUR);
fscanf(fptr,"%d",buf+1);
return 0;
}
int Fill_COTP(FILE *fptr, COTP *cotp)
{
unsigned short temp;
fseek(fptr,13,SEEK_CUR);
fscanf(fptr,"%d",&temp);
cotp->Destination_Ref[1] = temp;
cotp->Destination_Ref[0] = temp>>8;
printf("%x %x\n",cotp->Destination_Ref[0],cotp->Destination_Ref[1]);
fseek(fptr,13,SEEK_CUR);
fscanf(fptr,"%d",&temp);
cotp->Source_Ref[1] = temp;
cotp->Source_Ref[0] = temp>>8;
printf("%x %x\n",cotp->Source_Ref[0],cotp->Source_Ref[1]);
fseek(fptr,14,SEEK_CUR);
fscanf(fptr,"%d",&temp);
cotp->Source_Tsap[1] = temp;
cotp->Source_Tsap[0] = temp>>8;
printf("%x %x\n",cotp->Source_Tsap[0],cotp->Source_Tsap[1]);
fseek(fptr,14,SEEK_CUR);
fscanf(fptr,"%d",&temp);
cotp->Destination_Tsap[1] = temp;
cotp->Destination_Tsap[0] = temp>>8;
printf("%x %x\n",cotp->Destination_Tsap[0],cotp->Destination_Tsap[1]);
fseek(fptr,17,SEEK_CUR);
fscanf(fptr,"%d",&(cotp->TPDU_size));
printf("%x\n",cotp->TPDU_size);
return 0;
}
Here PStack is a file pointer.
I am not getting why my sockfd & TPKT_Buff values changing to zero even I am not using these values in my function Fill_COTP();
Please give some suggestion.
Definition of COTP is:
typedef struct
{
unsigned char PDU_type;
unsigned char Destination_Ref[2];
unsigned char Source_Ref[2];
unsigned char Source_Tsap[2];
unsigned char Destination_Tsap[2];
unsigned char TPDU_size;
} COTP;
There is no relation between sockfd & TPKT_Buff.
The trouble appears to be in the line:
fscanf(fptr,"%d",&(cotp->TPDU_size));
Your TPCU_size is unsigned char TPDU_size; which is only 1 byte (assuming this to be the size of 'char') in size, but you are trying put 4 bytes (assuming that to be the size of 'int') into it during fscanf, thereby potentially overwriting the memory around it.
While there is some information missing, some of what you have shown is clearly wrong and is likely to be involved in the problem. For instance:
int Fill_TPKT(FILE *fptr,unsigned char *buf)
{
fseek(fptr,14,SEEK_SET);
fscanf(fptr,"%d",buf+0);
fseek(fptr,15,SEEK_CUR);
fscanf(fptr,"%d",buf+1);
If each call to fscanf works, each will fill in one int, but buf points to a sequence of unsigned chars. Unless you have very large chars and sizeof(int) == 1 this is obviously wrong.
The same mistake is repeated at many other points, e.g., in Fill_COTP, fscanf with a %d directive is used to fill in temp, which has type unsigned short rather than int.
You could change the directives (%hhd will fill in a single char and %hd will fill in a single short; %hhu and %hu will fill in unsigned char and unsigned short). However, simply calling fscanf like this, without any error checking, is not very robust. If the contents of the input stream are not convert-able to the target type, the call will fail (fscanf will return either EOF or a short count, depending on the kind of failure, "input" vs "matching", and the point of the failure). You might want a little intermediate function that does appropriate error checking, perhaps scanning into an int after all and then range-checking the value for instance.
Firstly, i'm not very familiarized with C, i come from Java, C#, C++... and possibly i inherited defects from this languages in order to realize this practice, well i have the follows question, here is my code:
#include <stdio.h>
#include <stdlib.h>
void decrypt(unsigned long* v, unsigned long* k);
const int MAX = 32;
const long delta = 0x9e3779b9;
long sum=0xC6EF3720;
int main() {
FILE *fp;
FILE *destino;
unsigned long v[2];
unsigned long k[4] = { 128, 129, 130, 131 };
unsigned long tam=0;
char* buffer;
char* aux[sizeof(unsigned long)];
int i;
if ((fp = fopen("image.png", "rb")) == NULL) {
printf ("Error! \n ");
return 0;
}
else {
fread(&aux,sizeof(unsigned long),1,fp);
memcpy(&tam,&aux,sizeof(unsigned long));
buffer = (char*)malloc(tam);
//fread(&buffer,1,tam,fp);
char *buffer2[28568];
fread(&buffer2,1,28568,fp);
/*for(i = 0;i < tam;++i) {
printf("%c", ((char *)buffer2)[i]);
}*/
for(i=4;i<tam;i+=8) {
memcpy(&v,&buffer2[i],8);
decrypt(&v,&k);
}
if ((result= fopen("image2.png", "rb")) == NULL) {
printf ("Error! \n ");
return 0;
}
else {
fwrite(v,sizeof(unsigned long)*2,1,result);
fclose (result);
fclose(fp);
}
}
return 0;
}
void decrypt(unsigned long* v, unsigned long* k) {
int i=0;
while(i<MAX) {
v[1] = v[1] -((4 << v[0])+(k[2]^v[0])+(sum^(5 >> v[0]))+k[3]);
v[0] = v[0] -((4 << v[1])+(k[0]^v[1])+(sum^(5 >> v[1]))+k[1]);
sum = sum-delta;
i++;
}
}
Where tam is the size of my binary file (image in this case) where i store first 4 bytes (unsigned long) where is located the size in my png file (28568)
When i create my char* buffer i have to assign dynamically with malloc but when i make a new fread from my file i get a "No source available for "msvrct!memcpy() at 0xrandom_memory_address" from Eclipse when i debug, well, i comment this line and i try to make it manually set a new buffer2 with 28568 as size of my array, apparently works, making a iteration of buffer2 prints ascii characters values but when i call decrypt for make the decryption of my image, the final result is stored in v array which i have to copy in a new file, i tried to search how to make a empty image png in C but i didn't find anything, so i created a copy of my encrypt image calling it "image2.png" but i suppose this not the "clean solution" for that, because for the other hand is not working at all.
For more explanation about this exercise just say that the decrypt funcion work with blocks of 8 bytes (64 bits) that through a key (array k) make a series of operation where they store in v array itself, crossing through the loop 8 in 8 and retrieve the value of buffer in v in each one, after the loop execution we have the result in v and only left to copy in a new file where finally show up the image decrypt.
It's a very complex practice for all of one newbies in C, it's driving my crazy trying to figure out what i doing wrong.
I hope anyone can see what i'm not able to for now.
I think you are having problems with the declarations of the buffers. I think the correct should be:
FILE *fp;
FILE *destino;
unsigned long v[2];
unsigned long k[4] = { 128, 129, 130, 131 };
unsigned long tam=0;
char* buffer;
char aux[sizeof(unsigned long)]; // without the "*"
int i;
if ((fp = fopen("image.png", "rb")) == NULL) {
printf ("Error! \n ");
return 0;
}
else {
fread(aux,sizeof(unsigned long),1,fp);
memcpy(&tam,aux,sizeof(unsigned long));
buffer = (char*)malloc(tam);
//fread(buffer,1,tam,fp); // without the "&" in this case
char buffer2[28568]; // without the "*"
fread(buffer2,1,28568,fp); // or fread(buffer,1,tam,fp);
/*for(i = 0;i < tam;++i) {
printf("%c", buffer2[i]); // or buufer[i] if you change to use it again
}*/
for(i=4;i<tam;i+=8) {
memcpy(v,&buffer2[i],8);
decrypt(v,k);
}
...
I don't fully understand what you are trying to accomplish, but one problem is here:
char* aux[sizeof(unsigned long)];
// ... some code ...
fread(&aux,sizeof(unsigned long),1,fp);
Understand that char* aux[sizeof(unsigned long)]; means that you are declaring a double pointer, but fread() prototype states that the destination is a single pointer:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
so what you should be doing instead is:
char aux[sizeof(unsigned long)];
// ... some code ...
fread(aux,sizeof(unsigned long),1,fp);
Don't complicate things that are not complicated!
You also do this mistake in other parts of your code, you need to re-check everything, ok? Again:
char *buffer2[28568];
fread(&buffer2,1,28568,fp);
should be:
char buffer2[28568];
fread(buffer2, 1, 28568, fp);
// or: fread(buffer2, 1, sizeof(buffer2), fp);
There are some interesting tutorials on pointers and arrays, I suggest you read some.