Error shows in receiver code for RC4 decryption

Hello,

I am trying to implement RC4 encryption in MCU [i.e. Arduino UNO]. I have set up 2 Xbee [radio] +2 Arduino for a small network where 1 Xbee+1 Arduino will work as transmitter [encrypts the data] and another set of Xbee +Arduino will receive the encrypted data and decrypt it. I tested a sketch on single arduino and it encrypts and decrypts a string fine.

  1. But when I try to put only encryption code in transmitter and decryption code in receiver I can not get any value in receiver end. Transmission code is almost as receiver code and works fine, so has not been shown.
  2. The code for decryption has some issues. I can not compile the code for receiver. It shows: "error: invalid conversion from 'int' to 'char*' " this error. I have tried many other ways too but everytime it shows some compiler error. The receiver’s code is as follows:
void setup() {
  Serial.begin(9600);
}

void loop(){
char key[] = "Hello";
char *enc=Serial.read();  //I want to set the encrypted data as "enc" so that I can work with it to decrypt it. I am facing problem during coding here
if(Serial.available()>0){
Serial.write(enc);   //I am facing problem during coding here
//Serial.println(Serial.read());

rc4(key,enc); //that calls the RC4 function again which works ok for encryption	
Serial.print("Decrypted : ");
Serial.println(has); //"has" is the output of the RC4 encryption function
delay(1000);
}
  
}

Could you please let me know how to define the encrypted data so that after getting the data receiver can decrypt it?

Thank you

char *enc=Serial.read();

Serial "read" returns an int, not a pointer to char.

Thank you. Is there any other way to define the 'received encrypted output' from transmitter as a char? Because my RC4 encryption function is defined as char and if I change as above to int the error shows as

  1. invalid conversion from 'int' to 'char*'
  2. error: initializing argument 2 of 'void rc4(char*, char*)'.

I am new in this environment with limited knowledge of programming. Your answer will be highly appreciated. RC4 function code:

unsigned char S[256];
char has[512];

#define S_SWAP(a,b) do { int t = S[a]; S[a] = S[b]; S[b] = t; } while(0)

  void rc4(char *key, char *data){
     int i,j;
     
     for (i=0;i<256;i++){
         S[i] = i;
     }

     j = 0;
     for (i=0;i<256;i++){
         j = (j+S[i]+key[i%strlen(key)]) %256;
         S_SWAP(S[i],S[j]);
     }
     i = j = 0;
     for (int k=0;k<strlen(data);k++){
         i = (i+1) %256;
         j = (j+S[i]) %256;
         S_SWAP(S[i],S[j]);
         has[k] = data[k]^S[(S[i]+S[j]) %256];
     }
     has[strlen(data)+1] = '\0';
}

Thanks in advance for the comment.

How about good, old fashionedchar enc=Serial.read();but as you are reading a character before you know there is anything to read, and will get only one character anyway, you need to restructure your code.

Wait until there is something to read
Read characters until you get to the end. You need to know that you have reached the end
Add the characters to an array as each is received

Now use the array

See http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=11425&page=1

char *enc=Serial.read();  //I want to set the encrypted data as "enc" so that I can work with it to decrypt it. I am facing problem during coding here
if(Serial.available()>0){
Serial.write(enc);   //I am facing problem during coding here

Apart from the pointer issue, you're reading a character before you've checked to see if there's one to read.
It isn't clear to me (perhaps because you didn't post the transmitter code) what constitutes a complete message, which the receiver would need to know, so that it could call "rc4()" just once for the complete message.

@AWOL: Here is the complete code for transmitter:

unsigned char S[256];
char has[512];

#define S_SWAP(a,b) do { int t = S[a]; S[a] = S[b]; S[b] = t; } while(0)

void rc4(char *key, char *data){
     int i,j;
              
     for (i=0;i<256;i++){
         S[i] = i;
              }
     j = 0;
     for (i=0;i<256;i++){
         j = (j+S[i]+key[i%strlen(key)]) %256;
         S_SWAP(S[i],S[j]);
         //printf("%x",S[i]);
     }
     
          i = j = 0;
     for (int k=0;k<strlen(data);k++){
         i = (i+1) %256;
         j = (j+S[i]) %256;
         S_SWAP(S[i],S[j]);
         has[k] = data[k]^S[(S[i]+S[j]) %256];
     }
     has[strlen(data)+1] = '\0';
     
     
}

void setup() {
  Serial.begin(9600);
  Serial.println( "Arduino started sending bytes via XBee" );
}

void loop(){
  
  char key[] = "Hello";
  char sdata[] = "this is data source!";
  rc4(key,sdata);
  Serial.print("Encrypted : ");
  Serial.println(has);
  
  delay(8000); 
  
}

complete code for receiver:

unsigned char S[256];
char has[512];

#define S_SWAP(a,b) do { int t = S[a]; S[a] = S[b]; S[b] = t; } while(0)

  void rc4(char *key, char *data){
     int i,j;
     
     for (i=0;i<256;i++){
         S[i] = i;
     }

     j = 0;
     for (i=0;i<256;i++){
         j = (j+S[i]+key[i%strlen(key)]) %256;
         S_SWAP(S[i],S[j]);
     }
     i = j = 0;
     for (int k=0;k<strlen(data);k++){
         i = (i+1) %256;
         j = (j+S[i]) %256;
         S_SWAP(S[i],S[j]);
         has[k] = data[k]^S[(S[i]+S[j]) %256];
     }
     has[strlen(data)+1] = '\0';
}

void loop(){
char key[] = "Hello";
char *enc=Serial.read();  //I want to set the encrypted data as "enc" so that I can work with it to decrypt it. I am facing problem during coding here
if(Serial.available()>0){
Serial.write(enc);   //I am facing problem during coding here
//Serial.println(Serial.read());

rc4(key,enc); //that calls the RC4 function again which works ok for encryption	
Serial.print("Decrypted : ");
Serial.println(has); //"has" is the output of the RC4 encryption function
delay(1000);
}
  
}

Thank you for your patience.

UKHeliBob:
How about good, old fashionedchar enc=Serial.read();but as you are reading a character before you know there is anything to read, and will get only one character anyway, you need to restructure your code.

Wait until there is something to read
Read characters until you get to the end. You need to know that you have reached the end
Add the characters to an array as each is received

Now use the array

See http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=11425&page=1

Thank you for your answer. I am checking your provided link at first. Thanks

Hi.

After reading the provided link I can understand why it is necessary to wait until something to read. I have tried with the provided code in my receiver but could not get the data as again. So I thought of start again from basic and try to develop from there. As a new comer to this Arduino and programming world I expect your co-operation. I have tried at first this RC4 code which is both encryption and decryption for arduino. And in PC it shows ok. The code is:

#include <string.h>

unsigned char S[256];
char has[512];

#define S_SWAP(a,b) do { int t = S[a]; S[a] = S[b]; S[b] = t; } while(0)

void rc4(char *key, char *data){
     int i,j;
     
     Serial.print("Source : ");
     Serial.println(data);
     Serial.print("Key : ");
     Serial.println(key);
          
     for (i=0;i<256;i++){
         S[i] = i;
         //printf("%x",S[i]);
     }
     
     //printf("\n");

     j = 0;
     for (i=0;i<256;i++){
         j = (j+S[i]+key[i%strlen(key)]) %256;
         S_SWAP(S[i],S[j]);
         //printf("%x",S[i]);
     }
     
     //printf("\n");
     i = j = 0;
     for (int k=0;k<strlen(data);k++){
         i = (i+1) %256;
         j = (j+S[i]) %256;
         S_SWAP(S[i],S[j]);
         has[k] = data[k]^S[(S[i]+S[j]) %256];
     }
     has[strlen(data)+1] = '\0';
     
     //printf("\n");

}

void setup() {
  Serial.begin(9600);
  char key[] = "Hello";
  char sdata[] = "this is data source!";
  rc4(key,sdata);
  Serial.print("Encrypted : ");
  Serial.println(has);
  rc4(key,has);
  Serial.print("Decrypted : ");
  Serial.println(has);
  
}

void loop(){
  
}

After implementing it on one PC I wanted to at least transfer this whole output to my another Xbee+Arduino receiver. So I tried with very basic receiver code:

void setup() {
Serial.begin(9600);
}

void loop(){
if(Serial.available()>0){
Serial.write(Serial.read());
  }

}

But here I found an interesting problem that the receiver only can capture one line at a time and shows that particular line only if I disable other Serial.print lines [but even if I enable only decryption it does not show the decrypted value in receiver]. It never shows anything at all if I try to show all the 4-5 lines [enabling all the Serial.print lines]. I think the problem is for error in my receiver code.

My query now is to know what modification I should make in my receiver code so that receiver can show all the output (4-5 lines) in my PC.

I hope this big explanation does not make you bored and uninterested. I hope I will get some good input to start off this job from the scratch step by step.

Thank you

the receiver only can capture one line at a time

that's simply because the serial monitor only sends a line at a time. A proper terminal emulator like Putty would send a character at a time.

AWOL:
that's simply because the serial monitor only sends a line at a time. A proper terminal emulator like Putty would send a character at a time.

Thank you for your comment. I checked with PuTTY as well but it shows the same output as my serial monitor terminal of arduino IDE. Why is it ignoring

Serial.print("Source : ");
     Serial.println(data);
     Serial.print("Key : ");
     Serial.println(key);

and only showing

void loop(){
 Serial.println( "Encrypted : " );

though they both are using Serial.println? How can I show all the Serial.println in my receiver end's serial monitor as per my sketch? Is it about buffer limit [0 to 123]?

Thank you in advance for taking time to answer my question, I really do appreciate it.

The RC4 code shouldn't be using strlen() since valid encrypted strings will contain null bytes,
strlen assumes a null byte terminates the string. You need to pass in a length count as well as the
char* pointer to the routine.

Also what are you trying to achieve - encryption without authentication isnt normally useful.

MarkT:
The RC4 code shouldn't be using strlen() since valid encrypted strings will contain null bytes,
strlen assumes a null byte terminates the string. You need to pass in a length count as well as the
char* pointer to the routine.

Also what are you trying to achieve - encryption without authentication isnt normally useful.

Thank you. The encryption I am applying will be changed with authentication after I will be able to implement what I am doing now. Thank you for your suggestion. What should my receiver code so that it can accept all the lines from transmitter?

Start by changing:

void rc4(char *key, char *data){

to

void rc4(char *key, int keylen, char *data, int datalen){

And using the length parameters instead of calls to strlen(). Change the calls to rc4 to provide explicit lengths,
you'll have to ensure the lengths are knowable (are you sending fixed packet size for instance?).

BTW RC4 is no longer considered secure - you know this?

MarkT:
Start by changing:
BTW RC4 is no longer considered secure - you know this?

Thank you for the comment.

:slight_smile: Yes I know that it is no longer considered as secure. Actually my intention is to implement a custom made security in the WSN communication environment. So, to implement this I am trying to go step by step from scratch. I would try this once I will be able to communicate my sensor data encrypted from one radio to another with simple encryption like RC4. But I really do appreciate your concern and suggestion. This forum is really very helpful..thank YOU!

MarkT:
Start by changing:

void rc4(char *key, char *data){

to

void rc4(char *key, int keylen, char *data, int datalen){

And using the length parameters instead of calls to strlen(). Change the calls to rc4 to provide explicit lengths,
you'll have to ensure the lengths are knowable (are you sending fixed packet size for instance?).

Hi Mark, I have changed it to what you said with receiver code as before. But still it is showing nothing. But I can see in terminal the encrypted and decrypted code in transmitter side. Could you please let me know what can be done to get the output just in my receiver end? The problem is: if I disable the decryption option in transmitter code the receiver shows only encrypted data. But if I want to show the decrypted data [suppose i even disabled the encrypted data option in my transmitter code] still it does not show that. Do you want me to paste here my transmitter and receiver code?