【问题标题】:Delphi to PHP - String encryptDelphi 到 PHP - 字符串加密
【发布时间】:2014-11-05 14:03:02
【问题描述】:

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

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

我找到了一个适用于 Firemonkey 的解决方案。 我的问题是将此代码转换为 PHP。

德尔福演示项目:Link

德尔福代码:

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

【问题讨论】:

  • 正如我之前多次说过的,加密对二进制数据进行操作。加密和解密TBytes,字节数组。使用 TEncoding.GetStringTEncoding.GetBytes 对文本进行二进制编码和解码。

标签: php delphi encryption


【解决方案1】:

php中代码的实现不太对。

编码

    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;

永远不会是&lt;= 0 !!

部分代码 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;

部分代码错误:

 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 就可以了

  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(长度($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'

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

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

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

$vx 值落后于长度($Codes64) [0..63]
$s1 中删除前两个字符01 后,字符/ 位于62 的位置,所以$vx 也在length($s1) 后面


工作 PHP 代码

编码PWDEx
替换

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

制作RNDString 替换

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

解码

解码PWDEx 替换

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 个字符。

【讨论】:

  • 感谢您的帮助,PHP 代码正在运行 :D 但我还有一个小问题。在 delphi 中,非拉丁字符存在问题。 PROBLEM.
  • @xJernej 也许你应该注意我所说的我的评论
猜你喜欢
  • 1970-01-01
  • 2022-11-18
  • 1970-01-01
  • 1970-01-01
  • 2013-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多