1

私は Delphi 2009 を使用していますが、ここで見た回答のほとんどは 2010 以降のものです。暗号化 (delphi) を復号​​化 (php) に同期しようとして失敗しました。

Delphi で暗号化された文字列を生成します。

program Project4;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  DCPcrypt2,
  DCPsha1,
  DCPblockciphers,
  DCPdes,
  EncdDecd;

var des: tdcp_des;
    enc,dec: ansistring;

begin
  try
  des:=tdcp_des.Create(nil);
  des.InitStr('test', tdcp_sha1);
  enc:=encodestring(des.EncryptString('this is a test'));
  des.Free;

  des:=tdcp_des.Create(nil);
  des.InitStr('test', tdcp_sha1);
  dec:=des.DecryptString(decodestring(enc));
  des.Free;

  writeln(enc);
  writeln(dec);
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.

PHPで復号化:

<?php
function decrypt($str, $key)
{
    $size = mcrypt_get_iv_size(MCRYPT_DES, MCRYPT_MODE_CBC);
    $iv = mcrypt_create_iv($size, MCRYPT_DEV_RANDOM);
    $data = base64_decode($str);
    $block = mcrypt_get_block_size('des', 'ecb');
    $k = substr(sha1($key), 0, $block);
    $str = mcrypt_decrypt(MCRYPT_DES, $k, $data, MCRYPT_MODE_CBC, $iv);
    $pad = ord($str[($len = strlen($str)) - 1]);
    return substr($str, 0, strlen($str) - $pad);
}

$enc = 'TW5mbVFhODUyR2FoOTA2WWJIOD0=';
$dec = decrypt($enc, 'test');
echo "$dec\n";
?>
4

3 に答える 3

8

いくつかの問題があると思います:-)

  • des.InitStr() は内部的に 8 つの null バイトから IV を作成し、それを暗号化します。PHP で同じ IV を使用する必要があります。

  • sha1($key) は、パスワードの実際のバイトではなく、16 進文字列を生成します。代わりに mhash のようなものが必要です。

  • 指定された Delphi 関数で $enc 文字列を再現できませんでした。

  • Unicode の問題 - パスワードとソース テキストは Delphi で Unicode として扱われます。

  • Delphi ルーチンでソースを 2 回エンコードしている base 64 のようです。des.EncryptString と des.DecryptString は Base 64 でエンコードされた文字列を生成および使用するため、再度行う必要はありません。

  • パディング

ここでの私の以前の回答に基づいて-これは私の提案です:

function EncryptStringDES: string;
var
  des: TDCP_des;
  src, enc, b64: TBytes;
  index, slen, bsize, padsize: integer;
begin
  des:=tdcp_des.Create(nil);
  try
    des.InitStr(AnsiString('test'), tdcp_sha1);

    src := TEncoding.UTF8.GetBytes('this is a test');
    slen := Length(src);
    // Add padding
    bsize := des.BlockSize div 8;
    padsize := bsize - (slen mod bsize);
    Inc(slen, padsize);
    SetLength(src, slen);
    for index := padsize downto 1 do
    begin
      src[slen - index] := padsize;
    end;

    SetLength(enc, slen);
    des.EncryptCBC(src[0], enc[0], slen);
    result := EncdDecd.EncodeBase64(@enc[0], Length(enc));
  finally
    des.Free;
  end;
end;

function DecryptStringDES(ASource: string): string;
var
  des: TDCP_des;
  key, src, dec, b64: TBytes;
  pad, slen: integer;
begin
  des := TDCP_des.Create(nil);
  try
    des.InitStr(AnsiString('test'), tdcp_sha1);

    src := EncdDecd.DecodeBase64(AnsiString(ASource));
    slen := Length(src);
    SetLength(dec, slen);
    des.DecryptCBC(src[0], dec[0], slen);

    // Remove padding
    pad := dec[slen - 1];
    SetLength(dec, slen - pad);

    result := TEncoding.UTF8.GetString(dec);
  finally
    des.Free;
  end;
end;

そしてPHP:

<?php
function decrypt_SO($str, $key)
{
    //$ivsize = mcrypt_get_iv_size(MCRYPT_DES, MCRYPT_MODE_CBC);
    //$blocksize = mcrypt_get_block_size(MCRYPT_DES, MCRYPT_MODE_CBC);
    $keysize = mcrypt_get_key_size(MCRYPT_DES, MCRYPT_MODE_CBC);

    // Need to use the SAME IV as the Delphi function. By default
    // this is (0,0,0,0,0,0,0,0) encrypted using ECB mode and gives the
    // following bytes:
    $ivbytes = array(72, 163, 99, 62, 219, 111, 163, 114);
    $iv = implode(array_map("chr", $ivbytes));

    $enc = base64_decode($str);
    $k = mhash(MHASH_SHA1, $key);
    $dec = mcrypt_decrypt(MCRYPT_DES, substr($k, 0, $keysize), $enc, MCRYPT_MODE_CBC, $iv);

    $pad = ord($dec[strlen($dec) - 1]);
    return substr($dec, 0, strlen($dec) - $pad);
}

$enc = 'WRaG/8xlxqqcTAJ5UAk4DA==';
$dec = decrypt_SO($enc, 'test');
echo "$dec\n";
?>
于 2013-02-21T13:06:41.913 に答える
1

ivバイトは誰ですか

$ivbytes = array(72, 163, 99, 62, 219, 111, 163, 114);

キー: test123456

$ivbytes = array(??, ??, ??, ??, ??, ??, ??, ??);
于 2015-11-05T18:00:39.127 に答える
0

私はこの種の統合を成功に使用していますが、それ以上の情報を提供することはできません。それは私の雇用主のものです。

mycryptを初期化しましたか?

$iv = "nononono";
$key = "nononono";
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
mcrypt_generic_init($td, $key, $iv);
$decoded = base64_decode($mySecretString);
$decryptedcbc = mdecrypt_generic($td, $decoded);
mcrypt_generic_deinit($td);

文字列をdelphiで適切にエンコードすることを忘れないでください。私は、Base64EncodeStr(Buffer);を使用します。

お役に立てば幸いです。

于 2013-02-21T12:01:21.277 に答える