FHM31052601IBL - implementasi enkripsi PII pasien dan data medis (UU PDP)
- Tambah .env loader di index.php untuk IBL_ENCRYPT_KEY dan IBL_ENCRYPT_SEARCH_KEY - Library Ibl_encryptor: AES-256-GCM encrypt/decrypt + trigram blind index untuk partial search - SQL migration: tambah kolom _enc dan _bidx di 16 tabel (m_patient, m_patientaddress, hasil lab, log) - Script backup_pdp_tables.sh: backup tabel terdampak sebelum migrasi - Script migrate_encrypt_patient.php: enkripsi batch 178K data PII pasien - Script migrate_encrypt_results.php: enkripsi data medis hasil lab dan log - Patient.php: search via trigram blind index, add_new/edit enkripsi sebelum save Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
123
scripts/migrate_encrypt_patient.php
Normal file
123
scripts/migrate_encrypt_patient.php
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
/**
|
||||
* Batch migration: enkripsi PII m_patient dan m_patientaddress
|
||||
* Jalankan via: php scripts/migrate_encrypt_patient.php
|
||||
* Aman dijalankan berulang: skip row yang sudah ada _enc-nya
|
||||
*/
|
||||
|
||||
// Load .env
|
||||
$env_file = __DIR__ . '/../.env';
|
||||
if (!file_exists($env_file)) {
|
||||
die("ERROR: .env tidak ditemukan di " . realpath(__DIR__ . '/..') . PHP_EOL);
|
||||
}
|
||||
foreach (file($env_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $l) {
|
||||
if (strpos(trim($l), '#') === 0) continue;
|
||||
[$k, $v] = array_map('trim', explode('=', $l, 2));
|
||||
if ($k !== '') $_ENV[$k] = $v;
|
||||
}
|
||||
|
||||
define('BASEPATH', true);
|
||||
require __DIR__ . '/../application/libraries/Ibl_encryptor.php';
|
||||
$enc = new Ibl_encryptor();
|
||||
|
||||
// DB connection dari config CI
|
||||
include __DIR__ . '/../application/config/database.php';
|
||||
$cfg = $db['default'];
|
||||
$pdo = new PDO(
|
||||
"mysql:host={$cfg['hostname']};dbname={$cfg['database']};charset=utf8",
|
||||
$cfg['username'],
|
||||
$cfg['password'],
|
||||
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
|
||||
);
|
||||
|
||||
$batch = 500;
|
||||
|
||||
// ============================================================
|
||||
// m_patient
|
||||
// ============================================================
|
||||
echo "=== Migrasi m_patient ===\n";
|
||||
$total = 0;
|
||||
|
||||
$stmt_upd = $pdo->prepare("UPDATE m_patient SET
|
||||
M_PatientName_enc = ?, M_PatientName_bidx = ?,
|
||||
M_PatientHP_enc = ?, M_PatientHP_bidx = ?,
|
||||
M_PatientDOB_enc = ?, M_PatientDOB_bidx = ?,
|
||||
M_PatientEmail_enc = ?,
|
||||
M_PatientPhone_enc = ?,
|
||||
M_PatientPOB_enc = ?,
|
||||
M_PatientIDNumber_enc = ?,
|
||||
M_PatientNIK_enc = ?,
|
||||
M_PatientNIP_enc = ?
|
||||
WHERE M_PatientID = ?");
|
||||
|
||||
while (true) {
|
||||
$rows = $pdo->query(
|
||||
"SELECT M_PatientID, M_PatientName, M_PatientHP, M_PatientDOB,
|
||||
M_PatientEmail, M_PatientPhone, M_PatientPOB,
|
||||
M_PatientIDNumber, M_PatientNIK, M_PatientNIP
|
||||
FROM m_patient
|
||||
WHERE M_PatientName_enc IS NULL
|
||||
LIMIT $batch"
|
||||
)->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
if (empty($rows)) break;
|
||||
|
||||
foreach ($rows as $row) {
|
||||
$dob_str = $row['M_PatientDOB'] ? date('d-m-Y', strtotime($row['M_PatientDOB'])) : '';
|
||||
$stmt_upd->execute([
|
||||
$enc->encrypt($row['M_PatientName']), $enc->search_bidx($row['M_PatientName']),
|
||||
$enc->encrypt($row['M_PatientHP']), $enc->search_bidx($row['M_PatientHP']),
|
||||
$enc->encrypt($dob_str), $enc->search_bidx($dob_str),
|
||||
$enc->encrypt($row['M_PatientEmail']),
|
||||
$enc->encrypt($row['M_PatientPhone']),
|
||||
$enc->encrypt($row['M_PatientPOB']),
|
||||
$enc->encrypt($row['M_PatientIDNumber']),
|
||||
$enc->encrypt($row['M_PatientNIK']),
|
||||
$enc->encrypt($row['M_PatientNIP']),
|
||||
$row['M_PatientID'],
|
||||
]);
|
||||
$total++;
|
||||
}
|
||||
echo " {$total} rows...\n";
|
||||
}
|
||||
echo "m_patient selesai: {$total} rows\n\n";
|
||||
|
||||
// ============================================================
|
||||
// m_patientaddress
|
||||
// ============================================================
|
||||
echo "=== Migrasi m_patientaddress ===\n";
|
||||
$total = 0;
|
||||
|
||||
$stmt_addr = $pdo->prepare("UPDATE m_patientaddress SET
|
||||
M_PatientAddressDescription_enc = ?,
|
||||
M_PatientAddressDescription_bidx = ?,
|
||||
M_PatientAddressEmail_enc = ?,
|
||||
M_PatientAddressPhone_enc = ?
|
||||
WHERE M_PatientAddressID = ?");
|
||||
|
||||
while (true) {
|
||||
$rows = $pdo->query(
|
||||
"SELECT M_PatientAddressID, M_PatientAddressDescription,
|
||||
M_PatientAddressEmail, M_PatientAddressPhone
|
||||
FROM m_patientaddress
|
||||
WHERE M_PatientAddressDescription_enc IS NULL
|
||||
LIMIT $batch"
|
||||
)->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
if (empty($rows)) break;
|
||||
|
||||
foreach ($rows as $row) {
|
||||
$stmt_addr->execute([
|
||||
$enc->encrypt($row['M_PatientAddressDescription']),
|
||||
$enc->search_bidx($row['M_PatientAddressDescription']),
|
||||
$enc->encrypt($row['M_PatientAddressEmail']),
|
||||
$enc->encrypt($row['M_PatientAddressPhone']),
|
||||
$row['M_PatientAddressID'],
|
||||
]);
|
||||
$total++;
|
||||
}
|
||||
echo " {$total} rows...\n";
|
||||
}
|
||||
echo "m_patientaddress selesai: {$total} rows\n\n";
|
||||
|
||||
echo "=== Migrasi patient PII selesai ===\n";
|
||||
Reference in New Issue
Block a user