V dubnu 2026 představila Evropská komise referenční implementaci aplikace pro ověření věku (Age Verification, AV) – tzv. „mini-peněženku“, která má sloužit jako technologický předstupeň plnohodnotných peněženek European Digital Identity Wallet (EUDIW) plánovaných pro nasazení ve všech 27 členských státech do konce roku 2026.
Aplikace má lidem umožnit prokázat věk online službám (sociální sítě, hazard, obsah pro dospělé) bez prozrazení dalších osobních údajů. Vývoj zajišťuje konsorcium T-Scy – německý Deutsche Telekom T-Systems a švédská Scytáles AB. Zdrojový kód je veřejně dostupný na GitHubu pod organizací eu-digital-identity-wallet.
Hned několik bodů je třeba uvést na začátek, protože ovlivňují rámování celé debaty. Zaprvé: obě hlavní aplikace (av-app-android-wallet-ui , av-app-ios-wallet-ui ) i podkladové knihovny (eudi-lib-android-wallet-core , eudi-lib-ios-wallet-kit ) ve svých README explicitně uvádějí, že jde o „initial development release“ se „sníženými bezpečnostními, soukromými, dostupnostními a spolehlivostními standardy“ a že autoři „důrazně nedoporučují uvést tuto verzi do produkčního nasazení“. Členské státy mají kód před nasazením přizpůsobit a zpevnit.
Zadruhé: politické uvedení – tisková konference s Ursulou von der Leyenovou – proběhlo navzdory těmto disclaimerům. Tato propast mezi „demem na GitHubu“ a marketingovou prezentací je sama o sobě jádrem příběhu.
Veřejně dokumentované zranitelnosti aplikací
Britský bezpečnostní konzultant Paul Moore demonstroval na konci dubna 2026 kompletní obejití Android aplikace za méně než dvě minuty. Francouzský výzkumník Baptiste Robert nálezy reprodukoval, italský výzkumník přidal dalších pět zranitelností. Konkrétní problémy spadají do tří okruhů:
Slabé zacházení s PIN kódem. Referenční třídaPrefsPinStorageProvider obsahuje metodu retrievePin() , která vrací PIN v plaintextu, a porovnání isPinValid() provádí prostým retrievePin() == pin – tedy nikoli v konstantním čase, což otevírá teoretický timing side-channel. Komunitní pull request #83 („Fix PIN timing side-channel and remove plaintext PIN exposure“) oba problémy potvrzuje a opravuje nahrazením porovnání funkcí MessageDigest.isEqual() a odstraněním metody retrievePin().
Sdílený SharedPreferences soubor jako jediná obrana. PIN, jeho šifrovací IV, alias klíče v Android Keystore, počítadlo nezdařených pokusů i časové razítko zámku – vše leží v jediném XML souboru eudi-wallet.xml. Útočník s rootovaným zařízením nebo přístupem k záloze může vynulovat čítač pokusů (čímž obejde rate-limiting) a přepnout boolean UseBiometricAuth na false (čímž vypne biometrii). Dokumentuje to issue #73 v repozitáři, kde je popsán i celý řetězec útoku: čtení SharedPreferences → získání CryptoAlias → načtení AES klíče z Keystore → dešifrování PINu → reset zámku.
Žádná detekce roota, emulátoru ani manipulace. Žádný Kotlin soubor v repozitáři neobsahuje kontroly integrity zařízení. Issue #11 navrhuje použití Android Hardware Attestation API, dosud bez reakce. Ochrana SharedPreferences se opírá výhradně o sandbox Androidu – který root úplně neguje.
iOS aplikace prošla výrazně menší veřejnou kontrolou – má pouze 8 hvězd na GitHubu oproti 114 u Android verze, a žádná z veřejných demonstrací bypass útoku se na ni necílila. Sdílí ovšem stejné architektonické předpoklady.
Architektonická slabina protokolu vydávání atestace
Závažnější než výše popsané chyby v ukládání PIN je slabina, kterou samostatná analýza odhalila už v březnu 2026 – tedy ještě před dubnovým mediálním uvedením a před demonstracemi Paula Moora. Netýká se kódu aplikace, ale samotného návrhu protokolu mezi peněženkou a vydavatelem (issuer). Stojí za to ji rozebrat podrobněji, protože ji nelze opravit pull requestem; vyžaduje změnu protokolu.
Zápisový (enrolment) tok funguje zhruba takto: uživatel naskenuje strojově čitelnou zónu pasu (MRZ) → telefon se přes NFC připojí k čipu pasu, autentizuje se odvozenými klíči (BAC nebo PACE) a přečte z čipu podepsanou fotografii a osobní údaje → uživatel pořídí selfie a projde liveness testem → aplikace porovná selfie s fotografií z čipu → pokud se shodují, telefon pošle vydavateli žádost o vydání atestace věku, která je následně svázána s klíčem v Secure Enclave nebo StrongBox zařízení. Všechno to vypadá uzavřeně a bezpečně.
Problém je ve slově „pošle“. Vydavatel obdrží od telefonu v podstatě jen tvrzení: „naskenoval jsem pas, ověřil čip, udělal selfie, vše sedí, vydej mi atestaci“. Tato zpráva je sice kryptograficky podepsaná klíčem peněženky, ale ten klíč jen prokazuje, že žádost přišla z dané instance aplikace – neprokazuje, že popisované kroky skutečně proběhly. Vydavatel nemá kryptografický artefakt, který by potvrzoval, že NFC dialog s čipem pasu opravdu proběhl na zařízení uživatele a nebyl simulován; že načtená data pasu pocházejí z fyzického dokumentu a ne z dříve odcizené nebo nasdílené kopie; že selfie byla pořízena živým člověkem v reálném čase a ne přehrána z videa nebo vygenerována; ani že porovnání proběhlo skutečně lokálně na zařízení a vrátilo poctivý výsledek.
Co tomu pootevírá dveře: útočník, který má přístup k naskenovaným nebo NFC-staženým datům cizího pasu (například z úniku dat, z předchozí KYC procedury nebo prostě z půjčeného dokladu rodičů), může na upraveném klientovi vykonstruovat zdánlivě validní žádost a získat atestaci „nad 18“ pro někoho, kdo nesplňuje věk. Stejnou cestou lze získat atestaci pro účet, který vlastní někdo jiný – typický útok pro obchody s atestacemi, kde dospělý prodává „starší než 18“ tokeny nezletilým. ZKP (zero-knowledge proof) vrstva, kterou Komise marketingově zdůrazňuje jako záruku soukromí, tento problém neřeší – ZKP chrání data při prezentaci atestace ověřovateli, ale neříká nic o tom, zda atestace měla vůbec být vydána.
Existují kryptografické nástroje, které by tuto díru zacelily, a v ekosystému EUDI o nich existují diskuse, ale nejsou nasazené v referenční implementaci. Hardware key attestation – Android (KeyAttestation z Keystore) i Apple (App Attest, DeviceCheck) – umí vydat podepsaný řetězec certifikátů, který vydavateli prokáže, že klíč použitý k podpisu žádosti vznikl uvnitř konkrétního hardwarového Secure Element a že aplikace je nepozměněná. Bez tohoto kroku vydavatel nepozná simulátor od skutečného telefonu. Active Authentication a Chip Authentication v ICAO 9303 pasu umožňují čipu pasu na výzvu podepsat nonce vydaný vzdálenou stranou; pokud vydavatel zapojí svůj nonce do tohoto dialogu, získá důkaz, že NFC čtení nebylo přehráno z dřívější relace. A konečně, Wallet Unit Attestation (WUA) a Wallet Instance Attestation (WIA) – knihovna eudi-lib-android-wallet-core rozhraní pro WIA/WUA má, ale jeho implementace je volitelná a ponechaná na členském státu. V referenční age-verification aplikaci není povinně použito.
Důsledek je systémový: čím více se EU spoléhá na on-device processing kvůli soukromí – což je správný cíl – tím více se přesouvá důvěra na samotné zařízení a jeho deklarace. Pokud zařízení nemá povinnost svá tvrzení kryptograficky doložit, vzniká paradox, na který upozornili kryptolog Olivier Blazy a další: privátní architektura není automaticky bezpečná architektura. Důvěra v řetězec „naskenoval jsem pas → mám atestaci věku“ nyní stojí na předpokladu, že klient je nepozměněný – což je předpoklad, který zkušenost s mobilními ekosystémy spolehlivě nepodporuje.
Hlubší vrstva: knihovny pod aplikacemi
Závažnější část analýzy se týká toho, co je pod UI vrstvou – tedy kryptografických knihoven, které aplikace používají.
Android eudi-lib-android-wallet-core není kryptografická knihovna, ale orchestrátor. Skutečnou práci s klíči, Secure Element, StrongBox a ISO 18013–5 mdoc protokolem deleguje na knihovnu org.multipaz – projekt s původem v Google (dříve známý jako Identity Credential). Tvrzení Komise, že systém je „plně open source a auditovatelný“, je tedy technicky pravdivé, ale prakticky zavádějící: audit kódu EU repozitáře neauditoval kořen důvěry. Knihovna podporuje aktuálně pouze algoritmus ES256 (žádné silnější křivky, žádné post-kvantové alternativy), DPoP klíče ve výchozí konfiguraci nevyžadují biometrické ověření při použití, a centrální seznam důvěryhodných certifikátů relying parties stále neexistuje – issue #309 (ETSI trusted lists / LoTE / LOTL) je k dubnu 2026 stále otevřený. Do té doby si každý členský stát musí spravovat vlastní trust store.
iOS eudi-lib-ios-wallet-kit má strukturálně podobný přístup, používá ovšem ve výchozím nastavení Secure Enclave a Keychain – což je díky hardwarové izolaci Applu silnější výchozí pozice než na Androidu (kde je StrongBox volitelný). Knihovna má ovšem 140 vydaných verzí (Android jich má 21), což svědčí o intenzivních změnách API u kritické infrastruktury. Příkladový kód v README používáaccessControl: .requireUserPresence – což je splnitelné samotným systémovým PIN kódem zařízení, nikoli zvláštním biometrickým ověřením peněženky.
FaceMatchSDK – uzavřený binární blob v jinak open-source projektu. iOS repozitář obsahuje předkompilovanou knihovnu Frameworks/FaceMatchSDK.xcframework, jejíž zdrojový kód není veřejný. Android verze dělá face matching in-tree, ale modely neuronových sítí stahuje z GitHub Releases – a kód sám obsahuje varování, že „modely v výchozí konfiguraci jsou hostovány na GitHub Releases pouze pro vývojové a testovací účely. Toto NENÍ doporučeno pro produkční prostředí.“
Tato část je z hlediska celkové bezpečnosti nejzávažnější. Při vydávání atestace věku se totiž důvěra opírá o porovnání selfie s fotografií z čipu pasu – pokud je matcher snadno oklamatelný, padá celý řetězec důvěry, protože jiný důkaz vlastnictví pasu při zápisu neexistuje. Prahy livenessThreshold a matchingThreshold jsou konfigurovatelné a Komise nestanovila závazné minimum FAR/FRR. Vzhledem k tomu, že kontrakt získalo konsorcium T-Scy, je SDK pravděpodobně produktem Scytáles AB, ale nejde to z veřejně dostupných materiálů potvrdit. Nejcitlivější komponenta celého systému – biometrický matcher – je tedy jediná, kterou nelze veřejně auditovat, a Komise tuto skutečnost ve své komunikaci nezmiňuje.
Klíčová otázka
Bylo by nepřesné psát, že „aplikace EU pro ověření věku je rozbitá“. Kód je ze své podstaty demoverze a sami autoři ho označují jako nevhodný k produkčnímu nasazení.
Přesnější rámec zní takto: Komise uspořádala mediálně exponované uvedení kolem kódu, jehož vlastní README říká, že by neměl být nasazen. Demo-úrovňové zkratky v tomto kódu – PIN v plaintextu, rate-limiting v editovatelném souboru, žádná detekce roota – se dostaly do titulků novin, protože politické sdělení předběhlo technickou zralost.
Hlubší a méně diskutované otázky jsou strukturální: protokol vydávání atestace nemá kryptografický důkaz, že enrolment proběhl na skutečném zařízení, kryptografický základ Androidu pochází z knihovny org.multipaz s Google původem, klíčový biometrický matcher na iOS je uzavřený binární soubor neznámého výrobce, a centrální infrastruktura důvěry (ETSI trusted lists) zatím neexistuje.
Otázka pro Komisi není „je tento konkrétní kód bezpečný?“, ale „kdy a jak budou členské státy povinny tyto reference zpevnit, a kdo to bude auditovat předtím, než se aplikace dostane do rukou 450 milionů obyvatel EU?“