BAC (Basic Access Control) ve PACE (Password Authenticated Connection Establishment), elektronik kimlik veya pasaport çipinin bir okuyucunun içeriğe erişip erişemeyeceğini belirlemek için kullandığı protokollerdir. İkisi de ICAO uyumlu seyahat belgelerinin temelindeki açık standart olan ICAO Doc 9303'te tanımlanır. BAC, belge üzerine basılı verilerden anahtar türetir; bu verilerin düşük entropisi bilinen bir zayıflıktır. PACE ise zayıf bir parolayla bile güçlü oturum anahtarları üreten, parola doğrulamalı bir Diffie–Hellman değişimi yapar. Yeni belgelerde PACE öne çıkar; BAC eski çiplerle uyumluluk için okuyucularda kalır.
Bir bankacılık uygulaması için eID SDK geliştirirken bu ayrımla karşılaştım. Çipin NFC üzerinden okunması ve doğrulanmasının tamamını Android'de eID çipi okuma yazısında anlattım. Burada o akışın tek aşamasına, erişim kontrolüne ve BAC/PACE seçiminin neden önemli olduğuna odaklanıyorum.
Temel noktalar
- Erişim kontrolü, özgünlük kanıtı değildir. Çipi kimin okuyabileceğini belirler; verinin gerçekliğini ayrı bir aşama olan Passive Authentication doğrular.
- BAC anahtarlarını MRZ'den türetir: belge numarası, doğum tarihi ve son geçerlilik tarihi. Basılı ve kısmen tahmin edilebilir bu alanların etkili entropisi düşüktür.
- PACE, parola doğrulamalı anahtar değişimidir. Parola kısa olsa da oturum anahtarlarının güvenliği korunur; BAC'ın çevrimdışı saldırı zayıflığını giderir.
- Okuyucu protokolü müzakere eder.
EF.CardAccessiçindeki yetenekleri inceler, çip destekliyorsa PACE kullanır; eski belgelerde BAC'a döner.
Bir kimlik çipi neden erişim kontrolüne ihtiyaç duyar?
Temassız çiple radyo üzerinden, ISO/IEC 14443 aracılığıyla konuşulur. Erişim açık bırakılırsa yeterince yaklaşan biri adınızı, doğum tarihinizi ve fotoğrafınızı fark ettirmeden okuyabilir veya meşru bir terminalle belge arasındaki trafiği kaydedebilir. Çipin veri gruplarını vermeden önce okuyucunun belgeyi okumaya yetkili olduğunu göstermesi bu riski azaltır.
ICAO tasarımında okuyucu, belgeyi fiziksel olarak elinde tutan kişinin erişebileceği veriyi bildiğini gösterir: pasaport sayfasının altında veya kimliğin arkasında bulunan makine tarafından okunabilir alan, yani MRZ. MRZ'yi okuyabilmenin belgeyi elinde tutmaya işaret ettiği varsayılır. Bu mekanizma mahremiyet ve belge sahibinin erişimi mümkün kılmasıyla ilgilidir; içerik doğruluğuyla ilgili değildir. Verinin değiştirilmediğini ve güvenilen bir makamca üretildiğini sonradan Passive Authentication kanıtlar. Bu iki sorumluluğu ayrı tutmak bütün akışı anlaşılır kılar.
BAC: MRZ'den türetilen anahtarlar
İlk mekanizma BAC'tır. Okuyucu üç MRZ alanını kontrol basamaklarıyla birleştirir, SHA-1 ile hash alarak anahtar tohumu üretir. Bu tohumdan biri şifreleme, diğeri mesaj doğrulama için iki 3DES anahtarı türetir ve çiple Secure Messaging kanalı açar.
Türetmenin girdileri şunlardır:
/**
* The three MRZ fields that seed a BAC key. All three are printed on the
* document, which is the root of BAC's entropy problem. The same inputs can
* also serve as the PACE password when a CAN is not used.
*/
data class DocumentKeyInput(
val documentNumber: String,
val dateOfBirth: String, // YYMMDD
val dateOfExpiry: String, // YYMMDD
)
Zayıflık bir uygulama hatası değil, yapısaldır. Aynı belge için anahtar sabittir ve bütünüyle sayfaya basılı verilerden oluşur. Doğum tarihinin makul değerleri on binler, geçerlilik tarihinin değerleri birkaç bin mertebesindedir; belge numaraları da rastgele olmak yerine düzenleyen makamın tahmin edilebilir desenlerini izleyebilir. Dolayısıyla BAC anahtarının etkili entropisi, sonuçta üretilen 3DES anahtar uzayından çok daha küçüktür. Uzun anahtar üretmek, girdiye eksik olan rastgeleliği eklemez.
BAC oturumunu kaydeden bir saldırgan, MRZ alanlarının olası değerlerini çevrimdışı deneyerek oturum anahtarlarını bulabilir ve trafiği çözebilir. Kayıt alındıktan sonra çiple etkileşmesi gerekmez. Kısa, tahmin edilebilir, basılı veriden uzun ömürlü sır türetmek güçlü bir saldırgan karşısında sorun çıkarır. Mobil güvenlikte de benzer sınırlar vardır; bazılarını SecureCheck yazısında topladım.
PACE: parola doğrulamalı el sıkışma
PACE, kullanıcıdan daha güçlü bir sır ezberlemesini istemeden entropi sorununu çözer. Bir PAKE, yani parola doğrulamalı anahtar değişimidir. Amaç, zayıf olabilen ortak paroladan dinleyicinin çevrimdışı elde edemeyeceği güçlü oturum anahtarları oluşturmaktır.
Parola yine belge sahibinin erişebildiği bilgidir: BAC'taki gibi MRZ'den türetilebilir veya birçok modern belgede ayrıca basılan kısa CAN (Card Access Number) olabilir. Parolanın entropisi düşük kalır; fark, PACE'in o parolayla ne yaptığıdır.
El sıkışmayı üç adımda düşünebiliriz. Önce mapping aşamasında çip rastgele bir nonce üretir ve paroladan türetilen anahtarla şifreleyerek gönderir. Taraflar bu nonce ile yeni bir Diffie–Hellman değişimini birleştirip geçici bir grup üreteci oluşturur. ICAO Doc 9303 Part 11, Generic Mapping ve Integrated Mapping gibi farklı yöntemler tanımlar. Generic Mapping'de çözülmüş nonce ve anonim Diffie–Hellman sonucu üreteci eşlemek için kullanılır. İkinci aşamada yeni üreteç üzerinde Diffie–Hellman veya ECDH anahtar anlaşması yapılır. Son olarak oturum anahtarları türetilir ve tarafların aynı anahtara ulaştığını gösteren doğrulama token'ları değişilir.
Sonuç anahtarlarının gücü parolanın entropisine bağlı değildir. Tam oturum kaydını tutan pasif gözlemci, parola tahminlerini BAC'taki gibi çevrimdışı doğrulayamaz. Her tahmin canlı protokol etkileşimi gerektirir. Bu, zayıf parolanın çevrimiçi tahmin edilemeyeceği anlamına gelmez: çipi tekrar tekrar sorgulayabilen saldırgan hâlâ çipin cevap hızına ve uygulanan sınırlara bağlıdır. PACE'in kaldırdığı risk, BAC'ı kırılgan yapan çevrimdışı anahtar kurtarmadır. Modern belgeler PACE'i BAC'ın 3DES'i yerine AES tabanlı Secure Messaging ile de kullanır.
Hangisi ne zaman kullanılır: müzakere ve geri dönüş
Okuyucu serbestçe seçim yapmaz; çipin desteklerine göre karar verir. Kimlik doğrulamasından önce okunabilen EF.CardAccess, desteklenen PACE çeşitlerini ve domain parametrelerini içerir. Kararın kabaca şekli şöyledir:
sealed interface AccessControl {
data object Pace : AccessControl // chip advertises PACE in EF.CardAccess
data object Bac : AccessControl // legacy fallback, keys derived from the MRZ
}
/**
* EF.CardAccess is readable without authentication. If the chip publishes
* PACE parameters there, prefer PACE; otherwise fall back to BAC.
*/
fun selectAccessControl(cardAccess: ByteArray?): AccessControl =
if (cardAccess != null && cardAccess.isNotEmpty()) AccessControl.Pace
else AccessControl.Bac
Gerçek kod, dosyanın boş olup olmadığına bakmakla yetinmemeli; SecurityInfos yapısını ayrıştırıp PACEInfo girdisini aramalıdır. Örnekte yalnız kararın biçimini gösteriyorum.
Geçiş de bu müzakere ve geri dönüş mantığıyla yürüdü. ICAO, PACE'i Supplemental Access Control (SAC) altında ele alır. Eski okuyucuların da çalışabilmesi için PACE destekleyen çiplerin BAC'ı da desteklemesi bekleniyordu. Bu birlikte çalışabilirlik şartının geçiş takvimindeki bitişi genellikle 1 Ocak 2018 olarak anılır; sonrasında yalnız PACE kullanan çiplere izin verilir. Avrupa Komisyonu seyahat belgelerinde PACE'i 2014 sonundan itibaren zorunlu kıldı; üye devletlerde tam uyum 2015'ten itibaren uygulandı. Yön açıktır: PACE esas mekanizma, BAC ise eski belge uyumluluğudur. Bugün okuyucu tasarlarken PACE'i önceleyip BAC'ı ihtiyaç duyan eski belgeler için tutarım.
Android NFC okuyucusu için anlamı
Android tarafındaki mekanik adımlar iki protokol için de aynıdır: reader mode açılır, IsoDep bağlantısı alınır ve APDU'lar değişilir. Reader mode tarama sırasında platformun ve diğer NFC uygulamalarının araya girmesini azaltır:
import android.app.Activity
import android.nfc.NfcAdapter
import android.nfc.NfcManager
import android.nfc.tech.IsoDep
class PassportReader(private val activity: Activity) {
// getDefaultAdapter is deprecated since API 29; prefer NfcManager.
private val adapter: NfcAdapter? =
activity.getSystemService(NfcManager::class.java)?.defaultAdapter
fun startReading(onConnected: (IsoDep) -> Unit) {
adapter?.enableReaderMode(
activity,
{ tag ->
IsoDep.get(tag)?.use { isoDep ->
isoDep.timeout = 10_000
isoDep.connect()
onConnected(isoDep)
}
},
NfcAdapter.FLAG_READER_NFC_A or NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK,
null,
)
}
fun stopReading() {
adapter?.disableReaderMode(activity)
}
}
onConnected içindeki sıra sabittir: EF.CardAccess oku, protokolü seç, Secure Messaging kuran el sıkışmayı yap, sonra veri gruplarını seçip oku. Erişim kontrolünü atladığınızda çip okumayı reddeder. Sonraki ayrıştırma ve doğrulama için jMRTD gibi açık kaynak kütüphaneler iyi referanslardır; okuma ve güven kararını daha önce bağlantısını verdiğim eID yazısında ele aldım.
Tanı çıktısında erişim kontrolünü tek bir geçti/kaldı sonucuna indirgememek gerekir. “Çipe ulaşamadık”, “el sıkışma başarısız” ve “veri okundu ama doğrulanamadı” farklı çözümler gerektirir. Her güvenlik sinyalini açıklanabilen bir sonuç olarak ele almak, SecureCheck yazısındaki yaklaşımın da temelidir.
Son söz
BAC ve PACE farkı, kriptografide girdi entropisinin önemini gösterir. Kısa, basılı ve tahmin edilebilir veriden uzun ömürlü sır türetmek risklidir. PACE belge sahibinin zaten bildiği parolanın kullanım kolaylığını korurken oturum anahtarlarını onun zayıflığından bağımsızlaştırır. Okuyucuda PACE'i önceleyin, BAC'ı uyumluluk için tutun ve erişim kontrolünü — kimin okuyabileceği — okunan verinin özgünlüğünü doğrulamaktan ayrı tasarlayın.