C RC4 super weird behavior - c

so I found the implementation of RC4 in pure C, which I was using on my website. It was working super good except when I input a 6 characters string. Then I get the Internal Error Page. Figured out that only this length causes a problem.
1.Crypt.c
unsigned char S[256];
unsigned int i, j;
void swap(unsigned char *s, unsigned int i, unsigned int j) {
unsigned char temp = s[i];
s[i] = s[j];
s[j] = temp;
}
/* KSA */
void rc4_init(unsigned char *key, unsigned int key_length) {
for (i = 0; i < 256; i++)
S[i] = i;
for (i = j = 0; i < 256; i++) {
j = (j + key[i % key_length] + S[i]) & 255;
swap(S, i, j);
}
i = j = 0;
}
/* PRGA */
unsigned char rc4_output() {
i = (i + 1) & 255;
j = (j + S[i]) & 255;
swap(S, i, j);
return S[(S[i] + S[j]) & 255];
}
char *rc4_e(char *text, size_t text_length)
{
char *dup=(char *)malloc(text_length * sizeof(char));
strcpy(dup,text);
unsigned char *vector[2] = {"key", dup};
int y;
rc4_init(vector[0], strlen((char*)vector[0]));
char *out=(char *)malloc(text_length * sizeof(char) );
char *ptr=out;
for (y = 0; y < strlen((char*)vector[1]); y++)
ptr += sprintf(ptr,"%02X",vector[1][y] ^ rc4_output());
*(ptr + 1) = '\0';
return out;
}
2.Main
#define SIZE 1000
char* pass=(char*)malloc(SIZE * sizeof(char));
char *RC4_pass=(char*)malloc(getSize(pass) * sizeof(char));
strcpy(RC4_pass,rc4_e(pass,sizeof(pass)));
Any advice or thoughts are extremely welcome. Just want to know whether it is the function itself that is bad or the rest of my C code.
Thank!

There is a problem with this line:
char *dup=(char *)malloc(text_length * sizeof(char));
You forgot to add an extra byte for the terminating '\0' at the end of the string. So at the very next line:
strcpy(dup,text);
you're committing an out-of-bounds access in the array dup, which is causing undefined behaviour.

Related

Why does the array contain values which I did not specify?

I'm trying to make a program which crosses binary numbers. The problem is with the cross function. It accepts two binary sequences and returns 5 sequences which are the result of crossing the arguments. Somewhy, the first of these sequences has a mess of values, and I cannot really solve this problem. Does anyone have any ideas?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define BINARY_LEN 5
#define POPULATION 5
// #define CROSS_BINARY_LIMIT 3
unsigned randrange(unsigned lower, unsigned upper)
{
return lower + rand() / (RAND_MAX / (upper - lower + 1) + 1);
}
unsigned char *int_to_bin(unsigned number)
{
unsigned char *binary = malloc(BINARY_LEN);
unsigned count = 0;
while (number > 0)
{
binary[count] = number % 2;
number /= 2;
count++;
}
return binary;
}
unsigned char **cross(unsigned char *parent_1, unsigned char *parent_2)
{
unsigned char **offspring = malloc(POPULATION);
unsigned cross_binary_point;
for (unsigned char i = 0; i < POPULATION; i++)
{
cross_binary_point = randrange(0, BINARY_LEN);
offspring[i] = malloc(BINARY_LEN);
for (unsigned char j = 0; j < BINARY_LEN; j++)
{
if (j < cross_binary_point)
{
offspring[i][j] = parent_1[j];
}
else
{
offspring[i][j] = parent_2[j];
}
}
}
return offspring;
}
int main(void)
{
unsigned char *x = int_to_bin(14);
unsigned char *y = int_to_bin(18);
for (unsigned char i = BINARY_LEN; i > 0; i--)
{
printf("%hhu", x[i - 1]);
}
printf("\n");
for (unsigned char i = BINARY_LEN; i > 0; i--)
{
printf("%hhu", y[i - 1]);
}
printf("\n\n");
unsigned char **ofspr = cross(x, y);
printf("%s\n", ofspr[0]); // Try to check out what's wrong with the first array
for (unsigned char i = 0; i < POPULATION; i++)
{
for (unsigned char j = BINARY_LEN; j > 0; j--)
{
printf("%hhu", ofspr[i][j]);
}
printf("\n");
}
free(ofspr);
free(x);
free(y);
}
The output is like this:
01110
10010
`w;
00059119
01011
01001
01111
01011
Maybe there is some memory conflict stuff, but I do not have any ideas
unsigned char **offspring = malloc(POPULATION);
only allocates 5 bytes, you want 5 pointers
should be
unsigned char **offspring = malloc(POPULATION * sizeof(char*));

c; converting 2 bytes to short and vice versa

I want to convert array of bytes bytes1 (little endian), 2 by 2, into an array of short integers, and vice versa . I expect to get final array bytes2, equal to initial array bytes1. I have code like this:
int i = 0;
int j = 0;
char *bytes1;
char *bytes2;
short *short_ints;
bytes1 = (char *) malloc( 2048 );
bytes2 = (char *) malloc( 2048 );
short_ints = (short *) malloc( 2048 );
for ( i=0; i<2048; i+=2)
{
short_ints[j] = bytes1[i+1] << 8 | bytes1[i] ;
j++;
}
j = 0;
for ( i=0; i<2048; i+=2)
{
bytes2[i+1] = (short_ints[j] >> 8) & 0xff;
bytes2[i] = (short_ints[j]) ;
j++;
}
j = 0;
Now, can someone tell me why I haven't got bytes2 array, completely the same as bytes1 ? And how to do this properly?
Suggest 2 functions. Do all combining and extraction as unsigned to remove issues with the sign bit in short and maybe char.
The sign bit is OP's code biggest problem. short_ints[j] = bytes1[i+1] << 8 | bytes1[i] ; likely does a sign extend with bytes1[i] conversion to int.
Also (short_ints[j] >> 8) does a sign extend.
// Combine every 2 char (little endian) into 1 short
void charpair_short(short *dest, const char *src, size_t n) {
const unsigned char *usrc = (const unsigned char *) src;
unsigned short *udest = (unsigned short *) dest;
if (n % 2) Handle_OddError();
n /= 2;
while (n-- > 0) {
*udest = *usrc++;
*udest += *usrc++ * 256u;
udest++;
}
}
// Break every short into 2 char (little endian)
void short_charpair(char *dest, const short *src, size_t n) {
const unsigned short *usrc = (const unsigned short *) src;
unsigned char *udest = (unsigned char *) dest;
if (n % 2) Handle_OddError();
n /= 2;
while (n-- > 0) {
*udest++ = (unsigned char) (*usrc);
*udest++ = (unsigned char) (*usrc / 256u);
usrc++;
}
}
int main(void) {
size_t n = 2048; // size_t rather than int has advantages for array index
// Suggest code style: type *var = malloc(sizeof(*var) * N);
// No casting of return
// Use sizeof() with target pointer name rather than target type.
char *bytes1 = malloc(sizeof * bytes1 * n);
Initialize(bytes, n); //TBD code for OP-best to not work w/uninitialized data
// short_ints = (short *) malloc( 2048 );
// This is weak as `sizeof(short)!=2` is possible
short *short_ints = malloc(sizeof * short_ints * n/2);
charpair_short(short_ints, bytes1, n);
char *bytes2 = malloc(sizeof * bytes2 * n);
short_charpair(bytes2, short_ints, n);
compare(bytes1, bytes2, n); // TBD code for OP
// epilogue
free(bytes1);
free(short_ints);
free(bytes2);
return 0;
}
Avoided the union approach as that is platform endian dependent.
Here's a program that demonstrates that you are experiencing the problem associated with bit-shifting signed integral values.
#include <stdio.h>
#include <stdlib.h>
void testCore(char bytes1[],
char bytes2[],
short short_ints[],
int size)
{
int i = 0;
int j = 0;
for ( i=0; i<size; i+=2)
{
short_ints[j] = bytes1[i+1] << 8 | bytes1[i] ;
j++;
}
j = 0;
for ( i=0; i<size; i+=2)
{
bytes2[i+1] = (short_ints[j] >> 8) & 0xff;
bytes2[i] = (short_ints[j]) ;
j++;
}
for ( i=0; i<size; ++i)
{
if ( bytes1[i] != bytes2[i] )
{
printf("%d-th element is not equal\n", i);
}
}
}
void test1()
{
char bytes1[4] = {-10, 0, 0, 0};
char bytes2[4];
short short_ints[2];
testCore(bytes1, bytes2, short_ints, 4);
}
void test2()
{
char bytes1[4] = {10, 0, 0, 0};
char bytes2[4];
short short_ints[2];
testCore(bytes1, bytes2, short_ints, 4);
}
int main()
{
printf("Calling test1 ...\n");
test1();
printf("Done\n");
printf("Calling test2 ...\n");
test2();
printf("Done\n");
return 0;
}
Output of the program:
Calling test1 ...
1-th element is not equal
Done
Calling test2 ...
Done
Udate
Here's a version of testCore that works for me:
void testCore(char bytes1[],
char bytes2[],
short short_ints[],
int size)
{
int i = 0;
int j = 0;
unsigned char c1;
unsigned char c2;
unsigned short s;
for ( i=0; i<size; i+=2)
{
c1 = bytes1[i];
c2 = bytes1[i+1];
short_ints[j] = (c2 << 8) | c1;
j++;
}
j = 0;
for ( i=0; i<size; i+=2)
{
s = short_ints[j];
s = s >> 8;
bytes2[i+1] = s;
bytes2[i] = short_ints[j] & 0xff;
j++;
}
for ( i=0; i<size; ++i)
{
if ( bytes1[i] != bytes2[i] )
{
printf("%d-th element is not equal\n", i);
}
}
}
It is tested with:
char bytes1[4] = {-10, 0, 25, -4};
and
char bytes1[4] = {10, -2, 25, 4};
Well, what you need is a UNION:
#include <stdio.h>
#include <string.h>
union MyShort {
short short_value;
struct {
char byte1;
char byte2;
};
};
int main(int argc, const char * argv[])
{
char a[4]="abcd";
char b[4]="1234";
short c[5]; c[4]=0;
union MyShort d;
for (int i = 0; i<4; i++) {
d.byte1 = a[i];
d.byte2 = b[i];
c[i] = d.short_value;
}//next i
printf("%s\n", (char*)c);
return 0;
}
the result should be a1b2c3d4.

Quick shifting chars of string

I have a string This is a text and I want to shift it to the left.
So, when I want it to shift for 2 positions, it should result in is is a textTh.
For some reason, I can't quite get there.
void rotLeft(char *s, unsigned int n)
{
char *t = malloc(sizeof(char) * n);
int i;
int ti = 0;
for(i = 0; i < n; i+=1)
{
t[ti] = s[i];
ti +=1;
}
// + n should remove the n first chars?
strcat(s + n, t);
}
You just need a temp variable, this rotates ONCE. n is the length of the string.
void rotLeft(char *s, int n)
{
char temp;
int i;
temp = s[0];
for(i = 0; i < n-1; i++)
{
s[i] = s[i+1];
}
s[n-1]=temp;
}
void rotLeft(char *s, unsigned int n)
{
char *t;
int l;
l = strlen(s);
t = (char *)malloc(n);
strncpy (t,s,n);
strncpy (s,s+n,l-n);
strncpy (s+l-n,t,n);
free (t);
}
Just be carefull and not try to rotate more than the length of the string. Argument values are not checked against errors.
I would suggest constructing a new rotated string, not rotate the existing string in-place.
char *rotLeft(char *s, int n)
{
char * t = malloc((strlen(s) + 1) * sizeof(char))
strncpy(t, s + n, strlen(s) - n);
strncpy(t + strlen(s) - n, s, n);
s[strlen(s)] = '\0';
return t;
}
Here is the classic trick for rotating a string in-place without using temporary storage (aside from a single character). (A production version should check that the rotation amount is not too big.)
void reverse(char* s, size_t lo, size_t hi) {
while(lo < hi) {
char t = s[lo];
s[lo++] = s[--hi];
s[hi] = t;
}
}
void rotate_left(char* s, size_t n) {
size_t len = strlen(s);
reverse(s, 0, n);
reverse(s, n, len);
reverse(s, 0, len);
}

Why this C programming can not run crrectly?

It's just a sample test that I want to unite the list Lb and La without repeat element. It didn't work, and returned -1073741510, I think maybe the array overflow, but I can't find where the problem is
This is my code:
#include <stdio.h>
void Union(char *La, char *Lb);
int ListLength(char *L);
void GetElem(char *L, int i, char *e);
int LocateElem(char *L, char *e, int (*comp)(char a, char b));
int compare(char a, char b);
void ListInsert(char *, int, char *);
int main(){
char *La;
char *Lb;
int i;
for(i = 0; i <= 10; ++i){
La[i] = i;
Lb[i] = i + 5;
}
La[i] = '\0';
Lb[i] = '\0';
Union(La, Lb);
for(i = 0; La[i] != '\0'; ++i){
printf("%c\n", La[i]);
}
return 0;
}
//unite La and Lb without repeat elements
void Union(char *La, char *Lb){
int La_length = ListLength(La);
int Lb_length = ListLength(Lb);
int i = 0;
char *e;
for(i; i<= Lb_length; ++i){
GetElem(Lb, i, e);
if(!LocateElem(La, e, compare))
ListInsert(La, ++La_length, e);
}
}
//caculate the length of L
int ListLength(char *L){
int i;
for(i = 0; *(L + i) != '\0'; ++i);
return i;
}
void GetElem(char *L, int i, char *e){
*e = *(L + i);
}
//search the element e in L, if exist return the location, else return 0
int LocateElem(char *L, char *e, int (*comp)(char a, char b)){
int i;
for(i = 0; *(L + i) != '\0'; ++i){
if(comp(*(L + i), *e)) return i + 1;
}
return 0;
}
//compare the element a and b
int compare(char a, char b){
if(a == b) return 1;
return 0;
}
//if e doesn't exit in L, insert the e in L
void ListInsert(char *L, int i, char *e){
int j;
for(j = ListLength(L) - 1; j >= i; --j){
*(L + j + 1) = *(L + j);
}
L[ListLength(L)] = '\0';
*(L + i - 2) = *e;
}
First, this is wrong:
char *La;
char *Lb;
int i;
for(i = 0; i <= 10; ++i){
La[i] = i;
Lb[i] = i + 5;
}
You need to reserve memory for La and Lb, for instance, by declaring them as:
char La[12];
char Lb[12];
An then this:
char *e;
for(i; i<= Lb_length; ++i){
GetElem(Lb, i, e);
should read:
char e;
for(; i<= Lb_length; ++i){
GetElem(Lb, i, &e); /* better yet: e=Lb[i] */
Finally, you're most likely looping one time too many by using <= instead of < as the for exit condition.
You have several issues. I think you need to read more about what are raw pointers, fixed length arrays, variable length arras and dynamic arrays. If you need your array to grow you can make it dynamic with malloc and realloc. Alternatively you can use a "big" array you know never will overflow.
int La[12]; // 0 to 10, plus '\0'
But this is fixed and cannt grow. You could use
int La[1000]; // if it solve yours problems
But in general you will need dynamic arrays.
Also, you need to deside if your array can hold 0 or it is used as terminator. '\0' and 0, in the form you use it are equal. Many of your for cycle dont run because the first elemnt is 0.

How to split an array in c?

I need a logic to acheive my target. I've buffer array size of 38400. This array data can be filled by a controller. Here i have to obtain an AES algorithm. In that i've to read 16 bytes of data from the buffer then encrypt, upto end of buffer. How to spilt an array into 16 bytes and encrypt? . I used following logic but i can't get it right now ?
unsigned char ptext[16] = "Attack at dawn!";
unsigned char ctext[16];
unsigned char decptext[16];
unsigned char buffer[120*160*2];
for (int count = 0; count < 120*160*2; count ++)
buffer[count] = count + 1;
for (i = 0; i < 120*160*2; i ++)
{
ptext[i]= buffer[i];
if(i%15 == 0)
{
aes_encrypt(ctx, ptext, ctext);
for(k = 0; k<=i; k++)
{
ptext[k]='\0';
}
}
}
void aes_encrypt(aes_ctx_t *ctx, unsigned char input[16], unsigned char output[16])
{
int i;
// copy input to state
for(i = 0; i < 16; i++)
ctx->state[i & 0x03][i >> 2] = input[i];
aes_addroundkey(ctx, 0);
for(i = 1; i < ctx->rounds; i++) {
aes_subbytes(ctx);
aes_shiftrows(ctx);
aes_mixcolumns(ctx);
aes_addroundkey(ctx, i);
}
aes_subbytes(ctx);
aes_shiftrows(ctx);
aes_addroundkey(ctx, ctx->rounds);
// copy state to output
for(i = 0; i < 16; i++)
{
output[i] = ctx->state[i & 0x03][i >> 2];
printf("%c",output[i]);
}
}
Note: I've filled buffer[] with random numbers.
Me only have to know how to split an array.
Thanks in Advance.
You don't need to "split" the array (whatever "split" means for you.) Just operate on every 16-byte segment of it:
void process_segment(unsigned char segment[])
{
// Work on the first 16 bytes of 'segment'.
}
// ...
unsigned char buffer[120*160*2];
for (size_t i = 0; i < 120*160*2; i += 16) {
process_segment(buffer + i);
}
The above is just an example. If you want a nested for loop instead, you'd do something like this:
unsigned char buffer[120*160*2];
for (size_t i = 0; i < 120*160*2; i += 16) {
unsigned char* segment = buffer + i;
// Work on the first 16 bytes of 'segment'.
for (size_t j = 0; j < 16; ++j) {
// Work on segment[j].
}
}
You should probably change your aes_encrypt() function to take an unsigned char input[] instead of an unsigned char input[16] so that you can pass segment to it.
The code you posted would then become something like this:
unsigned char ptext[16] = "Attack at dawn!";
unsigned char ctext[16];
unsigned char decptext[16];
unsigned char buffer[120*160*2];
for (int count = 0; count < 120*160*2; count++)
buffer[count] = count + 1;
for (i = 0; i < 120*160*2; i += 16) {
unsigned char *segment = buffer + i;
aes_encrypt(ctx, segment, ctext);
// Clear the current 16-byte segment.
memset(segment, '\0', 16);
// ctext now contains the encrypted data of the current
// 16-byte segment. I assume you want to save it somewhere
// now since it will be overridden in the next iteration of
// the loop.
}
And the signature of your aes_encrypt() function would become:
void aes_encrypt(aes_ctx_t *ctx, unsigned char input[],
unsigned char output[16])

Resources