首页 > 解决方案 > 我需要哪种数据格式来解密存储在 MySQL DB 中的数据?

问题描述

我正在使用 PHP 7.1,研究加密/解密主题。我使用这个函数来编码/解码(基于 PHP 的官方文档):

$key = openssl_random_pseudo_bytes(16);

function encryptName($plaintext) {
  global $key;
  // $plaintext - string which must be encrypted

  $ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
  $iv = openssl_random_pseudo_bytes($ivlen);

  $ciphertext_raw = openssl_encrypt($plaintext, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);
  $hmac = hash_hmac('sha256', $ciphertext_raw, $key, $as_binary=true);
  $ciphertext = base64_encode( $iv.$hmac.$ciphertext_raw );
  return $ciphertext;
}

 function decryptName($ciphertext) {
    global $key;
    // $ciphertext - encrypted string

    $c = base64_decode($ciphertext);
    $ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
    $iv = substr($c, 0, $ivlen);

    $hmac = substr($c, $ivlen, $sha2len=32);
    $ciphertext_raw = substr($c, $ivlen+$sha2len);

    $original_plaintext = openssl_decrypt($ciphertext_raw, $cipher, $key, 
    $options=OPENSSL_RAW_DATA, $iv); // | OPENSSL_ZERO_PADDING
    $calcmac = hash_hmac('sha256', $ciphertext_raw, $key, $as_binary=true);

    if (hash_equals($hmac, $calcmac)) {
      //echo $original_plaintext."\n";
    }
    echo openssl_error_string();
    return $original_plaintext;  
}

当我 enc/dec strig "MyTestPhrase" 时,这两个函数都运行良好。但是当我加密数据然后将其写入 MySQL 表时,解密失败并出现以下错误代码:

error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length

和我的$original_plaintext平等bool(false)

我是这样想的。AES 适用于块。解密的字符串必须适合块长度:解密数据的大小必须是 16 的倍数。如果不是,我们必须激活 PHP 选项,用 0es 填充它。

猜猜这个问题可能与 MySQL 数据格式和加密字符串长度有关,但无法捕捉到它。

请帮我解决上面发布的问题。

标签: phpmysqlencryptionaes

解决方案


因此,在我的示例中,我使用 pseudo_bytes 创建了一个 base64_encoded 字符串。这样你的密钥是不变的。您可以创建自己的密钥,但对于这个 ex,我们将使用这个。LoPCPKd8iDxHvb8mATzhhg==

接下来我们将键定义为常量。这可以在脚本顶部或 conf.php 文件中完成。

接下来,我们将在需要密钥的任何地方使用常量值。

像这样:

define("MYKEY_", base64_decode('LoPCPKd8iDxHvb8mATzhhg=='));

function encryptName($plaintext) {

  $ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
  $iv = openssl_random_pseudo_bytes($ivlen);

  $ciphertext_raw = openssl_encrypt($plaintext, $cipher, MYKEY_, $options=OPENSSL_RAW_DATA, $iv);
  $hmac = hash_hmac('sha256', $ciphertext_raw, MYKEY_, $as_binary=true);
  $ciphertext = base64_encode( $iv.$hmac.$ciphertext_raw );
  return $ciphertext;
}

 function decryptName($ciphertext) {

    $c = base64_decode($ciphertext);
    $ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
    $iv = substr($c, 0, $ivlen);

    $hmac = substr($c, $ivlen, $sha2len=32);
    $ciphertext_raw = substr($c, $ivlen+$sha2len);

    $original_plaintext = openssl_decrypt($ciphertext_raw, $cipher, MYKEY_,
    $options=OPENSSL_RAW_DATA, $iv); // | OPENSSL_ZERO_PADDING
    $calcmac = hash_hmac('sha256', $ciphertext_raw, MYKEY_, $as_binary=true);

    if (hash_equals($hmac, $calcmac)) {
      //echo $original_plaintext."\n";
    }

    echo openssl_error_string();
    return $original_plaintext;
}

推荐阅读