Base64_-to_-stream涡轮动力锁箱3.6.2 Delphi Xe7 | E2010不兼容类型:';系统。TArray<;系统字节>';和';字符串';

Base64_-to_-stream涡轮动力锁箱3.6.2 Delphi Xe7 | E2010不兼容类型:';系统。TArray<;系统字节>';和';字符串';,delphi,encryption,base64,rijndael,lockbox-3,Delphi,Encryption,Base64,Rijndael,Lockbox 3,我正试图让程序在DelphiXe7上加密,在PHP端解密 我使用锁盒3.6.2使用AES 256加密CBC模式 Delphi XE7代码: Main.pas unit Main; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dia

我正试图让程序在DelphiXe7上加密,在PHP端解密

我使用锁盒3.6.2使用AES 256加密CBC模式

Delphi XE7代码:

Main.pas

unit Main;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes,
  System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  TPLB3.CryptographicLibrary, TPLB3.BaseNonVisualComponent, TPLB3.Codec,
  FMX.StdCtrls, FMX.Controls.Presentation, FMX.Edit, System.Actions,
  FMX.ActnList, FMX.Menus, FMX.ExtCtrls, FMX.Layouts, FMX.Memo;

type
  TForm2 = class(TForm)
    codecAES: TCodec;
    cryptoMain: TCryptographicLibrary;
    btnEncrypt: TButton;
    actlstMain: TActionList;
    edtSeed: TEdit;
    edtPassword: TEdit;

    rgCipher: TPopupBox;
    rgChainMode: TPopupBox;
    rgTestVectors: TPopupBox;
    btnRandomize: TButton;
    memoOutput: TMemo;
    memoPlaintext: TMemo;
    Action1: TAction;
    Action2: TAction;
    procedure actEncryptUpdate(Sender: TObject);
    procedure actEncryptExecute(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure rgTestVectorsClick(Sender: TObject);
    procedure rgChainModeClick(Sender: TObject);
    procedure actRandomizeUpdate(Sender: TObject);
    procedure actRandomizeExecute(Sender: TObject);

  private
    procedure LogFmt(const sLine: string; const Args: array of const);
    function SpaceOut(const sCompacted: string): string;
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

uses uTPLb_Random, uTPLb_StreamUtils, uTPLb_Constants;

{$R *.fmx}



function StreamToHex(Data: TStream): string;
var
  b: byte;
  sByte: string;
begin
  Data.Position := 0;
  result := '';
  while Data.Read(b, 1) = 1 do
  begin
    sByte := Format('%x', [b]);
    if Odd(Length(sByte)) then
      sByte := '0' + sByte;
    result := result + sByte
  end
end;

procedure TForm2.actEncryptExecute(Sender: TObject);
const
  TestCaseNames: array [0 .. 2] of string = ('Test Vector 1', 'Test Vector 2',
    'Custom');
var
  usPlaintext: String;
  aCiphertext: string;
  OriginalSeed: int64;
  stmCipher: TStream;
  FEncoding : TEncoding;
  sHex: string;

begin
  memoOutput.Lines.Clear;
  case rgCipher.ItemIndex of
    0:
      codecAES.BlockCipherId := Format(AES_ProgId, [128]);
  end;
  case rgChainMode.ItemIndex of
    0:
      codecAES.ChainModeId := CFB_ProgId;
    1:
      codecAES.ChainModeId := CBC_ProgId;
    2:
      codecAES.ChainModeId := ECB_ProgId;
  end;

  codecAES.UTF8Password := edtPassword.Text;
  usPlaintext := memoPlaintext.Lines.Text;
  OriginalSeed := StrToInt64(edtSeed.Text);
  TRandomStream.Instance.Seed := OriginalSeed;
  codecAES.EncryptString(usPlaintext, aCiphertext, FEncoding.UTF8);
  // NextSeed := TRandomStream.Instance.Seed;
  LogFmt('Test case = %s', [TestCaseNames[rgTestVectors.ItemIndex]]);
  LogFmt('Cipher = %s', [codecAES.Cipher]);
  LogFmt('Chain mode = %s', [codecAES.ChainMode]);
  LogFmt('PRNG seed = %d', [OriginalSeed]);
  LogFmt('Passord (UTF-8) = ''%s''', [codecAES.UTF8Password]);

  LogFmt('------------', []);
  stmCipher := TMemoryStream.Create;
  codecAES.Key.SaveToStream(stmCipher);
  sHex := StreamToHex(stmCipher);
  stmCipher.Free;
  LogFmt('key as hex = %s', [sHex]);
  LogFmt('Plaintext (UTF-8)', []);
  LogFmt('''%s''', [usPlaintext]);
  LogFmt('------------', []);
  LogFmt('ciphertext (base64) [Includes prepended IV and block quantisation] =',
    []);
  LogFmt(' ''%s''', [SpaceOut(aCiphertext)]);
  LogFmt('------------', []);
  stmCipher := TMemoryStream.Create;
  Base64_to_stream(aCiphertext, stmCipher);
  sHex := StreamToHex(stmCipher);
  stmCipher.Free;
  LogFmt('ciphertext (hex) [Includes prepended IV and block quantisation] =', []
    );
  LogFmt(' ''%s''', [SpaceOut(sHex)]);
  LogFmt('------------', []);
end;

procedure TForm2.actEncryptUpdate(Sender: TObject);
begin
  //
end;

procedure TForm2.actRandomizeExecute(Sender: TObject);
begin
  TRandomStream.Instance.Randomize;
  edtSeed.Text := IntToStr(TRandomStream.Instance.Seed)
end;

procedure TForm2.actRandomizeUpdate(Sender: TObject);
begin
  (Sender as TAction).Enabled := rgTestVectors.ItemIndex = 2
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
  memoOutput.Lines.Clear;
  LogFmt('Select test case and chain mode.', []);
  LogFmt('Enter password and plaintext message and then press the ''Encrypt'' button.',
    []);
end;

procedure TForm2.LogFmt(const sLine: string; const Args: array of const);
begin
  memoOutput.Lines.Add(Format(sLine, Args))
end;

procedure TForm2.rgChainModeClick(Sender: TObject);
begin
  //
end;

procedure TForm2.rgTestVectorsClick(Sender: TObject);
var
  isCustom: boolean;
begin
  case rgTestVectors.ItemIndex of
    0:
      begin
        edtPassword.Text := 'Your lips are smoother than vasoline.';
        memoPlaintext.Lines.Text := 'Leeeeeeeeeroy Jenkins!';
        // Above is constrained to:
        // More than 16 and not a whole multiple of 16 bytes as UTF-8.
        edtSeed.Text := '1';
        rgChainMode.ItemIndex := 0;
        rgCipher.ItemIndex := 0;
      end;
    1:
      begin
        edtPassword.Text := 'ORATIO IN L. CATILINAM PRIMA';
        memoPlaintext.Lines.Text := 'Quo usque tandem abutere, Catili';
        // Above is constrained to:
        // A whole multiple of 16 bytes as UTF-8, excluding the empty case.
        edtSeed.Text := '333';
        rgChainMode.ItemIndex := 0;
        rgCipher.ItemIndex := 0
      end;
    2:
      ;
  end;
  isCustom := rgTestVectors.ItemIndex = 2;
  edtPassword.ReadOnly := not isCustom;
  memoPlaintext.ReadOnly := not isCustom;
  edtSeed.ReadOnly := not isCustom;
  rgChainMode.Enabled := isCustom;
  rgCipher.Enabled := isCustom
end;

function TForm2.SpaceOut(const sCompacted: string): string;
const
  NewLineSpacing = 70;
  BunchSpacing = 6;
var
  i, j: integer;
begin
  SetLength(result, 2 * Length(sCompacted));
  i := 1;
  for j := 1 to Length(sCompacted) do
  begin
    if ((j mod NewLineSpacing) = 1) and (j <> 1) then
    begin
      result[i] := #13;
      Inc(i);
      result[i] := #10;
      Inc(i)
    end
    else if ((j mod BunchSpacing) = 1) and (j <> 1) then
    begin
      result[i] := ' ';
      Inc(i)
    end;
    result[i] := sCompacted[j];
    Inc(i)
  end;
  SetLength(result, i - 1)
end;

end.
unitmain;
接口
使用
System.SysUtils、System.TYPE、System.UITYPE、System.Classes、,
系统变量,
FMX.类型,FMX.控件,FMX.窗体,FMX.图形,FMX.对话框,
TPLB3.CryptographicLibrary,TPLB3.BaseNonVisualComponent,TPLB3.Codec,
FMX.StdCtrls、FMX.Controls.Presentation、FMX.Edit、System.Actions、,
FMX.ActnList、FMX.menu、FMX.ExtCtrls、FMX.Layouts、FMX.Memo;
类型
TForm2=类别(TForm)
编解码器:TCodec;
cryptoMain:Tcryptographics库;
btnEncrypt:TButton;
actlstMain:战术家;
种子:TEdit;
密码:TEdit;
rgCipher:TPopupBox;
rgChainMode:TPopupBox;
rgTestVectors:TPopupBox;
btnRandomize:t按钮;
输出:TMemo;
备忘录:TMemo;
行动1:战术;
行动2:战术;
程序更新(发送方:TObject);
执行过程(发送方:TObject);
过程表单创建(发送方:ToObject);
程序rgtestvectorslick(发送方:TObject);
程序rgChainModeClick(发送方:TObject);
程序actRandomizeUpdate(发送方:TObject);
程序actRandomizeExecute(发送方:TObject);
私有的
过程LogFmt(const sLine:string;const Args:const数组);
函数SpaceOut(constscompacted:string):string;
公众的
{公开声明}
结束;
变量
表2:TForm2;
实施
使用uTPLb_随机、uTPLb_流线、uTPLb_常数;
{$R*.fmx}
函数StreamToHex(数据:TStream):字符串;
变量
b:字节;
sByte:字符串;
开始
数据位置:=0;
结果:='';
而Data.Read(b,1)=1 do
开始
sByte:=格式('%x',[b]);
如果为奇数(长度(sByte)),则
sByte:=“0”+sByte;
结果:=结果+sByte
结束
结束;
过程TForm2.actEncryptExecute(发送方:TObject);
常数
TestCaseNames:string=('TestVector 1','TestVector 2',的数组[0..2],
"习俗";;
变量
usPlaintext:字符串;
aCiphertext:字符串;
原始种子:int64;
stm密码:TStream;
编码:十位编码;
弦;
开始
memoOutput.Lines.Clear;
案例rgCipher.ItemIndex of
0:
codecAES.BlockCipherId:=格式(AES_ProgId,[128]);
结束;
案例rgChainMode.ItemIndex of
0:
codecAES.ChainModeId:=CFB\u ProgId;
1:
codecAES.ChainModeId:=CBC_ProgId;
2:
codecAES.ChainModeId:=ECB_ProgId;
结束;
codecAES.UTF8Password:=edtPassword.Text;
usPlaintext:=memoplantext.Lines.Text;
OriginalSeed:=StrToInt64(edtSeed.Text);
TRandomStream.Instance.Seed:=原始种子;
EncryptString(usPlaintext、aCiphertext、FEncoding.UTF8);
//NextSeed:=TRandomStream.Instance.Seed;
LogFmt('testcase=%s',[TestCaseNames[rgTestVectors.ItemIndex]]);
LogFmt('Cipher=%s',[codecAES.Cipher]);
LogFmt('Chain mode=%s',[codecAES.ChainMode]);
LogFmt('PRNG seed=%d',[OriginalSeed]);
LogFmt('Passord(UTF-8)=''%s'',[codecAES.UTF8Password]);
LogFmt('-------------',[]);
stmCipher:=TMemoryStream.Create;
codecAES.Key.SaveToStream(stmcyper);
sHex:=StreamToHex(stmcyper);
免费的;
LogFmt('key as hex=%s',[sHex]);
LogFmt(‘明文(UTF-8)’,[]);
LogFmt(''%1!'',[usPlaintext]);
LogFmt('-------------',[]);
LogFmt(“密文(base64)[包括前置IV和块量化]=”,
[]);
LogFmt(''%1!'',[SpaceOut(aCiphertext)];
LogFmt('-------------',[]);
stmCipher:=TMemoryStream.Create;
Base64_到_流(aCiphertext,STMChipher);
sHex:=StreamToHex(stmcyper);
免费的;
LogFmt('密文(十六进制)[包括前置IV和块量化]=',[]
);
LogFmt(''%s',[SpaceOut(sHex)]);
LogFmt('-------------',[]);
结束;
程序TForm2.actEncryptUpdate(发送方:ToObject);
开始
//
结束;
程序TForm2.actRandomizeExecute(发送方:TObject);
开始
TRandomStream.Instance.Randomize;
edtSeed.Text:=IntToStr(TRandomStream.Instance.Seed)
结束;
程序TForm2.actRandomizeUpdate(发送方:TObject);
开始
(发送方为TAction)。已启用:=rgTestVectors.ItemIndex=2
结束;
过程TForm2.FormCreate(发送方:TObject);
开始
memoOutput.Lines.Clear;
LogFmt('选择测试用例和链模式',[]);
LogFmt('输入密码和明文信息,然后按“加密”按钮',
[]);
结束;
过程TForm2.LogFmt(const sLine:string;const Args:const数组);
开始
memoOutput.Lines.Add(格式(sLine,Args))
结束;
过程TForm2.rgChainModeClick(发送方:TObject);
开始
//
结束;
程序TForm2.rgtestvectorslick(发送方:TObject);
变量
isCustom:布尔型;
开始
案例rgTestVectors.ItemIndex of
0:
开始
edtPassword.Text:=“你的嘴唇比你的嘴唇光滑。”;
memoPlaintext.Lines.Text:=“LeeereRoy Jenkins!”;
//以上内容仅限于:
//UTF-8大于16字节,而不是16字节的整数倍。
edtSeed.Text:=“1”;
rgChainMode.ItemIndex:=0;
rgCipher.ItemIndex:=0;
结束;
1:
开始
edtPassword.Text:=“L.CATILINAM PRIMA中的演讲”;
memoPlaintext.Lines.Text:=“usque tandem abutere,Catili”;
//以上内容仅限于:
//作为UTF-8的16字节的整数倍,不包括空的大小写。
edtSeed.Text:=“333”;
rgChainMode.ItemIndex:=0;
rgCipher.ItemIndex:=0
结束;
2:
;
结束;
isCustom:=rgTestVectors.ItemIndex=2;
edtPassword.ReadOnly:=不自定义;
memoPlaintext.ReadOnly:=不自定义;
edtSeed.ReadOnly:=不自定义;
rgChainMode.Enabled:=isCustom;
rgCipher.Enabled:=isCustom
结束;
函数TForm2.SpaceOut(const-sCompacted:string):string;
常数
换行间距=70;
束间距=6;
变量
我
[dcc32 Error] Main.pas(125): E2010 Incompatible types: 'System.TArray<System.Byte>' and 'string'
<!DOCTYPE html>
<html lang="en">
 <head>
    <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=UTF-8">
    <META NAME="ROBOTS" CONTENT="NOINDEX,NOFOLLOW,NOARCHIVE" />
    <META NAME="DESCRIPTION" CONTENT="Tutorial and demostration page for Delphi (TurboPower LockBox3) to PHP symetric cryptography." />
    <META NAME="AUTHOR" CONTENT="Sean B. Durkin">
    <META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
    <META NAME="KEYWORDS" CONTENT="cryptography,delphi,php,turbopower,lockbox,lockbox3">
    <title>Delphi-to-PHP Cryptography Tutorial</title>
    <link rel="stylesheet" media="screen and (min-device-width:  721px)" href="tut.css" /><!-- <== Desktop. -->     
    <link rel="stylesheet" media="screen and (max-device-width:  720px)" href="tut-phone.css" / --><!-- <== Phone and tablet. -->  
 <head>

<body>
<?php
error_reporting(E_ALL | E_COMPILE_ERROR);
$password = $_GET["password"];
$ciphertext_trans = $_GET["ciphertext-trans"];
$rawInputCiphertext = $_GET["ciphertext"];
$chain = $_GET["chain"];
$cipherIn = $_GET["cipherIn"];

function radioChecked($param,$value,$isDefault)
{
  $echo = (($param == $value) or ($isDefault and ($param == ''))) ? ' checked="checked" ' : '';
  echo $echo;
  return $echo != '';  
}
?>

<nav>
  <div class="nav-bg"></div>
  <div class="nav-content">
    <h1><a href="http://lockbox.seanbdurkin.id.au/tiki-index.php?page=Delphi-to-PHP+Tutorial+project+home" title="Go to The Delphi-to-PHP project home"><span class="hidden">Project home</span></a></h1>
    <dl>
      <dt>Date created</dt>
      <dd><time datetime="2012-11-29">29-Nov-2012</time></dd>
    </dl>
    <dl>
      <dt>Date last modified</dt>
      <dd><time datetime="2012-12-02">2-Dec-2012</time></dd>
    </dl>
  </div>    
</nav>

<h1>Decrypt with PHP from Delphi (TurboPower LockBox3)</h1>
<form id="plainForm" class="floatbox" action="">
  <fieldset>
    <legend>Crypto data</legend>
    <label class="first" for="password">Password (UTF-8)
      <input id="password" name="password" type="text" placeholder="Enter TCodec password" value="<?php echo htmlspecialchars($password) ?>" />
    </label>            
    <fieldset class="radio">
      <legend>Transport encoding</legend>
        <label for="ciphertext-trans-base64">
          <input id="ciphertext-trans-base64" name="ciphertext-trans" type="radio" value="base64" 
          <?php radioChecked($ciphertext_trans,'base64',True); ?> />base64
        </label>
        <label for="ciphertext-trans-hex">
          <input id="ciphertext-trans-hex" name="ciphertext-trans" type="radio" value="hex" 
          <?php radioChecked($ciphertext_trans,'hex',False); ?> />hex
        </label>
    </fieldset>             
    <label for="ciphertext">Ciphertext (transport encoded)
      <input id="ciphertext" name="ciphertext" type="text" placeholder="Paste ciphertext here" value="<?php echo htmlspecialchars($rawInputCiphertext) ?>" />
    </label>            
  </fieldset>
  <fieldset>
    <legend>Options</legend>
    <fieldset class="radio">
      <legend>Chaining mode</legend>
        <label for="chain-cfb">
          <input id="chain-cfb" name="chain" type="radio" 
            value="CFB" <?php radioChecked($chain,'CFB',True); ?> />CFB
        </label>
        <label for="chain-cbc">
          <input id="chain-cbc" name="chain" type="radio"
            value="CBC" <?php radioChecked($chain,'CBC',False); ?> />CBC
        </label>
        <label for="chain-ecb">
          <input id="chain-ecb" name="chain" type="radio"
            value="ECB" <?php radioChecked($chain,'ECB',False); ?> />ECB
        </label>
    </fieldset>             

    <fieldset class="radio">
      <legend>Cipher</legend>
        <label for="aes-128">
          <input id="aes-128" name="cipherIn" type="radio" 
            value="AES-128" <?php radioChecked($cipherIn,'AES-128',True); ?> />AES-128
        </label>
        <!-- Extend here with more ciphers as required. Note: PHP does not support AES-256. -->
    </fieldset>             

    </fieldset>             
  <input class="submit" type="submit" value="Decrypt" />
</form>
<?php if ($chain) { ?>
<?php
function purgeWhiteSpace($sparseHex)
{
    return preg_replace('/\s+/', '', $sparseHex);
}
function expandWithWhiteSpace($compactHex)
{
// TODO: Insert white space for visual benefit. Bunch the brown spaces
//  into words of 6 characters, and then separate words with a single space.
//  Between every 10th word and 11th word, use a new-line ($0D) instead of space.
//  Assume that $compactHex ONLY consists of characters 0..9 and A..F .
    return $compactHex;
}
function displayableMultiline($str)
{
// TODO: Assume $str ONLY consists of characters whose code-points are below
//  137. Insert '<br />' before each $0D character.
    return $str;
}
function hexToStr($hex)
{
    $hex2 = purgeWhiteSpace( $hex);
    $str='';
    for ($i=0; $i < strlen($hex2)-1; $i+=2)
    {
        $str .= chr(hexdec($hex2[$i].$hex2[$i+1]));
    }
    return $str;
}   
function strToHex($str)
{
    $hex='';
    for ($i=0; $i < strlen($str); $i++)
    {       
        $addend = dechex(ord($str[$i]));
        if (strlen($addend) < 2)
          $addend = '0' . $addend;
        $hex .= $addend;
    }
    return $hex;
}

$normalisedRawCiphertext = purgeWhiteSpace( $rawInputCiphertext);
if ($ciphertext_trans == 'base64')
{ 
  $ciphertext = base64_decode( $normalisedRawCiphertext);
}
else
{
  $ciphertext = hexToStr( $normalisedRawCiphertext);
}

if ($cipherIn == 'AES-128')
{
  $cipher = MCRYPT_RIJNDAEL_128;
  $cipherName = 'AES-128';
}
else
{
  // Extend here with more ciphers as required. Note: PHP does not support AES-256.
  $cipher = MCRYPT_RIJNDAEL_128; // Example only.
  $cipherName = '???';           // Example only.
}

if ($chain == 'CFB')
    $mode = 'ncfb';  // Proper block-mode CFB. There is no constant for this.
  else if ($chain == 'CBC') 
    $mode = MCRYPT_MODE_CBC;
  else  
    $mode = MCRYPT_MODE_ECB;

$blockSize = mcrypt_get_block_size( $cipher, $mode);
$keySize = mcrypt_get_key_size( $cipher, $mode);

// Work-around PHP bugs.
if (($cipher == MCRYPT_RIJNDAEL_128) and ($keySize == 32))
  { $keySize = 16; }   // AES-128 key size is 16 bytes.
if (($cipher == MCRYPT_RIJNDAEL_256) and ($blockSize == 32))
  { $blockSize = 16; } // AES-256 block size is 16 bytes.

$ivSize = $blockSize; // Always. mcrypt_get_iv_size() is pointless.

if ($chain == 'ECB')
{
    $iv = str_pad( 'NOT USED', 16, chr(0));
    // $ciphertext unchanged.
}
else
{
    $iv = substr( $ciphertext, 0, 8);
    $iv = str_pad( $iv, $ivSize, chr(0));
    $ciphertext = substr( $ciphertext, 8);
}

$ciphertextLen = strlen( $ciphertext);
if  (($ciphertextLen > 0) && ($ciphertextLen < $blockSize) && ($chain == 'CBC'))
 { $mode = MCRYPT_MODE_CFB; } // CFB 8-bit. This is NOT the same as CFB.

if (strlen($password)==$keySize)
  {
    $key = $password;
  }
else
  {
    $shaPassword = sha1( $password, True);
    for ($key = ''; strlen( $key) < $keySize; $key .= $shaPassword) {}
    $key = substr( $key, 0, $keySize);
  }  

$countBlocks = $ciphertextLen / $blockSize;
$countWholeBlocks = floor( $countBlocks); 
$isRound = $countBlocks == $countWholeBlocks; 
if ($isRound)
    {
    $lastBlockSize = 0;
    }
  else
    {
    $countBlocks = $countWholeBlocks + 1;
    $lastBlockSize = $ciphertextLen - ($countWholeBlocks * $blockSize);
    }     
$isCipherStealing = ($mode == MCRYPT_MODE_CBC) && ($countWholeBlocks >= 1) && !$isRound;
if ($isCipherStealing)
    { // Reverse ciphertext stealing.
/* 
Ciphertext stealing algorithm - Encryption:
  Mix     := Enc( CV[N-2], X[N-2]);
  Steal   := Last( B-b, Mix);
  Recycle := X[N-1] + Steal;
  Y[N-2]  := Enc( CV[N-2], Recycle);
  Y[N-1]  := Head( b, Mix);

Ciphertext stealing algorithm - Decryption:
  Recycle := Dec( CV[N-2], Y[N-2]);
  Steal   := Last( B-b, Recycle);
  Mix     := Y[N-1] + Steal;
  X[N-2]  := Dec( CV[N-2], Mix);
  X[N-1]  := Head( b, Recycle);  
*/  
    // 1. Recycle := Dec( CV[N-2], Y[N-2]);
    $Recycle = mcrypt_decrypt ( $cipher, $key, substr( $ciphertext, 0, $countWholeBlocks * $blockSize), $mode, $iv);
    $reconUpToX_N_3 = substr( $Recycle, 0, ($countWholeBlocks - 1) * $blockSize); // X[0]..X{N-3]
    $Recycle = substr( $Recycle, ($countWholeBlocks - 1) * $blockSize, $blockSize);

    // 2. Steal := Last( B-b, Recycle);
    $Steal = substr( $Recycle, $lastBlockSize, $blockSize - $lastBlockSize);

    // 3. Mix := Y[N-1] + Steal;
    $Y_N1 = substr( $ciphertext, $countWholeBlocks * $blockSize, $lastBlockSize);
    $Mix = $Y_N1 . $Steal;

    // 4. X[N-2]  := Dec( CV[N-2], Mix);
    $reconUpToX_N_2 = mcrypt_decrypt ( $cipher, $key, substr( $ciphertext, 0, ($countWholeBlocks - 1) * $blockSize) . $Mix, $mode, $iv);

    // 5. X[N-1] := Head( b, Recycle);
    $reconX_N_1 = substr( $Recycle, 0, $lastBlockSize);

    // Putting it alltogether.
    $recon = $reconUpToX_N_2 . $reconX_N_1;
    }
  else
    { // Normal decyrption.
    $recon = mcrypt_decrypt ( $cipher, $key, $ciphertext, $mode, $iv);
    }
if (($chain == 'ECB') and ($recon != ''))
  { // Trim ECB padding.
  $last = strlen($recon);
  for ($l = strlen($recon); ($l >= 0) and (ord($recon[$l])==0); $l--)
    {$last = $l;}
  $recon = substr( $recon, 0, $last-1);
  }
?>
<hr />
<h2>Output</h2>
<h3>Summary2</h3>
<p>Cipher is <em><?php echo $cipherName; ?></em></p>
<p>Block size is <?php echo $blockSize; ?> bytes</p>
<?php if ($isRound) { ?>
  <p>Given ciphertext was a round <?php echo $countBlocks; ?> blocks long.</p>
<?php } else { ?>
  <p>Given ciphertext was a <?php echo $countWholeBlocks; ?> whole blocks long and <?php echo $lastBlockSize; ?> bytes in an odd block.</p>
<?php } ?>
<p>Key size is <?php echo $keySize; ?> bytes</p>
<p>Given chain mode was <em><?php echo $chain; ?></em></p>
<p>Given password was <em>&apos;<?php echo htmlspecialchars($password); ?>&apos;</em></p>
<p>Ciphertext as hex is...</p>
<code><?php echo '[' . $ciphertextLen . '] ' . displayableMultiline( expandWithWhiteSpace( strToHex( $ciphertext))); ?></code>
<p></p>
<p>Reconstructed plaintext message is <em>&apos;<?php echo htmlspecialchars( $recon); ?>&apos;</em></p>
<p></p>
<h2>Debug</h2>
<p>Key as hex is...</p>
<code><?php echo '[' . strlen($key) . '] ' . expandWithWhiteSpace( strToHex( $key)); ?></code>
<p>IV as hex is...</p>
<code><?php echo '[' . strlen($iv) . '] ' . expandWithWhiteSpace( strToHex( $iv)); ?></code>
<p>$countBlocks = <code><?php echo $countBlocks; ?></code></p>
<p>$countWholeBlocks = <code><?php echo $countWholeBlocks; ?></code></p>
<p>$isRound = <code><?php echo $isRound ? 'True' : 'False'; ?></code></p>
<p>$isCipherStealing = <code><?php echo $isCipherStealing ? 'True' : 'False'; ?></code></p>
<p>$lastBlockSize = <code><?php echo $lastBlockSize; ?></code></p>
<p>$Recycle = <code><?php echo '[' . strlen($Recycle) . '] ' . strToHex( $Recycle); ?></code></p>
<p>$recon X[0..N-3] = <code><?php echo '[' . strlen($reconUpToX_N_3) . '] ' . strToHex( $reconUpToX_N_3); ?></code></p>
<p>$Steal = <code><?php echo '[' . strlen($Steal) . '] ' . strToHex( $Steal); ?></code></p>
<p>$Mix = <code><?php echo '[' . strlen($Mix) . '] ' . strToHex( $Mix); ?></code></p>
<p>$recon X[0..N-2] = <code><?php echo '[' . strlen($reconUpToX_N_2) . '] ' . strToHex( $reconUpToX_N_2); ?></code></p>
<p>$recon X[N-1] = <code><?php echo '[' . strlen($reconX_N_1) . '] ' . strToHex( $reconX_N_1); ?></code></p>
<p>Reconstructed plaintext as hex is...</p>
<code><?php echo '[' . strlen($recon) . '] ' . expandWithWhiteSpace( strToHex( $recon)); ?></code>
<?php } ?>
</body> 
</html>
Base64_to_stream(aCiphertext, stmCipher);
procedure Base64_to_stream(const Base64: string; Destin: TStream);