1. Go to this page and download the library: Download jatimprovcsirt/panda-php library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
jatimprovcsirt / panda-php example snippets
use Panda\Crypto\InfisicalKeyProvider;
use Panda\Crypto\FieldCipher;
// Baca dari environment variables atau config
$keyProvider = new InfisicalKeyProvider(
siteUrl: 'https://app.infisical.com',
clientId: $_ENV['PANDA_INFISICAL_CLIENT_ID'],
clientSecret: $_ENV['PANDA_INFISICAL_CLIENT_SECRET'],
projectId: $_ENV['PANDA_INFISICAL_PROJECT_ID'],
environment: $_ENV['PANDA_INFISICAL_ENVIRONMENT'],
cacheTTL: 300 // optional
);
$cipher = new FieldCipher($keyProvider);
// Sisa kode tetap sama
$envelope = $cipher->encrypt("3201012501990001", "nik-key");
use Panda\Crypto\LocalKeyProvider;
use Panda\Crypto\FieldCipher;
// 1. KeyProvider reads PANDA_KEY_... from the environment
$keyProvider = new LocalKeyProvider();
// 2. FieldCipher handles encryption, decryption, and auditing
$cipher = new FieldCipher($keyProvider);
$rawNik = '3201012501990001';
$kid = 'opd-dukcapil-key-1';
$envelope = $cipher->encrypt($rawNik, $kid);
$jsonForDatabase = $envelope->toJson();
// Store $jsonForDatabase in your database!
use Panda\Crypto\Envelope;
$row = $db->query("SELECT nik FROM citizens WHERE id = 1")->fetch();
$envelope = Envelope::fromJson($row['nik']);
// A. Decrypt with default masking (for safe displaying/logs)
$masked = $cipher->decrypt($envelope);
echo $masked; // Output: "32************01"
// B. Decrypt raw unmasked plaintext (for exports/audited API use)
$raw = $cipher->decryptRaw($envelope);
echo $raw; // Output: "3201012501990001"
use Panda\BlindIndex\BlindIndexer;
// Note: The blind index key is distinct and uses the "-idx" suffix
$blindIndexKid = 'opd-dukcapil-key-1-idx';
$blindIndexKey = $keyProvider->getKey($blindIndexKid);
// 1. Compute blind index during INSERT/UPDATE
$blindIndexValue = BlindIndexer::generate($rawNik, $blindIndexKey, 'digits');
// Store both $jsonForDatabase in 'nik' AND $blindIndexValue in 'nik_bidx'!
// 2. Querying by NIK
$searchQuery = '3201012501990001';
$searchHash = BlindIndexer::generate($searchQuery, $blindIndexKey, 'digits');
// Execute SQL lookup:
$stmt = $pdo->prepare("SELECT * FROM citizens WHERE nik_bidx = :hash");
$stmt->execute(['hash' => $searchHash]);
$results = $stmt->fetchAll();
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Panda\Integrations\Laravel\EncryptedCast;
use Panda\Integrations\Laravel\HasEncryptedFields;
class Citizen extends Model
{
use HasEncryptedFields;
protected $casts = [
// Specify the key identifier (KID) to encrypt this column
'nik' => EncryptedCast::class . ':default-key',
];
// Configure the automatic blind indexing for search lookups:
protected $encryptedFields = [
'nik' => [
'kid' => 'default-key',
'blind_index' => true, // Automatically syncs 'nik_bidx'
'normalization' => 'digits', // Normalization function (e.g. digits, lowercase, trim)
],
];
}
$citizen = new Citizen();
$citizen->nik = '3201012501990001';
$citizen->save(); // Automatically saves encrypted envelope in 'nik' and blind index in 'nik_bidx'
$citizen = Citizen::first();
echo $citizen->nik; // Output: "32************01" (Masked by default)
// Get raw decrypted value
echo $citizen->getRawEncrypted('nik'); // Output: "3201012501990001"
// Use the whereEncrypted query scope
$citizens = Citizen::whereEncrypted('nik', '3201012501990001')->get();
use Panda\Integrations\Laravel\Rules\UniqueEncrypted;
$request->validate([
'nik' => ['
use Panda\Integrations\CodeIgniter\PandaService;
$cipher = PandaService::fieldCipher();
use Panda\BlindIndex\BlindIndexer;
use Panda\Crypto\LocalKeyProvider;
$rawNik = '3201012501990001';
$kid = 'opd-dukcapil-key-1';
// 1. Encrypt raw text
$envelope = $cipher->encrypt($rawNik, $kid);
$encryptedJson = $envelope->toJson();
// 2. Generate blind index hash
$keyProvider = new LocalKeyProvider();
$blindIndexKey = $keyProvider->getKey("{$kid}-idx");
$blindIndexHash = BlindIndexer::generate($rawNik, $blindIndexKey, 'digits');
// 3. Save to Database
$db = \Config\Database::connect();
$db->table('citizens')->insert([
'nik' => $encryptedJson,
'nik_bidx' => $blindIndexHash,
]);
use Panda\Crypto\Envelope;
$searchQuery = '3201012501990001';
// 1. Hash the search value
$keyProvider = new LocalKeyProvider();
$blindIndexKey = $keyProvider->getKey("opd-dukcapil-key-1-idx");
$searchHash = BlindIndexer::generate($searchQuery, $blindIndexKey, 'digits');
// 2. Perform query lookup
$db = \Config\Database::connect();
$row = $db->table('citizens')
->where('nik_bidx', $searchHash)
->get()
->getRow();
if ($row) {
$envelope = Envelope::fromJson($row->nik);
// A. Masked value
echo $cipher->decrypt($envelope); // Output: "32************01"
// B. Raw unmasked value
echo $cipher->decryptRaw($envelope); // Output: "3201012501990001"
}
Schema::table('citizens', function (Blueprint $table) {
$table->text('nik')->change();
$table->string('nik_bidx', 64)->nullable()->index();
});
// Loop through rows missing the blind index and trigger a save (which automatically computes the bidx)
foreach (Citizen::whereNull('nik_bidx')->cursor() as $citizen) {
$citizen->save();
}
$db = \Config\Database::connect();
$rows = $db->table('citizens')->where('nik_bidx', null)->get()->getResult();
foreach ($rows as $row) {
$envelope = Envelope::fromJson($row->nik);
// Decrypt to get raw value
$rawVal = $cipher->decryptRaw($envelope);
// Calculate blind index
$blindIndexHash = BlindIndexer::generate($rawVal, $blindIndexKey, 'digits');
// Update
$db->table('citizens')
->where('id', $row->id)
->update(['nik_bidx' => $blindIndexHash]);
}
bash
composer
bash
# Menggunakan binary CLI dari vendor (setelah composer install)
php vendor/bin/panda init --token YOUR_TOKEN
bash
# Rotasi: buat kunci baru dan set sebagai default KID aktif
php vendor/bin/panda rotate-key --new-kid opd-dukcapil-key-2
bash
# Hapus kunci secara permanen
# PERINGATAN: Data yang dienkripsi dengan kunci ini tidak bisa didekripsi lagi!
php vendor/bin/panda shred opd-dukcapil-key-old