1

I need encrypt string in XE6 Firemonkey project.

I tried dcpcrypt but Firemonkey doesn't support AnciString, .....

I found a solution that works in Firemonkey. My problem is converting this code to PHP.

DELPHI DEMO PROJECT : Link

DELPHI CODE :

const 
  Codes64 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/';

function GeneratePWDSecutityString: string;
var 
  i, x: integer;
  s1, s2: string;
begin
  s1 := Codes64;
  s2 := '';
  for i := 0 to 15 do
  begin
    x  := Random(Length(s1));
    x  := Length(s1) - x;
    s2 := s2 + s1[x];
    s1 := Copy(s1, 1,x - 1) + Copy(s1, x + 1,Length(s1));
  end;
  Result := s2;
end;

function MakeRNDString(Chars: string; Count: Integer): string;
var 
  i, x: integer;
begin
  Result := '';
  for i := 0 to Count - 1 do
  begin
    x := Length(chars) - Random(Length(chars));
    Result := Result + chars[x];
    chars := Copy(chars, 1,x - 1) + Copy(chars, x + 1,Length(chars));
  end;
end;

function EncodePWDEx(Data, SecurityString: string; MinV: Integer = 0;
  MaxV: Integer = 5): string;
var 
  i, x: integer;
  s1, s2, ss: string;
begin
  if minV > MaxV then 
  begin 
    i := minv;
    minv := maxv; 
    maxv := i; 
  end;
  if MinV < 0 then MinV := 0;
  if MaxV > 100 then MaxV := 100;
  Result := '';
  if Length(SecurityString) < 16 then Exit;
  for i := 1 to Length(SecurityString) do
  begin
    s1 := Copy(SecurityString, i + 1,Length(securitystring));
    if Pos(SecurityString[i], s1) > 0 then Exit;
    if Pos(SecurityString[i], Codes64) <= 0 then Exit;
  end;
  s1 := Codes64;
  s2 := '';
  for i := 1 to Length(SecurityString) do
  begin
    x := Pos(SecurityString[i], s1);
    if x > 0 then s1 := Copy(s1, 1,x - 1) + Copy(s1, x + 1,Length(s1));
  end;
  ss := securitystring;
  for i := 1 to Length(Data) do
  begin
    s2 := s2 + ss[Ord(Data[i]) mod 16 + 1];
    ss := Copy(ss, Length(ss), 1) + Copy(ss, 1,Length(ss) - 1);
    s2 := s2 + ss[Ord(Data[i]) div 16 + 1];
    ss := Copy(ss, Length(ss), 1) + Copy(ss, 1,Length(ss) - 1);
  end;
  Result := MakeRNDString(s1, Random(MaxV - MinV) + minV + 1);
  for i := 1 to Length(s2) do Result := Result + s2[i] + MakeRNDString(s1,
      Random(MaxV - MinV) + minV);
end;


function DecodePWDEx(Data, SecurityString: string): string;
var 
  i, x, x2: integer;
  s1, s2, ss: string;
begin
  Result := #1;
  if Length(SecurityString) < 16 then Exit;
  for i := 1 to Length(SecurityString) do
  begin
    s1 := Copy(SecurityString, i + 1,Length(securitystring));
    if Pos(SecurityString[i], s1) > 0 then Exit;
    if Pos(SecurityString[i], Codes64) <= 0 then Exit;
  end;
  s1 := Codes64;
  s2 := '';
  ss := securitystring;
  for i := 1 to Length(Data) do if Pos(Data[i], ss) > 0 then s2 := s2 + Data[i];
  Data := s2;
  s2   := '';
  if Length(Data) mod 2 <> 0 then Exit;
  for i := 0 to Length(Data) div 2 - 1 do
  begin
    x := Pos(Data[i * 2 + 1], ss) - 1;
    if x < 0 then Exit;
    ss := Copy(ss, Length(ss), 1) + Copy(ss, 1,Length(ss) - 1);
    x2 := Pos(Data[i * 2 + 2], ss) - 1;
    if x2 < 0 then Exit;
    x  := x + x2 * 16;
    s2 := s2 + chr(x);
    ss := Copy(ss, Length(ss), 1) + Copy(ss, 1,Length(ss) - 1);
  end;
  Result := s2;
end;

And this is my PHP code ;

function INDEX($CHAR) {
    $Codes64 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
    return strpos($Codes64, $CHAR) + 1;
}
function MakeRNDString($Chars, $Count) {
    $i = 0;
    $x = 0;
    $Result = '';
    for ($i = 0; $i < $Count; $i++) {
        $x = strlen($Chars) - rand(0, intval(strlen($Chars)));
        $Result .= substr($Chars,$x,1);     
        $chars = substr($Chars, 1, $x - 1) + substr($Chars, $x + 1, strlen($Chars));
    }
    return $Result;
}

function DIV($N, $D) {
    return (integer)($N / $D);
}
function EncodePWDEx($Data, $SecurityString, $minV = 0, $maxV = 5) {
    $Codes64 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
    $i = 0;
    $x = 0;
    $s1 = '';
    $s2 = '';
    $ss = '';
    if ($minV > $maxV) {
        $i = $minv;
        $minv = $maxv;
        $maxv = $i;
    }
    if ($maxV < 0) {
        $minV = 0;
    };
    if ($maxV > 100) {
        $maxV = 100;
    };
    if (strlen($SecurityString) < 16)
        Exit ;
    for ($i = 0; $i < strlen($SecurityString) - 1; $i++) {
        $s1 = substr($SecurityString, $i + 1, strlen($SecurityString));
        if (strpos($s1, $SecurityString[$i]) > 0)
            Exit ;
        if (INDEX($SecurityString[$i]) <= 0)
            Exit ;
    }
    $s1 = $Codes64;
    $s2 = '';
    for ($i = 0; $i < strlen($SecurityString); $i++) {
        $vx = INDEX($SecurityString[$i]);
        if ($vx > 0) {
            $s1 = substr($s1, 1, $vx - 1) . substr($s1, $vx + 1, strlen($s1));
        }
    }
    $ss = $SecurityString;
    for ($i = 0; $i < strlen($Data); $i++) {
        $FM = fmod(ord($Data[$i]), 16);
        $CH = substr($ss, $FM, 1);
        $s2 = $s2 . $CH;
        $ss = substr($ss, strlen($ss) - 1, 1) . substr($ss, 0, strlen($ss) - 1);
        $tmp = substr($ss, DIV(ord($Data[$i]), 16), 1);
        $s2 = $s2 . substr($ss, DIV(ord($Data[$i]), 16), 1);
        $ss = substr($ss, strlen($ss) - 1, 1) . substr($ss, 0, strlen($ss) - 1);
    }   
    $MRN = MakeRNDString($s1, (rand(1, $maxV - $minV) + intval($minV)));
    $Result = '';
    $Result = $MRN;
    for ($i = 0; $i < strlen($s2); $i++) {
        $Result .= substr($s2,$i,1) . MakeRNDString($s1, rand(0, $maxV - $minV) + intval($minV)  );
    }
    return $Result;
}

function DecodePWDEx($Data, $SecurityString){
    $Codes64 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
    $Result = '';
    if (strlen($SecurityString) < 16)
        Exit;

    for ($i = 0; $i < strlen($SecurityString) - 1; $i++) {
        $s1 = substr($SecurityString, $i + 1, strlen($SecurityString));
        if (strpos($s1, $SecurityString[i]) > 0 )
            Exit;
        if (strpos($Codes64, $SecurityString[i]) <= 0) 
            Exit;
    }
    $s1 = $Codes64;
    $s2 = '';
    $ss = $SecurityString;


    for ($i = 0; $i < strlen($Data); $i++) {
        if (strpos($ss, substr($Data,$i,1)) > 0)
            $s2 = $s2 + substr($Data,$i,1);
    }
    $Data = $s2;
    $s2 = '';

    /*
    if strlen($Data) mod 2 <> 0 then
        Exit;
    */
    $x = -1;
    for ($i = 0; $i < (DIV(Length($Data), 2)); $i++) {
        $x = strpos($ss,substr($Data, (i * 2),1)) - 1;

        if ($x < 0)
            Exit;

        $ss = substr($ss, strlen($ss), 1) + substr($ss, 1, strlen($ss) - 1);
        $x2 = -1;
        $x2 = strpos(substr($Dat,($i * 2 + 2), 1), $ss) - 1;
        if ($x2 < 0) 
          Exit;
        $x = $x + $x2 * 16;
        $s2 .= chr(x);
        $ss = substr($ss, strlen($ss), 1) + substr($ss, 1, strlen($ss));
    }
  $Result = $s2;
  return $Result;
}

$e1 = "test";
$e2 = "0/nCXpmMP2iFvJ3G";
echo '<br />Text : ' . $e1;
echo '<br />Pass : ' . $e2;
echo '<br />EncodePWDEx : <b>' . EncodePWDEx($e1, $e2).'</b>';
1
  • 1
    As I have said so many times before, encryption operates on binary data. Encrypt and decrypt TBytes, byte arrays. Encode and decode binary to/from text using TEncoding.GetString and TEncoding.GetBytes. Commented Sep 11, 2014 at 15:10

1 Answer 1

1

The implementation of the code in php is not quite right.

ENCODE

    if (strpos($s1, $SecurityString[$i]) > 0)

The php function strpos may well 0 return. To test whether a character found in another string you should use === true or === false.

    if (strpos($s1, $SecurityString[$i]) === true) Exit;
    if (strpos($Codes64, $SecurityString[$i]) === false) Exit;

NOT

    if (strpos($s1, $SecurityString[$i]) > 0) Exit;
    if (INDEX($SecurityString[$i]) <= 0) Exit;

The INDEX() function is wrong.

function INDEX($CHAR) {
  ...
  return strpos($Codes64, $CHAR) + 1;
}

may return false + 1 !!!
you test the return value with

if (INDEX($SecurityString[$i]) <= 0) Exit;

will never be <= 0 !!

Part of Code Delphi OK :

for i := 1 to Length(SecurityString) do
 begin
  s1 := Copy(SecurityString, i + 1,Length(securitystring));
  if Pos(SecurityString[i], s1) > 0 then Exit;
  if Pos(SecurityString[i], Codes64) <= 0 then Exit;
 end;

Part of wrong Code Php:

 for ($i = 0; $i < strlen($SecurityString) - 1; $i++) {
    $s1 = substr($SecurityString, $i + 1, strlen($SecurityString));
    if (strpos($s1, $SecurityString[$i]) > 0)
        Exit ;
    if (INDEX($SecurityString[$i]) <= 0)
        Exit ;
}

With Delphi OK

  s1 := Codes64;
  s2 := '';
  for i := 1 to Length(SecurityString) do
  begin
    x := Pos(SecurityString[i], s1);
    if x > 0 then s1 := Copy(s1, 1,x - 1) + Copy(s1, x + 1,Length(s1));
  end;

Php code wrong

 for ($i = 0; $i < strlen($SecurityString); $i++) {
    $vx = INDEX($SecurityString[$i]);
    if ($vx > 0) { // $vx will always > 0
        $s1 = substr($s1, 1, $vx - 1) . substr($s1, $vx + 1, strlen($s1));
    }
 }

Look at

        $s1 = substr($s1, 1, $vx - 1) . substr($s1, $vx + 1, strlen($s1));

The substr() function use 1 as starting point should use 0.
Otherwise are always two characters deleted not just one.

$s1 = substr($s1, 1, $vx - 1)

will give us an empty substring : $s1 = substr($s1, 1, 0);

now $s1 == ''

more errors

  • The INDEX() function use the never changing string $Codes64
  • while the substr() function uses the ever shrinking $s1 string.
  • (DIV(Length($Data)
    (DIV(strlen($Data)
  • substr($Data, (i * 2)
    substr($Data, ($i * 2)
  • $ss = substr($ss, strlen($ss), 1) + substr($ss, 1, strlen($ss) - 1);
    $ss = substr($ss, strlen($ss)-1, 1) . substr($ss, 0, strlen($ss) - 1);
  • $s2 .= chr(x);
    $s2 .= chr($x);

    $SecurityString == '0/nCXpmMP2iFvJ3G'

Have a look at the next $SecurityString Char. It is / this is the last character in the string $Codes64 .

with

$vx = INDEX($SecurityString[$i]);

we get the Char / at position 63 + 1 == 64
now $vx == 64

$vx value is behind length($Codes64) [0..63]
after deleting the first two chars 01 from $s1 the Char / is at position 62 so $vx that's also behind length($s1)


working Php code

EncodePWDEx
replace

if (strlen($SecurityString) < 16)
        Exit ;
    for ($i = 0; $i < strlen($SecurityString) - 1; $i++) {
        $s1 = substr($SecurityString, $i + 1, strlen($SecurityString));
        if (strpos($s1, $SecurityString[$i]) > 0)
            Exit ;
        if (INDEX($SecurityString[$i]) <= 0)
            Exit ;
    }
    $s1 = $Codes64;
    $s2 = '';
    for ($i = 0; $i < strlen($SecurityString); $i++) {
        $vx = INDEX($SecurityString[$i]);
        if ($vx > 0) {
            $s1 = substr($s1, 1, $vx - 1) . substr($s1, $vx + 1, strlen($s1));
        }
    }

with

if (strlen($SecurityString) < 16)
        Exit ;
    for ($i = 0; $i < strlen($SecurityString) - 1; $i++) {
        $s1 = substr($SecurityString, $i + 1);
        if (strpos($s1, $SecurityString[$i]) !== FALSE )
            Exit;
        if (strpos($Codes64, $SecurityString[$i]) === FALSE) 
            Exit;
    }
    $s1 = $Codes64;
    $s2 = '';
    for ($i = 0; $i < strlen($SecurityString); $i++) {
        $vx = strpos($s1,$SecurityString[$i]);
        if ($vx !== false) {
            $s1 = substr_replace ( $s1, '' , $vx , 1 );
        }
    }

MakeRNDString replace

    $Result .= substr($Chars,$x,1);     
    $chars = substr($Chars, 1, $x - 1) + substr($Chars, $x + 1, strlen($Chars));

with

    $Result .= substr($Chars,$x,1);     
    $Chars = substr($Chars, 0, $x - 1) . substr($Chars, $x + 1);

DECODE

DecodePWDEx replace

for ($i = 0; $i < strlen($SecurityString) - 1; $i++) {
        $s1 = substr($SecurityString, $i + 1, strlen($SecurityString));
        if (strpos($s1, $SecurityString[i]) > 0 )
            Exit;
        if (strpos($Codes64, $SecurityString[i]) <= 0) 
            Exit;
    }
    $s1 = $Codes64;
    $s2 = '';
    $ss = $SecurityString;


    for ($i = 0; $i < strlen($Data); $i++) {
        if (strpos($ss, substr($Data,$i,1)) > 0)
            $s2 = $s2 + substr($Data,$i,1);
    }
    $Data = $s2;
    $s2 = '';

    /*
    if strlen($Data) mod 2 <> 0 then
        Exit;
    */
    $x = -1;
    for ($i = 0; $i < (DIV(Length($Data), 2)); $i++) {
        $x = strpos($ss,substr($Data, (i * 2),1)) - 1;

        if ($x < 0)
            Exit;

        $ss = substr($ss, strlen($ss), 1) + substr($ss, 1, strlen($ss) - 1);
        $x2 = -1;
        $x2 = strpos(substr($Dat,($i * 2 + 2), 1), $ss) - 1;
        if ($x2 < 0) 
          Exit;
        $x = $x + $x2 * 16;
        $s2 .= chr(x);
        $ss = substr($ss, strlen($ss), 1) + substr($ss, 1, strlen($ss));
    }
  $Result = $s2;
  return $Result;
}

with

for ($i = 0; $i < strlen($SecurityString) - 1; $i++) {
        $s1 = substr($SecurityString, $i + 1);
        if (strpos($s1, $SecurityString[$i]) !== FALSE )
            Exit;
        if (strpos($Codes64, $SecurityString[$i]) === FALSE) 
            Exit;
    }

    $s2 = '';
    $ss = $SecurityString;
    for ($i = 0; $i < strlen($Data); $i++) {
        $fd = substr($Data,$i,1);
        $vx = strpos($ss,$fd);
        if ($vx !== false) {
            $s2 .= $fd;
        }
    }
    $Data = $s2;
    $s2 = '';
    for ($i = 0; $i < (DIV(strlen($Data), 2)); $i++) {
        $x = strpos($ss,substr($Data, ($i * 2),1));
        if ($x < 0)  Exit;
        $ss = substr($ss, strlen($ss)-1, 1) . substr($ss, 0, strlen($ss) - 1);
        $fd = substr($Data,($i * 2 + 2-1), 1);
        $x2 = strpos($ss,$fd);
        if ($x2 < 0) Exit;
        $x = $x + $x2 * 16;
        $s2 .= chr($x);
        $ss = substr($ss, strlen($ss)-1, 1) . substr($ss, 0, strlen($ss)-1);
    }
  return $s2;
}

Update

Includes the current solution, 16 * 16 = 256 characters. You have to increase the chars in password to enlarge the displayable characters.

46 x 16 == 736 characters.

enter image description here

Sign up to request clarification or add additional context in comments.

2 Comments

Thx fow your help, PHP code is working :D But I still have a small problem. In delphi there is problem with non-Latin characters. PROBLEM.
@xJernej perhaps you should heed what I said my comment

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.