ePassport Çipinden Dijital Seyahat Kimliğine: NFC, Passive Authentication ve Veri Normalizasyonu
Çalışan Digital Travel prototipi üzerinden ePassport çip erişimini, okuyucu cevabının normalize edilmesini, Passive Authentication güven zincirini ve doğrulanmış veriden Passport Credential üretmenin doğru mimari sınırlarını inceliyoruz.
Digital Travel Architecture — Bölüm 1
Temassız seyahat deneyimi çoğu sunumda yolcunun telefonundaki dijital kimlik veya havalimanındaki yüz doğrulama kapısıyla başlatılır. Oysa güven zincirinin ilk kritik noktası daha geridedir: fiziksel ePassport içindeki verinin doğru okunması, kriptografik olarak doğrulanması ve uygulamanın geri kalanına kontrollü bir veri modeli olarak aktarılması.
Bu yazıda çalışan bir FastAPI prototipindeki pasaport çipi okuma akışını referans alarak şu soruya cevap arıyoruz: Bir ePassport okuyucusundan gelen ham sonuç, ileride dijital cüzdana eklenecek bir Passport Credential için nasıl güvenilir bir girdiye dönüştürülür?
1. Mimari sınırı doğru çizmek
Demo uygulamada React arayüzü pasaport numarası, doğum tarihi ve geçerlilik tarihi alanlarını backend'e gönderiyor. FastAPI katmanı bu değerleri çip okuyucu servisin beklediği biçime dönüştürüyor, yerel bir ePassport okuma servisini çağırıyor ve dönen sonucu normalize ediyor.
React istemcisi
│ belge no + doğum tarihi + son geçerlilik tarihi
▼
FastAPI /issuer/passport-chip-read
│ alan dönüşümü ve servis çağrısı
▼
ePassport okuma servisi / NFC okuyucu
│ LDS veri grupları + EF.SOD + doğrulama sonucu
▼
Normalize edilmiş pasaport modeli
│
├── kullanıcıya gösterilecek biyografik alanlar
├── biyometrik kayıt için portre
└── credential issuance için güvenlik sonucu
Bu ayrım önemlidir. FastAPI katmanı NFC protokollerini yeniden uygulamıyor; belge okuyucu entegrasyonu ile dijital seyahat uygulaması arasında bir anti-corruption layer görevi görüyor. Okuyucuya özgü alan adlarını, tarih biçimlerini ve hata nesnelerini uygulamanın geri kalanının anlayacağı kararlı bir sözleşmeye çeviriyor.
2. Çipe erişim: üç alan neden gerekli?
Prototipte kullanıcıdan belge numarası, doğum tarihi ve son geçerlilik tarihi alınıyor. Bu üç değer MRZ tabanlı erişim anahtarı üretiminde kullanılan temel girdilerdir. Kod, ISO tarihlerini okuyucu servisinin beklediği altı haneli YYMMDD biçimine dönüştürüyor:
def to_chip_date(date_text: str) -> str:
for fmt in ("%d.%m.%Y", "%Y-%m-%d"):
try:
parsed = datetime.strptime(date_text, fmt)
return parsed.strftime("%y%m%d")
except ValueError:
continue
raise ValueError("Unsupported date format")
Demo kodu parse edilemeyen değeri olduğu gibi okuyucuya iletiyor. Üretim sisteminde bu yaklaşım yerine istek daha dış sınırda reddedilmelidir. Aksi halde bir biçim hatası, erişim protokolü hatası gibi görünür ve gözlemlenebilirliği bozar.
Bu alanlar çipteki veriyi güvenilir ilan etmez. Yalnızca BAC veya PACE gibi erişim mekanizmalarının kurulabilmesi için gerekli girdiyi sağlar. Erişim kontrolü, haberleşme kanalının kurulması ve Passive Authentication birbirinden farklı güvenlik kontrolleridir.
3. Ham okuyucu cevabını normalize etmek
Okuyucu servisleri çoğu zaman donanım üreticisine, kütüphaneye veya ülkeye özgü alan isimleri döndürür. Referans uygulamada Ad, Soyad, Uyruk, Belge_Numarasi, Dogum_Tarihi, IMAGE ve passiveAuth alanları tek bir Pydantic modeline aktarılıyor.
class PassportChipNormalized(BaseModel):
given_name: str
family_name: str
nationality: str
passport_number: str
date_of_birth: str
expiry_date: str
place_of_birth: str | None = None
portrait_b64: str | None = None
passive_auth_ok: bool
passive_auth_error: str | None = None
Normalize katmanının üç faydası vardır:
- Frontend, okuyucu üreticisinin alan adlarına bağımlı kalmaz.
- Credential, check-in ve biyometri servisleri aynı kanonik veri modelini kullanır.
- Okuyucu değiştiğinde dönüşüm yalnızca entegrasyon katmanında güncellenir.
Ancak prototipteki raw cevap ve Base64 portreyi istemciye geri döndürmek üretim için uygun değildir. Ham cevap debug ortamıyla sınırlandırılmalı; portre ise amaç, saklama süresi ve erişim politikası belirlenmeden loglara, tarayıcı durumuna veya genel API cevabına taşınmamalıdır.
4. Passive Authentication gerçekte neyi kanıtlar?
ICAO'ya göre Passive Authentication, ePassport çipindeki verinin bütünlüğünü ve düzenleyen makamdan geldiğini dijital imza üzerinden doğrular. Basitleştirilmiş zincir şöyledir:
Güvenilen CSCA sertifikası
│ doğrular
▼
Document Signer Certificate (DSC)
│ EF.SOD üzerindeki imzayı doğrular
▼
Document Security Object
│ beklenen hash değerlerini taşır
▼
DG1, DG2 ve okunan diğer Data Group'lar
İnceleme sistemi önce EF.SOD içindeki imzayı Document Signer sertifikasıyla doğrular. Ardından DS sertifikasının güvenilen ülke kök sertifikası CSCA'ya bağlandığını kontrol eder. Son olarak okunan veri gruplarının hash değerleri EF.SOD içindeki değerlerle karşılaştırılır. Güncel CRL bilgileri de sertifika durum değerlendirmesinin parçası olmalıdır.
Bu kontrol başarılıysa şu iki sonuç desteklenir:
- Okunan veri, yetkili düzenleyici tarafından imzalanan belge verisiyle tutarlıdır.
- İmzalama sonrasında ilgili veri grubu değiştirilmemiştir.
Fakat Passive Authentication tek başına çipin klon olmadığını kanıtlamaz. ICAO, kopya çip tespitinin desteklenen belgeye göre Active Authentication, Chip Authentication veya PACE Chip Authentication Mapping gibi ek mekanizmalar gerektirebileceğini açıkça ayırır. Aynı şekilde başarılı Passive Authentication, belgeyi taşıyan kişinin portredeki kişi olduğunu da kanıtlamaz; bunun için canlı yüz, DG2 portresi ve uygun biyometrik karşılaştırma politikası gerekir.
5. Boolean sonuç neden yetersiz kalır?
Referans kod, okuyucunun failureReason alanı yoksa passive_auth_ok=True kabul ediyor. Demo için anlaşılır olan bu yaklaşım, üretimde yanlış pozitif üretebilir. “Hata alanı gelmedi” ile “bütün kriptografik kontroller başarıyla tamamlandı” aynı şey değildir.
Daha sağlam bir sonuç modeli her adımı ayrı taşır:
class PassiveAuthResult(BaseModel):
sod_signature_valid: bool
ds_certificate_valid: bool
csca_trust_anchor_found: bool
revocation_status: str
data_group_hashes: dict[str, bool]
overall_status: Literal["valid", "invalid", "indeterminate"]
failure_codes: list[str]
indeterminate özellikle önemlidir. Örneğin CSCA güven noktası bulunamaması, veri grubunun değiştirilmiş olmasıyla aynı operasyonel sonuç değildir. İlki trust-store veya sertifika dağıtım sorunu olabilir; ikincisi doğrudan bütünlük ihlaline işaret edebilir. Bu ayrım, otomatik kararın yanında doğru manuel inceleme kuyruğunu da belirler.
6. Passport Credential ne zaman üretilebilir?
Prototipte çip okuma endpointi ile Passport Credential üreten endpoint birbirinden bağımsızdır. Credential alanları kullanıcı formundan gönderildiği için, teknik olarak çip okunmadan veya Passive Authentication başarısızken de credential üretilebilir. Bu nokta demo ile güvenilir üretim mimarisi arasındaki en önemli sınırdır.
Üretimde issuance işlemi, istemciden tekrar gönderilen biyografik alanlara değil sunucu tarafında doğrulanmış kısa ömürlü bir okuma oturumuna bağlanmalıdır:
chip_session = chip_sessions.get(request.chip_session_id)
if chip_session.passive_auth.overall_status != "valid":
raise IssuanceDenied("Chip authenticity is not established")
credential = issue_passport_credential(
subject=authenticated_wallet_holder,
claims=chip_session.verified_claims,
evidence={
"method": "eMRTD-passive-authentication",
"verified_at": chip_session.verified_at,
"reader_id": chip_session.reader_id,
},
)
Bu modelde tarayıcı, ad-soyad veya belge numarasını yeniden belirleyen otorite değildir. İstemci yalnızca doğrulanan oturumu ve credential'ın bağlanacağı cüzdanı işaret eder. Issuer, claim'leri kendi güvenilir sunucu durumundan alır.
7. Üretim için güvenlik kontrol listesi
- Çip okuyucu servisi yalnızca yerel adrese güvenilerek değil, karşılıklı TLS ve servis kimliğiyle korunmalı.
- MRZ/CAN girdileri loglarda maskelenmeli; portre ve ham LDS verisi varsayılan olarak loglanmamalı.
- CSCA, DSC, Master List ve CRL güncelleme süreçleri izlenebilir ve sürümlü olmalı.
- Passive Authentication sonucu ayrıntılı hata kodlarıyla saklanmalı; başarısız ve belirsiz durumlar ayrılmalı.
- Credential yalnızca doğrulanmış chip session üzerinden ve kullanıcı/cüzdan doğrulaması sonrasında üretilmeli.
- Portre kullanımı açık rıza, amaç sınırlaması, minimum saklama ve silme politikasıyla yönetilmeli.
- Reader, issuer ve wallet arasındaki tüm çağrılar correlation ID ile denetlenebilir olmalı.
Sonuç
ePassport çipini okumak, dijital seyahat kimliği üretmek için gerekli fakat tek başına yeterli olmayan bir adımdır. Güvenilir mimari; erişim protokolünü, veri normalizasyonunu, Passive Authentication sonucunu ve credential issuance kararını ayrı katmanlar olarak ele alır. En kritik tasarım ilkesi şudur: Credential içindeki iddialar tarayıcı formundan değil, kriptografik olarak doğrulanmış belge oturumundan gelmelidir.
Serinin sonraki bölümünde bu doğrulanmış verinin Passport Credential'a nasıl dönüştürülebileceğini; Issuer–Holder–Verifier rollerini, JWT tabanlı demo yaklaşımını ve gerçek Verifiable Credential mimarisine geçişte gereken güvenlik kontrollerini inceleyeceğiz.
Resmî kaynaklar
Bu makaleyi nasıl değerlendirirsin?
Geri bildirimin sonraki içerikleri geliştirmeme yardımcı olur.