Delphi到PHP - 字符串加密

时间:2014-09-11 14:46:57

标签: php delphi encryption

我需要在XE6 Firemonkey项目中加密字符串。

我尝试过dcpcrypt,但Firemonkey不支持AnciString,.....

我找到了一个适用于Firemonkey的解决方案。 我的问题是将此代码转换为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;

这是我的PHP代码;

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 个答案:

答案 0 :(得分:1)

在php中执行代码并不完全正确。

ENCODE

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

php函数strpos可能会0返回。要测试在另一个字符串中找到的字符,您应该使用=== true=== false

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

不是

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

INDEX()函数错误。

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

可能会返回false + 1 !!!
你用

测试返回值
if (INDEX($SecurityString[$i]) <= 0) Exit;

永远不会是<= 0 !!

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;

部分错误的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 ;
}

用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代码错误

 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));
    }
 }

看看

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

substr()函数使用1作为起点应使用0 否则总是删除两个字符而不只是一个。

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

将为我们提供一个空子字符串:$s1 = substr($s1, 1, 0);

现在$s1 == ''

更多错误

  • INDEX()函数使用永不更改的字符串$Codes64
  • 而substr()函数使用不断缩小的$s1字符串。
  • (DIV(长度($数据)
    (DIV(strlen的($数据)
  • 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 ==&#39; 0 / nCXpmMP2iFvJ3G&#39;

看看下一个$SecurityString字符。它是/这是字符串$Codes64中的最后一个字符。

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

我们得到位置63 + 1 == 64的Char / 现在$vx == 64

$ vx值落后于长度($ Codes64)[0..63]
01删除前两个字符$s1后,字符/位于62位置,因此$ vx也位于长度($ s1)之后


工作Php代码

<强> EncodePWDEx
取代

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));
        }
    }

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 取代

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

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

DECODE

<强> DecodePWDEx 取代

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;
}

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;
}

<强>更新

包括当前解决方案,16 * 16 = 256个字符。您必须增加密码中的字符以放大可显示的字符。

46 x 16 == 736个字符。

enter image description here