PHP code example of jatimprovcsirt / panda-php

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");



$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();

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
bash
# Hapus kunci dengan konfirmasi otomatis (hati-hati!)
php vendor/bin/panda shred old-deprecated-key --force
bash
# Migrasi batch processing dengan flags
php vendor/bin/panda migrate citizens nik default-key \
  --batch-size 500 \
  --delay 200 \
  --pk id \
  --dry-run

# Migrasi PostgreSQL dengan batch size custom
php vendor/bin/panda migrate users email email-key --batch-size 1000

# Migrasi dengan custom primary key
php vendor/bin/panda migrate transactions transaction_id txn-key --pk uuid
bash
php artisan panda:install
bash
php vendor/bin/panda init --token YOUR_TOKEN
bash
php artisan migrate
bash
php vendor/bin/panda init --token YOUR_TOKEN
bash
# php vendor/bin/panda migrate <table> <column> <kid>
php vendor/bin/panda migrate citizens nik opd-dukcapil-key-1