PHP中DES加密OFB模式异常及数据库存储为空问题求助
问题描述
我用PHP对HTML表单提交的数据做DES加密,测试时遇到两个问题:
- OFB模式加密结果无法正常显示(乱码/异常)
- 加密后的内容无法存入MySQL数据库,对应字段显示为NULL,即使移除加密解密输出代码,查询也看不到加密数据
问题1:OFB模式加密结果显示异常
原因
使用OPENSSL_RAW_DATA选项时,加密输出是二进制数据,直接echo会出现不可见字符或乱码——不止OFB,其他模式的二进制结果直接输出也会有同样问题。另外你代码里解密时重新生成了新IV,这是错误的,解密必须用加密时的同一个IV才能成功。
修复方法
把加密后的二进制数据用base64_encode()转成可打印字符串,解密时再用base64_decode()还原;同时将加密时生成的IV和密文拼接后一起编码存储,解密时拆分出IV再使用。
问题2:加密数据存入数据库为NULL
原因
- 二进制数据包含不可见字符,直接插入字符串类型字段会被截断或识别为无效数据
- 代码里写了两次
INSERT语句,第二次覆盖了第一次,导致根本没插入加密字段的数据 - 直接拼接SQL语句,存在SQL注入风险,且特殊字符会导致插入失败
修复方法
- 加密后用base64编码,把二进制转成字符串存储
- 合并
INSERT语句,同时插入需要的字段(明文/加密数据按需选择) - 使用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
相关产品推荐
相关产品推荐

