草庐IT

php - TPLockBox3 和 PHP - AES 在 Delphi 中加密,在 PHP 中解密

coder 2024-05-03 原文

我在使用 lockbox3 和 PHP mcrypt 时遇到了麻烦。我无法将 IV 传递给 PHP。 Delphi code :

var
  Codec: TCodec;
  CL: TCryptographicLibrary;
  PlainStream: TStringStream;
  CipherStream: TMemoryStream;
begin
  PlainStream := TStringStream.Create(Edit1.Text);
  CipherStream := TMemoryStream.Create;

  CL := TCryptographicLibrary.Create(nil);
  Codec := TCodec.Create(nil);
  Codec.CryptoLibrary := CL;
  Codec.ChainModeId := uTPLb_Constants.CBC_ProgId;
  Codec.StreamCipherId := uTPLb_Constants.BlockCipher_ProgId;
  Codec.BlockCipherId := Format(uTPLb_Constants.AES_ProgId, [256]);
  Codec.Password := Edit3.Text;

  Codec.EncryptStream(PlainStream, CipherStream);
  Codec.Burn;

  Memo1.Text := Stream_to_Base64(CipherStream);
  Memo2.Clear;
  Memo2.Lines.Add(Format('Size: %d bytes', [CipherStream.Size]));
  Memo2.Lines.Add(Format('Original size: %d bytes', [PlainStream.Size]));

  Codec.Free;
  CL.Free;
  CipherStream.Free;
  PlainStream.Free;

PHP code :

  $ciphertext = base64_decode("zA/eeF+WFVMDsZ7+iA==");
  $iv = substr($ciphertext, 0, 8);
  $text = substr($ciphertext, 8, strlen($ciphertext) - 8);

  $td = mcrypt_module_open("rijndael-256", "", "cbc", $iv);
  mcrypt_generic_init($td, "PasswordPassword", $iv);
  $plaintext = mdecrypt_generic($td, $text);
  echo $plaintext;
  mcrypt_generic_deinit($td);
  mcrypt_module_close($td);

我得到一个错误:

Warning: mcrypt_generic_init() [function.mcrypt-generic-init]: Iv size incorrect; supplied length: 8, needed: 32 in C:...\aestest.php on line 7

相关主题:AES Encrypt/Decrypt Delphi & PHP

最佳答案

您还没有说您使用的是哪个版本的 Delphi。这是一个重要的细节。目前,我假设它是 Delphi 2010。您的代码存在许多问题。我会解决他们...

(1) 在 Delphi 2010 及之后的版本中,字符串以 UTF-16LE 编码,而在 PHP 中,字符串为 UTF-8。考虑一下你的这条线......

PlainStream := TStringStream.Create(Edit1.Text);

您正在做的是为您的负载字符串创建 UTF-16LE 编码。您对此进行加密并将其传递给 PHP 端并对其进行解密。但是您不会得到预期的结果,因为解密的字节是 UTF-16LE,但 PHP 期望它们是 UTF-8。

(2) TP Lockbox 3 已经有了加密字符串的本地方法。为什么不使用它们?

(3) 所有 3 种 AES 变体的 block 大小均为 128 位,即 16 字节。 IV 的大小总是 block 的大小。在 PHP 方面,作为通用编码的问题,您应该始终调用 mcrypt_enc_get_iv_size() (你没有)。请阅读reference page here .无论如何,对于 AES-256 必须返回 16 个字节。如果不是,那就是严重错误。

(4) 你的密码不一样,所以你永远无法合理地期待一个快乐的结果。在 Delphi 方面,您的密码以 UTF-16LE 编码。在 PHP 方面,您的密码是“PasswordPassword”的 UTF-8 编码,它永远不会逐字节等于 UTF-16 中的有效内容。

(5) 在 PHP 端,你写了..

 $iv = substr($ciphertext, 0, 8);

您需要将其零扩展到 16 个字节。引用这个question .


更新

正如所 promise 的,这里有一些 PHP 代码用于解密由 TurboPower LockBox 3 生成的密文消息。您需要制作一个 css 文件,否则呈现会很丑陋。

<!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>

... 这里是一个匹配的 Delphi 程序,用于为前面的 PHP 网页生成密文消息,用于测试和演示目的。 (不包括 DFM 文件)...

unit umfmDelphi_to_PHP_Symetric;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ActnList, StdCtrls, uTPLb_Codec, uTPLb_BaseNonVisualComponent,
  uTPLb_CryptographicLibrary, ExtCtrls;

type
  TmfmDelphi_to_PHP_Symetric = class(TForm)
    rgTestVectors: TRadioGroup;
    rgChainMode: TRadioGroup;
    edtPassword: TEdit;
    memoPlaintext: TMemo;
    lblPassword: TLabel;
    lblPlaintext: TLabel;
    cryptoMain: TCryptographicLibrary;
    codecAES: TCodec;
    memoOutput: TMemo;
    btnEncrypt: TButton;
    actlstMain: TActionList;
    actEncrypt: TAction;
    edtSeed: TEdit;
    lblSeed: TLabel;
    btnRandomize: TButton;
    actRandomize: TAction;
    rgCipher: TRadioGroup;
    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
  mfmDelphi_to_PHP_Symetric: TmfmDelphi_to_PHP_Symetric;

implementation



uses uTPLb_Random, uTPLb_StreamUtils, uTPLb_Constants;

{$R *.dfm}


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 TmfmDelphi_to_PHP_Symetric.actEncryptExecute( Sender: TObject);
const
  TestCaseNames: array[0..2] of string = ('Test Vector 1', 'Test Vector 2', 'Custom');
var
  usPlaintext: UTF8String;
  aCiphertext: ansistring;
  OriginalSeed: int64;
  stmCipher: TStream;
  sHex: string;
begin
memoOutput.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.EncryptAnsiString( usPlaintext, aCiphertext);
// 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 TmfmDelphi_to_PHP_Symetric.actEncryptUpdate( Sender: TObject);
begin
//
end;

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

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

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

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

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

procedure TmfmDelphi_to_PHP_Symetric.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 TmfmDelphi_to_PHP_Symetric.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.

关于php - TPLockBox3 和 PHP - AES 在 Delphi 中加密,在 PHP 中解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13534360/

有关php - TPLockBox3 和 PHP - AES 在 Delphi 中加密,在 PHP 中解密的更多相关文章

  1. ruby - Ruby 中的单 block AES 解密 - 2

    我需要尝试一些AES片段。我有一些密文c和一个keyk。密文已使用AES-CBC加密,并在前面加上IV。不存在填充,纯文本的长度是16的倍数。所以我这样做:aes=OpenSSL::Cipher::Cipher.new("AES-128-CCB")aes.decryptaes.key=kaes.iv=c[0..15]aes.update(c[16..63])+aes.final它工作得很好。现在我需要手动执行CBC模式,所以我需要单个block的“普通”AES解密。我正在尝试这个:aes=OpenSSL::Cipher::Cipher.new("AES-128-ECB")aes.dec

  2. ruby - 使用 AES 的 Rails 加密,过于复杂 - 2

    我在加密来self正在使用的第三方供应商的值时遇到问题。他们的指令如下:1)Converttheencryptionpasswordtoabytearray.2)Convertthevaluetobeencryptedtoabytearray.3)Theentirelengthofthearrayisinsertedasthefirstfourbytesontothefrontofthefirstblockoftheresultantbytearraybeforeencryption.4)EncryptthevalueusingAESwith:1.256-bitkeysize,2.25

  3. ruby - 如何在Elixir中使用AES CBC 128进行加密和解密 - 2

    我在Rails中有一个具有以下方法的应用程序,该方法可以加密和解密文本并与Java客户端通信。defencrypt(string,key)cipher=OpenSSL::Cipher::AES.new(128,:CBC)cipher.encryptcipher.padding=1cipher.key=hex_to_bin(Digest::SHA1.hexdigest(key)[0..32])cipher_text=cipher.update(string)cipher_textexcenddefhex_to_bin(str)[str].pack"H*"enddefbin_to_hex(

  4. ruby-on-rails - 这个 C 和 PHP 程序员如何学习 Ruby 和 Rails? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我来自C、php和bash背景,很容易学习,因为它们都有相同的C结构,我可以将其与我已经知道的联系起来。然后2年前我学了Python并且学得很好,Python对我来说比Ruby更容易学。然后从去年开始,我一直在尝试学习Ruby,然后是Rails,我承认,直到现在我还是学不会,讽刺的是那些打着简单易学的烙印,但是对于我这样一个老练的程序员来说,我只是无法将它

  5. Ruby - 不支持的密码算法 (AES-256-GCM) - 2

    我收到错误:unsupportedcipheralgorithm(AES-256-GCM)(RuntimeError)但我似乎具备所有要求:ruby版本:$ruby--versionruby2.1.2p95OpenSSL会列出gcm:$opensslenc-help2>&1|grepgcm-aes-128-ecb-aes-128-gcm-aes-128-ofb-aes-192-ecb-aes-192-gcm-aes-192-ofb-aes-256-ecb-aes-256-gcm-aes-256-ofbRuby解释器:$irb2.1.2:001>require'openssl';puts

  6. ruby - 在类/模块中加载外部文件 - 2

    我有一个外部文件:path_to_external_file.rb带有一些类定义:classAsome_definitionsend我想在模块B中加载它,以便上面定义的类A可以称为B::A。我试过:classBload('path_to_external_file.rb')end但是A是在主环境中定义的,而不是在B中定义的:A#=>AB.constants#=>[]如何在某些类/模块中加载外部文件?编辑我是否应该将外部文件作为字符串读取,并在Class.new{...}中评估它们,然后在B中include该类? 最佳答案 你不能。至

  7. ruby - Gem 在 irb 中加载但不在控制台中加载 - 2

    这个让我抓狂。我可以通过irb加载gem:steve@server:/var/www/listings$irbirb(main):001:0>Gem.path=>["/home/steve/.gem/ruby/1.9.1","/usr/local/ruby/lib/ruby/gems/1.9.1"]irb(main):002:0>require'nokogiri'=>true但我无法通过Rails控制台加载它:irb(main):001:0>Gem.path=>["/home/steve/.gem/ruby/1.9.1","/usr/local/ruby/lib/ruby/gems/1

  8. ruby-on-rails - 如果 YAML 文件不存在或无法在 Rails 中加载,请进行救援 - 2

    我正在使用YAML文件来存储一些secret配置数据。我只是在开发环境中使用该文件。在生产中,我使用ENV变量。这是我现在正在做的事情:我有一个config/confidental.yml文件,看起来像这样:email:user_name:'my_user'password:'my_passw'我有一个config/environments/development.rb文件(除其他外)有这些行:#Mailerconfigemail_confidential=YAML.load_file("#{Rails.root}/config/confidential.yml")['email']c

  9. ruby-on-rails - Rails 还是 Sinatra? PHP程序员入门学习哪个好? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。我使用PHP的时间太长了,对它感到厌倦了。我也想学习一门新语言。我一直在使用Ruby并且喜欢它。我必须在Rails和Sinatra之间做出选择,那么您会推荐哪一个?Sinatra真的不能用来构建复杂的应用程序,它只能用于简单的应用程序吗?

  10. ruby - 在散列单行中加入公共(public)键 - 2

    我有这个数组对:[{"a"=>"1"},{"b"=>"2"},{"a"=>"3"},{"b"=>"4"},{"a"=>"5"}]我想要一种方法来将具有多个值的公共(public)键合并到:[{"a"=>["1","3","5"]},{"b"=>["2","4"]}] 最佳答案 根据Marc-Andre的建议进行了改进。array=[{"a"=>"1"},{"b"=>"2"},{"a"=>"3"},{"b"=>"4"},{"a"=>"5"}]array.group_by(&:keys).map{|k,v|{k.first=>v.fla

随机推荐