在 Delphi 和PHP上工作的加密/解密函数

qxgroojn  于 2023-04-20  发布在  PHP
关注(0)|答案(2)|浏览(173)

由于GDPR,我试图找到一个好的方法来加密/解密数据。但由于我的应用程序同时具有 Delphi 和PHP端点,我需要具有强大加密功能并在两者上工作的函数。
搜索on SO I've found out the following one,但我不知道如何在 Delphi 上执行相同的功能:

function encryptString($plaintext, $password, $encoding = null) {
    $iv = openssl_random_pseudo_bytes(16);
    $ciphertext = openssl_encrypt($plaintext, "AES-256-CBC", hash('sha256', $password, true), OPENSSL_RAW_DATA, $iv);
    $hmac = hash_hmac('sha256', $ciphertext.$iv, hash('sha256', $password, true), true);
    return $encoding == "hex" ? bin2hex($iv.$hmac.$ciphertext) : ($encoding == "base64" ? base64_encode($iv.$hmac.$ciphertext) : $iv.$hmac.$ciphertext);
}

function decryptString($ciphertext, $password, $encoding = null) {
    $ciphertext = $encoding == "hex" ? hex2bin($ciphertext) : ($encoding == "base64" ? base64_decode($ciphertext) : $ciphertext);
    if (!hash_equals(hash_hmac('sha256', substr($ciphertext, 48).substr($ciphertext, 0, 16), hash('sha256', $password, true), true), substr($ciphertext, 16, 32))) return null;
    return openssl_decrypt(substr($ciphertext, 48), "AES-256-CBC", hash('sha256', $password, true), OPENSSL_RAW_DATA, substr($ciphertext, 0, 16));
}
dnph8jn4

dnph8jn41#

你发现的代码不是最优的。一旦识别出什么是重复的,并使用常量而不是文字的原则来丰富它,就会出现以下PHP代码:

define( 'ALGO_SECRET',  'sha256' );  // SHA-256 = 32 bytes; https://en.wikipedia.org/wiki/SHA-2
define( 'ALGO_MSGAUTH', 'sha256' );
define( 'ALGO_SSL',     'aes-256-cbc' );
define( 'SALT',         'Bedrock Hordes Staples' );  // https://en.wikipedia.org/wiki/Salt_(cryptography)

function encrypt( $plainbytes, $secretkey ) {
  // Preparations
  $hash=        hash( ALGO_SECRET, $secretkey. SALT, true );  // true = return bytes
  $iv=          openssl_random_pseudo_bytes( 16 );  // 16 bytes; https://en.wikipedia.org/wiki/Initialization_vector

  // Actual encryption of the payload
  $cipherbytes= openssl_encrypt( $plainbytes, ALGO_SSL, $hash, OPENSSL_RAW_DATA, $iv );

  // Adding a modification detection to the encrypted data in front of it; https://en.wikipedia.org/wiki/HMAC
  $hmac=        hash_hmac( ALGO_MSGAUTH, $cipherbytes. $iv, $hash, true );  // true = return bytes
  return $iv. $hmac. $cipherbytes;  // 16 + 32 + ? = 48 bytes minimum
}

function decrypt( $allbytes, $secretkey ) {
  // Preparations
  $hash=        hash( ALGO_SECRET, $secretkey. SALT, true );  // Same as in encryption
  $iv=          substr( $allbytes,  0, 16 );  // Cut into 3 pieces again
  $hmac=        substr( $allbytes, 16, 32 );
  $cipherbytes= substr( $allbytes, 48 );

  // Both extracted and recalculated modification detection values must match
  $hmac_recalc= hash_hmac( ALGO_MSGAUTH, $cipherbytes. $iv, $hash, true );  // Same as in encryption
  if( !hash_equals( $hmac_recalc, $hmac ) ) return null;  // Not equal? Payload must be considered tampered/modified/corrupted.

  // Actual decryption of the payload
  return openssl_decrypt( $cipherbytes, ALGO_SSL, $hash, OPENSSL_RAW_DATA, $iv );
}

我认为这是为了方便区分所有的单个项目以及加密和解密过程有多少是相同的。在 Delphi 或其他语言中执行相同的步骤应该不会那么困难-它也可以在两端不使用OpenSSL的情况下工作。
对于现成的例子,以及解释为什么从不处理文本,而只处理字节

inkz8wg9

inkz8wg92#

我在 Delphi 中尝试了DCPrijndael,在php中尝试了openssl_decrypt,但由于某种原因,它没有按预期工作。
经过多次尝试和错误,我终于使用TDCP_rijndael.EncryptCFB8bit在 Delphi 代码和openssl_decrypt与“aes-128-cfb 8”参数在php解码相同的数据和所有工作只是伟大的.
顺便说一句,我手动填充数据与零,所以我使用OPENSSL_ZERO_PADDING在解密功能。

相关问题