-2

Following is a program in lazarus to perform RC4 encryption and decryption when given a string. When the compiler directive {$mode fpc} is used and the string 123 is entered it crashes with External: SIGSEGV. However there is no crash when inputting the same string in {$mode objfpc}. Another inconsistency is that in {$mode objfpc} the program raises the exception External: SIGSEGV again with the input of hellow.

//{$mode fpc}
{$mode objfpc}
program project1;
uses
  sysutils, strutils;
type
  myArray = array[0..255] of integer;
  dynamicArray = array of integer;
  dynamicArrayString = array of string;
const
  key = 'qwertyui';
var
  plaintext : string;

function KSA(const key: string): myArray;
var
  i, j, key_length, temp: integer;
  S : myArray;
begin
  key_length := length(key);
  j := 0;
  for i := Low(S) to High(S) do
    S[i] := i;
  for i := Low(S) to High(S) do
  begin
    j := ((j + S[i] + ord(key[i mod key_length + 1])) mod 256);
    temp := S[i];
    S[i] := S[j];
    S[j] := temp;
  end;
  KSA := S;
end;

function PRGA(S : myArray; n : integer) : dynamicArray;
var
  i, j, K, temp, sizeOfArray : integer;
  key : dynamicArray;
begin
  i := 0;
  j := 0;
  K := 0;
  temp := 0;
  sizeOfArray := n - 1;
  SetLength(key, sizeOfArray);
  while n > 0 do
  begin
    n := n - 1;
    i := (i + 1) mod 256;
    j := (j + S[i]) mod 256;
    temp := S[i];
    S[i] := S[j];
    S[j] := temp;
    K := S[(S[i] + S[j]) mod 256];
    key[i-1] := K;
  end;
  PRGA := key;
end;

procedure getPlaintext;
begin
  readln(plaintext);
end;

function encrypt : string;
var
  sizeOfArray, i : integer;
  cipherString : string;
  cipher, keystream: dynamicArray;
  S : myArray;
begin
  S := KSA(key);
  keystream := PRGA(S, length(plaintext));
  sizeOfArray := 0;
  for i := 0 to (length(plaintext) - 1) do
  begin
    sizeOfArray := sizeOfArray + 1;
    SetLength(cipher, sizeOfArray);
    cipher[i] := (keystream[i]) xor (ord(plaintext[i + 1]));
  end;
  cipherString := '';
  for i := 0 to High(cipher) do
    cipherString := cipherString + IntToHex(cipher[I], 2);
  encrypt := cipherString;
end;

function stringToHex(cipherString : string) : dynamicArrayString;
var
  sizeOfArray, i: integer;
  DecryptArrayString : dynamicArrayString;
begin
  sizeOfArray := 0;
  i := 0;
  // Turn the string into an array of hex
  while length(cipherString) > 0 do
  begin
    sizeOfArray := sizeOfArray + 1;
    SetLength(DecryptArrayString, sizeOfArray);
    DecryptArrayString[i] := cipherString[1] + cipherString[2];
    i := i + 1;
    cipherString := rightstr(cipherString, length(cipherString) - 2);
  end;
  stringToHex :=  DecryptArrayString;
end;

function hexToDecimal(DecryptArrayString : dynamicArrayString) : dynamicArray;
var
  sizeOfDecryptArrayInt, i : integer;
  DecryptArrayInt : dynamicArray;
begin
  sizeOfDecryptArrayInt := 0;
  // Hex to decimal
  for i := 0 to high(DecryptArrayString) do
  begin
    sizeOfDecryptArrayInt := sizeOfDecryptArrayInt + 1;
    SetLength(DecryptArrayInt, sizeOfDecryptArrayInt);
    DecryptArrayInt[i] := Hex2Dec(DecryptArrayString[i]);
  end;
  hexToDecimal := DecryptArrayInt;
end;

function decrypt(DecryptArrayInt : dynamicArray) : string;
var
  DecryptedString : string;
  S : myArray;
  keystream, Decrypted : dynamicArray;
  sizeOfArray, i : integer;
begin
  sizeOfArray := 0;
  for i := 0 to high(DecryptArrayInt) do
  begin
    sizeOfArray := sizeOfArray + 1;
    SetLength(Decrypted, sizeOfArray);
    S := KSA(key);
    keystream := PRGA(S, length(plaintext));
    Decrypted[i] := (keystream[i] xor DecryptArrayInt[i]);
  end;
  decryptedString := '';
  // Turn array to string
  for i := 0 to high(Decrypted) do
    decryptedString := decryptedString + chr(Decrypted[i]);
  decrypt := decryptedString;
end;

procedure encryptDecrypt;
var
  cipherString, DecryptedString : string;
  DecryptArrayString : dynamicArrayString;
  DecryptArrayInt : dynamicArray;
begin
  cipherString := encrypt;
  writeln(cipherString);
  DecryptArrayString := stringToHex(cipherString);
  DecryptArrayInt := hexToDecimal(DecryptArrayString);
  DecryptedString := decrypt(DecryptArrayInt);
  writeln(DecryptedString);
end;

begin
  getPlaintext;
  encryptDecrypt;
  readln;
end.

I've not been able to find the many specific cases that makes the program crash apart from a string of any three characters will always crash in {$mode fpc} but not in {$mode objfpc}

HabibC
  • 19
  • 5
  • 1
    Well, you've got your screen right in front of you so why not tell us the exact line on which the crash occurs? What does the call stack tell you is executing at the exact point the crask occurs? Meanwhile -1. – MartynA Dec 01 '18 at 16:42
  • To find what is going wrong, you could try to debug your code. It should not be too hard to find out where things go wrong. – Rudy Velthuis Dec 01 '18 at 17:37
  • You seem to have more on-off errors (index one too low or too high). Why don't you draw these things on paper and give each element a number, e.g. a string is 1, 2, ... i + 1 and a dynamic array is 0, 1, ... i etc. Also: **DEBUG DEBUG DEBUG**. It is a very important skill. Learn it. You will need it a lot. And **draw diagrams** like I do here: http://rvelthuis.de/articles/articles-pointers.html#references. – Rudy Velthuis Dec 03 '18 at 16:29
  • I meant' one-off errors", i.e. where your indexes are off by one. – Rudy Velthuis Dec 03 '18 at 16:36

1 Answers1

1

You should debug (and watch) your code so any error can be traced more easily. Use the FP IDE, it helps a lot.

Meanwhile, watch this line:

keystream := PRGA(S, length(plaintext));

And inside the PRGA function watch these lines:

sizeOfArray := n - 1;
SetLength(key, sizeOfArray);

What's wrong here? Well, suppose "plaintext" has only 1 character. So, "Length(plaintext)"=1, right? In PRGA you do "sizeOfArray:= n-1;", so sizeOfArray = 0. When you do SetLength, "Key" will be NIL because you're indicating a zero indexes length. Later, on loop, you have:

key[i-1] := K;

the program will fail because you are accessing at index 0 and the Key variable is NIL.

Careful: On "SetLength(key, sizeOfArray);" valid indexes for key are in range [0..sizeOfArray-1], but sizeOfArray must be at least 1 to be valid (sizeOfArray >= 1).

So, you should check your PRGA function. It's up to you to find the definitive solution. Don't give up. Good luck!

  • He already aksed questions about this program of his. He keeps on having one-off errors (often in the wrong direction too), because he has problems reconciling 1-based strings and 0-based dynamic arrays. He should learn to debug. – Rudy Velthuis Dec 03 '18 at 15:38