gpt4 book ai didi

Delphi 7 - DCPCrypt - TDCP_rijndael - DecryptString - 如何使它工作?

转载 作者:行者123 更新时间:2023-12-04 12:34:51 25 4
gpt4 key购买 nike

我在 PHP (openssl_encrypt/'aes-256-cbc') 中加密文本,然后尝试在 Delphi 7 (DCPCrypt/TDCP_rijndael) 中解密它。
PHP 脚本文件以ANSI 编码保存,希望传输的字符串(其REST API Web 服务)与Delphi 兼容。
但是 Delphi 解密产生了错误的结果,我猜测代码中有问题。如果您能看一下,并在 Delphi 方面发现我的错误,我将不胜感激:
PHP代码:

function encrypt($key, $payload) {
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
$encrypted = openssl_encrypt($payload, 'aes-256-cbc', $key, 0, $iv);
return base64_encode($encrypted . '::' . $iv);
}

function decrypt($key, $garble) {
list($encrypted_data, $iv) = explode('::', base64_decode($garble), 2);
return openssl_decrypt($encrypted_data, 'aes-256-cbc', $key, 0, $iv);
}
德尔福代码:
var
DCP_rijndael: TDCP_rijndael;

const
cPASSWORD = 'myownpassword';

function Decrypt(AStr: string): string;
var
d, s, iv: String;
p: Integer;
begin
d := Base64DecodeStr(AStr);
p := Pos('::', d);
s := Copy(d, 1, p - 1);
iv := Copy(d, p + 2, Length(s));

DCP_rijndael.SetIV(iv);
Result := DCP_rijndael.DecryptString(s);
end;

initialization
DCP_rijndael := TDCP_rijndael.Create(nil);
DCP_rijndael.Algorithm := 'Rijndael';
DCP_rijndael.CipherMode := cmCBC;

//DCP_rijndael.BlockSize := 128; {tried various values with no luck!}
//DCP_rijndael.MaxKeySize := 256;{tried various values with no luck!}

DCP_rijndael.Init(cPASSWORD, 256, nil);

finalization
DCP_rijndael.Free;
..有一个紧迫的项目截止日期,我坚持这个..将非常感谢帮助解决问题。蒂亚!

最佳答案

需要了解的基础知识

  • 永远不要处理“文本”,因为加密不知道 text encodings
  • 永远不要处理“Strings ”,因为编程语言之间的差异很大。
  • 不同的密码具有不同的块大小 - 这意味着提供的要加密的数据必须匹配可以被给定除数(即 8 或 16)除的长度。否则填充适用,您可能需要处理它。
  • OpenSSL 的主要目标受众是 MIME/电子邮件,因此它已经在 Base64 上运行。不要再次将其输出重新编码为 Base64 - 这只是错过了重点。
  • key 始终是二进制的。将其作为原始字节处理。 ASCII 也能工作,这只是巧合。但是,一旦您超出了这个范围,请重新考虑您将要做什么。

  • 为什么要处理 Base64?
    这只是一种以坚如磐石的格式存储二进制数据的方法。它的尺寸更大,但即使通过电子邮件发送也是安全的。如果您没有那个需要,因为无论如何您都会将数据存储到文件中,那么(当然)不要使用它。
    使用 OpenSSL 在 PHP 中加密和解密
    PHP 文件的文本编码与编码和解码无关:这些函数的参数仍被视为二进制。
    <?php

    // This file's output should not be interpreted as HTML
    header( 'Content-type: text/plain' );

    // Do not use the same literals again and again
    define( 'CIPHER', 'aes-128-cbc' ); // Which algorithm is used
    define( 'GLUE', '::' ); // How to concatenate data and IV


    function encrypt( $key, $plain ) {
    // Initialization vector comes in binary. If we want to carry that
    // thru text-like worlds then we should convert it to Base64 later.
    $iv= openssl_random_pseudo_bytes( openssl_cipher_iv_length( CIPHER ) );
    echo "\n iv=\t\t(binary as hex)\t". bin2hex( $iv ). "\tlength=". strlen( $iv );

    // By default OpenSSL already returns Base64, but it could be changed
    // to binary with the 4th parameter, if we want.
    $encryptedData= openssl_encrypt( $plain, CIPHER, $key, 0, $iv );
    echo "\n encrypted=\t(Base64)\t". $encryptedData;

    // The encrypted data already came in Base64 - no need to encode it
    // again in Base64. Just concatenate it with the initialization
    // vector, which is the only part that should also be encoded to
    // Base64. And now we have a 7bit-safe ASCII text, which could be
    // easily inserted into e-mails.
    return $encryptedData. GLUE. base64_encode( $iv ). GLUE. strlen( $plain );
    }

    function decrypt( $key, $allinone ) {
    // The "glue" must be a sequence that would never occur in Base64.
    // If everything works as expected we get an array with exactly three
    // elements: first is data, second is IV, third is size.
    $aParts= explode( GLUE, $allinone, 3 );

    // OpenSSL expects Base64 by default as input - don't decode it!
    $data= $aParts[0];
    echo "\n data=\t\t(Base64)\t". $data;

    // The initialization vector was encoded in Base64 by us earlier and
    // now needs to be decoded to its binary form. Should size 16 bytes.
    $iv= base64_decode( $aParts[1] );
    echo "\n iv=\t\t(binary as hex)\t". bin2hex( $iv ). "\tlength=". strlen( $iv );

    return openssl_decrypt( $data, CIPHER, $key, 0, $iv );
    }

    // Keep in mind that you DON'T encrypt and decrypt "TEXT" - you
    // operate on binary data. Likewise make sure you fully understood
    // this by choosing only ASCII before advancing into the world of
    // different text encodings. Never mix encryption with "Strings" -
    // only operate on it as if it would be naked bytes that make no sense!
    $plain= 'AbCdEfGhIjKlMnOpQrStUvWxYz';
    $key= '1234567890123456';

    echo "Parameters:
    plain=\t\t(binary)\t$plain\tlength=". strlen( $plain ). "
    key=\t\t(binary)\t$key\tlength=". strlen( $key ). "
    ";

    echo "\nEncryption:";
    $en= encrypt( $key, $plain );
    echo "\n allinone=\t(ASCII)\t\t". $en. "\n";

    echo "\nDecryption:";
    $de= decrypt( $key, $en );
    echo "\n decrypted=\t(binary)\t". $de;
    如果选择 9e8e5d5ab909d93c991fd604b98f4f50initialization vector( hexadecimal 表示其 16 字节长度),则加密应生成 9NC0HhAxFZLuF/omOcidfDQnczlczTS1nIZkNPOlQZk=::no5dWrkJ2TyZH9YEuY9PUA==::26 的一体式文本,其中第一部分是 Base64 中的加密数据,第二部分是 Base64 中的初始化向量,第三部分确保我们的纯(文本)输入的长度。使用该长文本,您应该能够将其解码回 AbCdEfGhIjKlMnOpQrStUvWxYz 的纯文本(文本)(长度为 26 字节)。
    使用 DEC5.2 在 D7 中解密
    我不完全确定,但 Delphi Encryption Compendium 5.2, Part I 似乎不支持 AES 的不同 key 大小,这就是我坚持 128 的原因。请记住,Delphi 7 的 String 在其他版本中必须始终被视为 AnsiString,否则最终会不是字节安全的东西。
    uses
    DecCipher, DecFmt;

    const // The same glue for concatenating all 3 parts
    GLUE= '::';

    var
    c: TDecCipher; // Successfully tested with DEC 5.2 on Delphi 7
    sAllInOne, // All 3 parts in a 7bit-safe ASCII text
    sKey, // The binary key we have to provide
    sIv, // Initialization vector, decoded from sAllInOne
    sEncrypted, // Actual data to decrypt, decoded from sAllInOne
    sPlain: AnsiString; // Decrypted binary we want to get
    iPosGlue, // Next found glue token to cut one part off
    iLength: Integer; // Plaintext length target, in bytes
    begin
    // What was output by the PHP script
    sAllInOne:= '9NC0HhAxFZLuF/omOcidfDQnczlczTS1nIZkNPOlQZk=::no5dWrkJ2TyZH9YEuY9PUA==::26';

    // Find next delimiter; Base64 will never have a '..' sequence
    iPosGlue:= Pos( GLUE, sAllInOne );
    sEncrypted:= Copy( sAllInOne, 1, iPosGlue- 1 ); // Still Base64
    Delete( sAllInOne, 1, iPosGlue- 1+ Length( GLUE ) );

    iPosGlue:= Pos( GLUE, sAllInOne );
    sIv:= Copy( sAllInOne, 1, iPosGlue- 1 );
    Delete( sAllInOne, 1, iPosGlue- 1+ Length( GLUE ) );

    // What remains is the length of the original text, once decrypted. Why do we need it?
    // Because the cipher/algorithm depends on fixed block sizes, so it is automatically
    // padded to the next full length. Otherwise we end up with decryptions that will
    // always have a few odd bytes at the end, if they aren't multiples of 16.
    iLength:= StrToInt( sAllInOne );

    // Keep in mind: this is treated as binary, not text!
    sKey:= '1234567890123456';

    // Decode Base64 back into binary
    sEncrypted:= TFormat_MIME64.Decode( sEncrypted );
    sIv:= TFormat_MIME64.Decode( sIv );

    // Expect DEC 5.2 to only deal with AES-128-CBC, not 256.
    c:= ValidCipher( DecCipher.TCipher_Rijndael ).Create;
    try
    c.Mode:= cmCBCx;
    c.Init( sKey, sIv ); // Provide binary key and binary IV
    SetLength( sPlain, Length( sEncrypted ) ); // By now the output length must match the input's
    c.Decode( sEncrypted[1], sPlain[1], Length( sEncrypted ) );
    SetLength( sPlain, iLength ); // Now cut it to the actual expected length

    // We're done: sPlain should be 'AbCdEfGhIjKlMnOpQrStUvWxYz'
    Writeln( sPlain );
    finally
    c.Free;
    end;
    end;
    由于未使用 OpenSSL,我们需要自己处理块大小填充 - 如果您省略最后一个长度分配,您将看到有更多字节可以四舍五入到 32 字节的大小。
    剩下的呢?
    应该是显而易见的。 Delphi 中的加密非常相似。使用 ASCII 以外的文本作为有效载荷和/或 key 是完全可能的,但很可能不会在幕后神奇地完成 - 确保你 实际上 有 ie UTF-8ISO-8859-1 通过逐步遍历所有代码行并跟踪内存真正拥有您期望的字节。如果你不喜欢文本编码,那就把它留给其他人。如果您不喜欢加密,则将处理文本的工作留给其他人。
    如果您介意所有步骤,在 Delphi 中使用不同的库/组件(即支持 AES-256 的库/组件)应该很容易与我的示例互换。如果您从 Internet 上获取了一个狂野的 Base64 编码器/解码器,请注意也有略微不同的版本。

    关于Delphi 7 - DCPCrypt - TDCP_rijndael - DecryptString - 如何使它工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65810276/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com