You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP中DES加密OFB模式异常及数据库存储为空问题求助

问题描述

我用PHP对HTML表单提交的数据做DES加密,测试时遇到两个问题:

  1. OFB模式加密结果无法正常显示(乱码/异常)
  2. 加密后的内容无法存入MySQL数据库,对应字段显示为NULL,即使移除加密解密输出代码,查询也看不到加密数据

问题1:OFB模式加密结果显示异常

原因

使用OPENSSL_RAW_DATA选项时,加密输出是二进制数据,直接echo会出现不可见字符或乱码——不止OFB,其他模式的二进制结果直接输出也会有同样问题。另外你代码里解密时重新生成了新IV,这是错误的,解密必须用加密时的同一个IV才能成功。

修复方法

把加密后的二进制数据用base64_encode()转成可打印字符串,解密时再用base64_decode()还原;同时将加密时生成的IV和密文拼接后一起编码存储,解密时拆分出IV再使用。


问题2:加密数据存入数据库为NULL

原因

  1. 二进制数据包含不可见字符,直接插入字符串类型字段会被截断或识别为无效数据
  2. 代码里写了两次INSERT语句,第二次覆盖了第一次,导致根本没插入加密字段的数据
  3. 直接拼接SQL语句,存在SQL注入风险,且特殊字符会导致插入失败

修复方法

  1. 加密后用base64编码,把二进制转成字符串存储
  2. 合并INSERT语句,同时插入需要的字段(明文/加密数据按需选择)
  3. 使用mysqli预处理语句,避免SQL注入,确保数据正确插入

修正后的完整代码

<?php
date_default_timezone_set('America/Bogota');
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "TallerFB";

// 初始化数据库连接
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
    die("Error en la conexión a la base de datos: " . $conn->connect_error);
}

// 获取表单数据
$fecha_hora = date('Y-m-d H:i:s');
$banco_origen = $_POST['banco_origen'];
$cuenta_origen = $_POST['cuenta_origen'];
$tipo_cuenta_origen = $_POST['tipo_cuenta_origen'];
$banco_destino = $_POST['banco_destino'];
$cuenta_destino = $_POST['cuenta_destino'];
$tipo_cuenta_destino = $_POST['tipo_cuenta_destino'];
$numero_identificacion = $_POST['numero_identificacion'];
$valor_transaccion = $_POST['valor_transaccion'];
$cus = $_POST['cus'];
$descripcion = $_POST['descripcion'];

// 拼接待加密的原始数据
$raw_data = $fecha_hora . $banco_origen . $cuenta_origen . $tipo_cuenta_origen . 
            $banco_destino . $cuenta_destino . $tipo_cuenta_destino . $numero_identificacion . 
            $valor_transaccion . $cus . $descripcion;

$clave = "BlOcKcH4!n$";

// -------------------------- 加密处理 --------------------------
// CBC模式:保存IV+密文,转base64
$iv_cbc = openssl_random_pseudo_bytes(openssl_cipher_iv_length('des-cbc'));
$cifrado_cbc = openssl_encrypt($raw_data, 'des-cbc', $clave, OPENSSL_RAW_DATA, $iv_cbc);
$cifrado_cbc_base64 = base64_encode($iv_cbc . $cifrado_cbc);

// ECB模式:无需IV,直接转base64
$cifrado_ecb = openssl_encrypt($raw_data, 'des-ecb', $clave, OPENSSL_RAW_DATA);
$cifrado_ecb_base64 = base64_encode($cifrado_ecb);

// CFB模式:保存IV+密文,转base64
$iv_cfb = openssl_random_pseudo_bytes(openssl_cipher_iv_length('des-cfb'));
$cifrado_cfb = openssl_encrypt($raw_data, 'des-cfb', $clave, OPENSSL_RAW_DATA, $iv_cfb);
$cifrado_cfb_base64 = base64_encode($iv_cfb . $cifrado_cfb);

// OFB模式:保存IV+密文,转base64
$iv_ofb = openssl_random_pseudo_bytes(openssl_cipher_iv_length('des-ofb'));
$cifrado_ofb = openssl_encrypt($raw_data, 'des-ofb', $clave, OPENSSL_RAW_DATA, $iv_ofb);
$cifrado_ofb_base64 = base64_encode($iv_ofb . $cifrado_ofb);

// 显示加密结果(base64编码后可正常显示)
echo "Texto cifrado CBC: " . $cifrado_cbc_base64 . "<br>";
echo "Texto cifrado ECB: " . $cifrado_ecb_base64 . "<br>";
echo "Texto cifrado CFB: " . $cifrado_cfb_base64 . "<br>";
echo "Texto cifrado OFB: " . $cifrado_ofb_base64 . "<br><br>";

// -------------------------- 解密处理 --------------------------
// CBC解密:拆分IV和密文
$cbc_decoded = base64_decode($cifrado_cbc_base64);
$iv_cbc_decrypt = substr($cbc_decoded, 0, openssl_cipher_iv_length('des-cbc'));
$cifrado_cbc_decrypt = substr($cbc_decoded, openssl_cipher_iv_length('des-cbc'));
$datos_descifrados_cbc = openssl_decrypt($cifrado_cbc_decrypt, 'des-cbc', $clave, OPENSSL_RAW_DATA, $iv_cbc_decrypt);

// ECB解密
$cifrado_ecb_decrypt = base64_decode($cifrado_ecb_base64);
$datos_descifrados_ecb = openssl_decrypt($cifrado_ecb_decrypt, 'des-ecb', $clave, OPENSSL_RAW_DATA);

// CFB解密:拆分IV和密文
$cfb_decoded = base64_decode($cifrado_cfb_base64);
$iv_cfb_decrypt = substr($cfb_decoded, 0, openssl_cipher_iv_length('des-cfb'));
$cifrado_cfb_decrypt = substr($cfb_decoded, openssl_cipher_iv_length('des-cfb'));
$datos_descifrados_cfb = openssl_decrypt($cifrado_cfb_decrypt, 'des-cfb', $clave, OPENSSL_RAW_DATA, $iv_cfb_decrypt);

// OFB解密:拆分IV和密文
$ofb_decoded = base64_decode($cifrado_ofb_base64);
$iv_ofb_decrypt = substr($ofb_decoded, 0, openssl_cipher_iv_length('des-ofb'));
$cifrado_ofb_decrypt = substr($ofb_decoded, openssl_cipher_iv_length('des-ofb'));
$datos_descifrados_ofb = openssl_decrypt($cifrado_ofb_decrypt, 'des-ofb', $clave, OPENSSL_RAW_DATA, $iv_ofb_decrypt);

// 显示解密结果
echo "Datos descifrados CBC: " . $datos_descifrados_cbc . "<br>";
echo "Datos descifrados ECB: " . $datos_descifrados_ecb . "<br>";
echo "Datos descifrados CFB: " . $datos_descifrados_cfb . "<br>";
echo "Datos descifrados OFB: " . $datos_descifrados_ofb . "<br><br>";

// -------------------------- 数据库插入 --------------------------
// 使用预处理语句,同时插入明文和加密数据(按需调整字段)
$sql = "INSERT INTO transacciones (fecha_hora, banco_origen, cuenta_origen, tipo_cuenta_origen, banco_destino, cuenta_destino, tipo_cuenta_destino, numero_identificacion, valor_transaccion, cus, descripcion, cifrado_cbc, cifrado_ecb, cifrado_cfb, cifrado_ofb)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

$stmt = $conn->prepare($sql);
$stmt->bind_param("sssssssssssssss", 
    $fecha_hora, $banco_origen, $cuenta_origen, $tipo_cuenta_origen, 
    $banco_destino, $cuenta_destino, $tipo_cuenta_destino, $numero_identificacion, 
    $valor_transaccion, $cus, $descripcion, 
    $cifrado_cbc_base64, $cifrado_ecb_base64, $cifrado_cfb_base64, $cifrado_ofb_base64);

if ($stmt->execute()) {
    echo "Transacción registrada correctamente.";
    unset($_POST);
} else {
    echo "Error al registrar la transacción: " . $stmt->error;
}

// 关闭连接
$stmt->close();
$conn->close();
?>
<br>
<a href="inicio.php">Click aquí para realizar otra transacción</a>

内容的提问来源于stack exchange,提问作者SERGIO ANDRES VALDERRAMA VELEZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 06:02:05