Aufbau biometrischer Verifizierungssysteme fuer Indonesien: Architektur und Rust-Patterns
Engineering Team
Aufbau des Backends fuer die biometrische SIM-Verifizierung in Indonesien
Dieser Artikel ist der dritte Teil der Serie ueber Indonesiens biometrische SIM-Pflicht und konzentriert sich auf die praktischen Architekturentscheidungen und Code-Implementierungen, die fuer den Aufbau eines produktionsreifen biometrischen Verifizierungssystems erforderlich sind. Wir vertiefen uns in Systemdesign, Datenfluesse, Verschluesselungspraktiken und skalierbare Backend-Dienste, die mit Rust und Axum erstellt werden.
Systemarchitektur-Ueberblick
Ein produktionsreifes biometrisches Verifizierungssystem besteht aus mehreren miteinander verbundenen Komponenten, die jeweils bestimmte Verantwortlichkeiten haben:
Kernkomponenten
- Erfassungsdienst (Mobile/Web-SDK) — Frontend-Komponente fuer die Gesichtsbilderfassung und geraeteseitige Lebendigkeitserkennung
- API-Gateway — Zentralisierte Authentifizierung, Ratenbegrenzung, Request-Routing und TLS-Terminierung
- Biometrische Verarbeitungs-Engine — Dienst zur Extraktion biometrischer Merkmals-Templates aus Gesichtsbildern
- Lebendigkeitserkennungsdienst — Fuehrt passive und aktive Lebendigkeitserkennungsmodelle aus
- IKD-Integrationsdienst — Behandelt die 1:1-Verifizierungskommunikation mit der indonesischen IKD-Plattform
- Verschluesselungsdienst — AES-256-Schluesselverwaltung, Template-Verschluesselung/Entschluesselung
- Audit-Log-Dienst — Protokolliert alle Verifizierungstransaktionen fuer die regulatorische Compliance
- Monitoring und Alerting — Systemzustand, Leistungsmetriken und Anomalieerkennung
Datenfluss-Architektur
Client-SDK → API-Gateway → Biometrische Engine → IKD-Plattform
↓ ↓ ↓
Ratenbegrenzung Verschluesselungsdienst Audit-Log
↓ ↓ ↓
Auth-Cache Schluesselverwaltung Compliance-Speicher
Rust-Backend-Implementierung
Projektstruktur
biometric-service/
├── Cargo.toml
├── src/
│ ├── main.rs # Einstiegspunkt und Server-Setup
│ ├── config.rs # Konfigurationsverwaltung
│ ├── routes/
│ │ ├── mod.rs
│ │ ├── verify.rs # Verifizierungsendpunkte
│ │ ├── health.rs # Gesundheitspruefung
│ │ └── admin.rs # Verwaltungsendpunkte
│ ├── services/
│ │ ├── mod.rs
│ │ ├── biometric.rs # Biometrische Verarbeitung
│ │ ├── liveness.rs # Lebendigkeitserkennung
│ │ ├── ikd.rs # IKD-Plattform-Client
│ │ ├── crypto.rs # Verschluesselungsoperationen
│ │ └── audit.rs # Audit-Protokollierung
│ ├── models/
│ ├── middleware/
│ └── errors.rs
├── migrations/
└── tests/
Kern-Verifizierungsendpunkt
use axum::{extract::State, Json};
use chrono::Utc;
use uuid::Uuid;
pub async fn verify_biometric(
State(state): State<AppState>,
Json(req): Json<VerificationRequest>,
) -> Result<Json<VerificationResponse>, AppError> {
let transaction_id = Uuid::new_v4();
let started_at = Utc::now();
req.validate()?;
let liveness = state.liveness_service
.detect(&req.capture_data)
.await
.map_err(|e| {
state.audit.log_failure(transaction_id, "liveness_failed", &e);
e
})?;
if !liveness.is_live {
return Err(AppError::LivenessCheckFailed);
}
let template = state.biometric_engine
.extract(&req.facial_image).await?;
let encrypted = state.crypto_service
.encrypt_template(&template).await?;
let ikd_result = state.ikd_client
.verify(&req.nik, &encrypted).await?;
let elapsed = Utc::now() - started_at;
state.audit.log_verification(AuditRecord {
transaction_id,
nik_hash: hash_nik(&req.nik),
liveness_score: liveness.confidence,
match_score: ikd_result.score,
verified: ikd_result.matched,
duration_ms: elapsed.num_milliseconds(),
timestamp: started_at,
}).await?;
Ok(Json(VerificationResponse {
transaction_id,
verified: ikd_result.matched,
confidence: ikd_result.score,
}))
}
AES-256-Verschluesselungsdienst
use aes_gcm::{Aes256Gcm, KeyInit, Nonce};
use aes_gcm::aead::Aead;
use rand::RngCore;
pub struct CryptoService {
cipher: Aes256Gcm,
}
impl CryptoService {
pub fn new(key: &[u8; 32]) -> Self {
let cipher = Aes256Gcm::new_from_slice(key)
.expect("AES-256 key must be 32 bytes");
Self { cipher }
}
pub async fn encrypt_template(
&self,
template: &BiometricTemplate,
) -> Result<EncryptedTemplate, CryptoError> {
let mut nonce_bytes = [0u8; 12];
rand::thread_rng().fill_bytes(&mut nonce_bytes);
let nonce = Nonce::from_slice(&nonce_bytes);
let plaintext = bincode::serialize(template)?;
let ciphertext = self.cipher
.encrypt(nonce, plaintext.as_ref())
.map_err(|_| CryptoError::EncryptionFailed)?;
Ok(EncryptedTemplate {
ciphertext,
nonce: nonce_bytes.to_vec(),
algorithm: "AES-256-GCM".into(),
})
}
}
Skalierbarkeit und Leistung
Mit ueber 270 Millionen Einwohnern und 345 Millionen aktiven SIM-Karten sind die Skalierungsanforderungen enorm:
- Spitzenlast-Schaetzung: Bei 50 Millionen Neuanmeldungen in den ersten 6 Monaten ca. 278.000 Verifizierungen pro Tag
- Spitzenzeiten: Peak 3-5x des Durchschnitts, also 830.000-1.390.000 pro Tag
- Anfragen pro Sekunde: Spitze ca. 16 TPS, mit Reserve fuer Burst-Traffic
UU PDP-Compliance-Implementierung
pub async fn cleanup_expired_records(
pool: &PgPool,
) -> Result<u64, sqlx::Error> {
let cutoff = Utc::now() - chrono::Duration::days(5 * 365);
let result = sqlx::query("DELETE FROM audit_logs WHERE created_at < $1")
.bind(cutoff).execute(pool).await?;
Ok(result.rows_affected())
}
pub async fn handle_deletion_request(
pool: &PgPool,
nik_hash: &str,
) -> Result<DeletionReport, AppError> {
let mut tx = pool.begin().await?;
let templates_deleted = sqlx::query(
"DELETE FROM biometric_templates WHERE nik_hash = $1"
).bind(nik_hash).execute(&mut *tx).await?.rows_affected();
let logs_anonymized = sqlx::query(
"UPDATE audit_logs SET nik_hash = 'anonymized' WHERE nik_hash = $1"
).bind(nik_hash).execute(&mut *tx).await?.rows_affected();
tx.commit().await?;
Ok(DeletionReport {
templates_deleted,
logs_anonymized,
completed_at: Utc::now(),
})
}
Bereitstellungsempfehlungen
Rechenzentren in Indonesien
Gemaess der KOMDIGI-Verordnung und UU PDP muss die biometrische Verarbeitung in indonesischen Rechenzentren erfolgen:
- Primaer: Jakarta (Naehe zu den meisten Nutzern und der IKD-Plattform)
- DR: Surabaya oder Bali (geografische Redundanz)
- CDN: Landesweite Edge-Knoten (fuer SDK-Verteilung und statische Ressourcen)
Fazit
Der Aufbau eines biometrischen Verifizierungssystems, das der KOMDIGI-Verordnung entspricht, ist eine komplexe, aber handhabbare Engineering-Herausforderung. Wichtigste Erkenntnisse:
- Sicherheit zuerst: AES-256-Verschluesselung, TLS 1.3-Uebertragung, Zero-Trust-Architektur
- Compliance-getrieben: UU PDP-Datenschutz, 5 Jahre Audit-Log-Aufbewahrung, Nutzer-Loeschrecht
- Skalierbares Design: Horizontale Skalierung, mehrstufiges Caching, asynchrone Verarbeitung
- Lokalisierte Bereitstellung: Indonesische Rechenzentren, Optimierung fuer niedrige Bandbreite, Unterstuetzung der Geraetevielfalt
- Umfassendes Monitoring: Echtzeit-Metriken, Anomalieerkennung, Compliance-Berichte
Mit Rust und Axum bietet dieses System hervorragende Leistungs- und Sicherheitsgarantien bei Einhaltung der strengen regulatorischen Anforderungen Indonesiens.