我是 PHP 新手,正在编写 PHP 和 MYSQL 代码,该代码将加密的患者数据存储在 mysql 数据库中,然后在需要时检索它并将其显示给用户。 现在我有 2 个文件,第一个是我加密数据的地方
<?php
require_once "config.php";
require_once "session.php";
try {
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (isset($_SESSION["userid"])) {
$Patient_Number = $_SESSION["userid"];
$Date = $_POST["date"];
$encryptionKey = 'random_64_character_hexadecimal_key';
$Systolic_BP = bin2hex(openssl_random_pseudo_bytes(openssl_cipher_iv_length("aes-256-cbc"))) . ':' . bin2hex(openssl_encrypt($_POST["sys"], "aes-256-cbc", hex2bin($encryptionKey), 0, $iv, $tag));
$Diastolic_BP = bin2hex(openssl_random_pseudo_bytes(openssl_cipher_iv_length("aes-256-cbc"))) . ':' . bin2hex(openssl_encrypt($_POST["dia"], "aes-256-cbc", hex2bin($encryptionKey), 0, $iv, $tag));
$Respiratory_Rate = bin2hex(openssl_random_pseudo_bytes(openssl_cipher_iv_length("aes-256-cbc"))) . ':' . bin2hex(openssl_encrypt($_POST["rr"], "aes-256-cbc", hex2bin($encryptionKey), 0, $iv, $tag));
$Capillary_Refill = bin2hex(openssl_random_pseudo_bytes(openssl_cipher_iv_length("aes-256-cbc"))) . ':' . bin2hex(openssl_encrypt($_POST["cr"], "aes-256-cbc", hex2bin($encryptionKey), 0, $iv, $tag));
$Body_Temp = bin2hex(openssl_random_pseudo_bytes(openssl_cipher_iv_length("aes-256-cbc"))) . ':' . bin2hex(openssl_encrypt($_POST["temp"], "aes-256-cbc", hex2bin($encryptionKey), 0, $iv, $tag));
$Weight = bin2hex(openssl_random_pseudo_bytes(openssl_cipher_iv_length("aes-256-cbc"))) . ':' . bin2hex(openssl_encrypt($_POST["weight"], "aes-256-cbc", hex2bin($encryptionKey), 0, $iv, $tag));
$Pulse_Rate = bin2hex(openssl_random_pseudo_bytes(openssl_cipher_iv_length("aes-256-cbc"))) . ':' . bin2hex(openssl_encrypt($_POST["pulse"], "aes-256-cbc", hex2bin($encryptionKey), 0, $iv, $tag));
$Doctor_Name = bin2hex(openssl_random_pseudo_bytes(openssl_cipher_iv_length("aes-256-cbc"))) . ':' . bin2hex(openssl_encrypt($_POST["dn"], "aes-256-cbc", hex2bin($encryptionKey), 0, $iv, $tag));
$Symptoms = bin2hex(openssl_random_pseudo_bytes(openssl_cipher_iv_length("aes-256-cbc"))) . ':' . bin2hex(openssl_encrypt($_POST["symptoms"], "aes-256-cbc", hex2bin($encryptionKey), 0, $iv, $tag));
$Diagnosis = bin2hex(openssl_random_pseudo_bytes(openssl_cipher_iv_length("aes-256-cbc"))) . ':' . bin2hex(openssl_encrypt($_POST["diagnosis"], "aes-256-cbc", hex2bin($encryptionKey), 0, $iv, $tag));
$Medication = bin2hex(openssl_random_pseudo_bytes(openssl_cipher_iv_length("aes-256-cbc"))) . ':' . bin2hex(openssl_encrypt($_POST["medication"], "aes-256-cbc", hex2bin($encryptionKey), 0, $iv, $tag));
$error = "";
$insertQuery = $db->prepare("INSERT INTO medical_records (Date, Symptoms, Systolic_BP, Diastolic_BP, Respiratory_Rate, Capillary_Refill, Body_Temp, Weight, Pulse_Rate, Diagnosis, Medication, Doctor_Name, Patient_Number) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?); ");
if ($insertQuery === false) {
throw new Exception('Error preparing query: ' . $db->error);
}
$insertQuery->bind_param("ssssssssssssi", $Date, $Symptoms, $Systolic_BP, $Diastolic_BP, $Respiratory_Rate, $Capillary_Refill, $Body_Temp, $Weight, $Pulse_Rate, $Diagnosis, $Medication, $Doctor_Name, $Patient_Number);
$result = $insertQuery->execute();
if ($result) {
echo "Query executed successfully.";
$error .= '<p class="success">Your registration was successful!</p>';
header("Location: welcome.php");
exit;
} else {
$error .= '<p class="error">Something went wrong! ' . $insertQuery->error . '</p>';
}
$insertQuery->close();
mysqli_close($db);
} else {
echo "Patient_Number is not set in the session";
}
}
} catch (Exception $e) {
echo "Caught exception: " . $e->getMessage();
}
?>
第二个文件是我解密数据并以表格格式打印的地方。
<?php
require_once "config.php";
require_once "session.php";
if (!isset($_SESSION["userid"]) || empty($_SESSION["userid"])) {
header("location: login.php");
exit;
}
$Patient_Number = $_SESSION["userid"];
$user = [];
if (isset($_SESSION["user"])) {
$user = $_SESSION["user"];
}
$encryptionKey = 'same_random_64_character_hexadecimal_key_used_during_encryption';
if ($_SERVER["REQUEST_METHOD"] == "GET" && isset($_GET["Case_Number"])) {
$caseNumber = $_GET["Case_Number"];
$query = $db->prepare("SELECT * FROM medical_records WHERE Patient_Number = ? AND Case_Number = ?");
$query->bind_param("ii", $Patient_Number, $caseNumber);
$query->execute();
$result = $query->get_result();
if (!$result) {
echo "Error: " . $query->error;
exit;
}
if ($result->num_rows > 0) {
// Fetch the row as an associative array
$row = $result->fetch_array(MYSQLI_ASSOC);
// Decrypt the encrypted values
$decryptedRow = [];
foreach ($row as $key => $value) {
if (in_array($key, ['Case_Number', 'Date', 'Patient_Number'])) {
$decryptedRow[$key] = $value;
continue;
}
// Checking if the value is empty before decryption
if (!empty($value)) {
// Separating IV and encrypted value
$parts = explode(':', $value, 2);
// Checking if the array has at least two elements
if (count($parts) >= 2) {
// Extracting IV and encrypted value
list($iv, $encryptedValue) = $parts;
// Checking IV length
$expectedIvLength = openssl_cipher_iv_length("aes-256-cbc");
if (strlen($iv) === $expectedIvLength * 2) {
// Converting hexadecimal IV to binary
$ivBinary = hex2bin($iv);
// Checking if IV conversion was successful
if ($ivBinary === false) {
echo "Invalid IV format for key: $key\n";
} else {
$decryptedValue = openssl_decrypt(hex2bin($encryptedValue), 'aes-256-cbc', hex2bin($encryptionKey), 0, $ivBinary);
var_dump($decryptedValue);
// Checking if decryption was successful
if ($decryptedValue === false) {
echo "Decryption failed for key: $key\n";
echo "Error: " . openssl_error_string() . "\n";
} else {
// Decryption successful, store the decrypted value
$decryptedRow[$key] = $decryptedValue;
}
}
} else {
echo "Invalid IV length for key: $key\n";
}
} else {
// Handling the case where there are not enough parts in the array
echo "Invalid format for encrypted value: $value\n";
}
} else {
$decryptedRow[$key] = $value;
}
}
// Displaying decrypted values in a table
echo "<table border='1'>";
foreach ($decryptedRow as $key => $value) {
echo "<tr>";
echo "<td><strong>$key</strong>";
echo "<td>$value</td>";
echo "</tr>";
}
echo "</table>";
} else {
echo "Report not found.";
}
$query->close();
mysqli_close($db);
} else {
echo "Invalid request.";
}
?>
现在我面临的问题是,由于某种原因,在解密期间 openssl_decrypt() 函数返回 false;我不确定问题是什么。
我收到的错误是:
密钥解密失败:症状错误:错误:1C800064:提供程序例程::错误解密布尔(假)密钥解密失败:Systolic_BP错误:错误:1C800064:提供程序例程::错误解密布尔(假)密钥解密失败: Diastolic_BP 错误:错误:1C800064:提供程序例程::解密错误 bool(假) 密钥解密失败:Respiratory_Rate 错误:错误:1C800064:提供程序例程::解密错误布尔(假) 密钥解密失败:Capillary_Refill 错误:错误:1C800064 : 提供程序例程:: 错误解密 bool(false) 密钥解密失败:Body_Temp 错误:错误:1C800064:提供程序例程::错误解密 bool(false) 密钥解密失败:权重错误:错误:1C800064:提供程序例程::错误解密布尔(假)密钥解密失败:Pulse_Rate错误:错误:1C800064:提供程序例程::错误解密布尔(假)密钥解密失败:诊断错误:错误:1C800064:提供程序例程::错误解密布尔(假)解密密钥失败:药物错误:错误:1C800064:提供程序例程::解密错误 bool(假) 密钥解密失败:Doctor_Name 错误:错误:1C800064:提供程序例程::解密错误
供您参考,加密数据以以下格式存储
iv:加密数据
例如:
86f8589c55d009da3f46e039a1ee1218:2f5066596e5648414b5150633173516c4448593136513d3d
您使用了大量重复的代码,这是一个巨大的危险信号,您应该封装该逻辑,通常作为函数或方法。
正如评论中所述,您正在生成一个随机 IV,但没有使用它,至少据我所知。
我已经采用了您提供的代码(大部分按原样),并将其转换为加密和解密函数。我并不是说这些都是完美的,但应该能让你进步一点。我们生成一个 IV,在加密中使用它,并将其标记到字符串的前面。我也不太喜欢密码算法的制作方法,但它展示了如何抽象它,至少在某种程度上是这样。作为常数或类似值可能更好。
function encryptString(string $s, string $cipher_algo = "aes-256-cbc"): string
{
// Not a big fan, but I'm just trying to keep things simple
global $encryptionKey;
if (!$ivLength = openssl_cipher_iv_length($cipher_algo)) {
throw new Exception('Could not determine IV length');
}
if (!$iv = openssl_random_pseudo_bytes($ivLength)) {
throw new Exception('Could not generate IV');
}
if (!$encrypted = openssl_encrypt($s, $cipher_algo, hex2bin($encryptionKey), iv: $iv)) {
throw new Exception('Could not encrypt');
}
return sprintf(
"%s:%s",
bin2hex($iv),
bin2hex($encrypted),
);
}
function decryptString(string $s, string $cipher_algo = "aes-256-cbc"): string
{
// Not a big fan, but I'm just trying to keep things simple
global $encryptionKey;
if (!str_contains($s, ':')) {
throw new Exception('The provided string does not match the expected format');
}
[$iv, $encrypted] = explode(':', $s);
if (!$decrypted = openssl_decrypt(hex2bin($encrypted), $cipher_algo, hex2bin($encryptionKey), iv: hex2bin($iv),)) {
throw new Exception('Could not decrypt');
}
return $decrypted;
}
然后下面的代码展示了它的使用。密钥显然应该生成一次并安全存储。非常具体地说,将其正确存储在代码文件中会带来潜在的麻烦,因此请务必研究安全存储的方法。
// This would obviously be generated once and stored somewhere safe
$encryptionKey = bin2hex(openssl_random_pseudo_bytes(64));
$encrypted = encryptString('something');
$decrypted = decryptString($encrypted);
echo $encrypted, PHP_EOL, $decrypted, PHP_EOL;
OUTPUT:
960e4b3057968c90c7eef79cdeaaa124:32457554366e325771657479572f7656374e706a58773d3d
something