Basic Access Control (BAC)
Basic Access Control is a protocol designed to protect the content of the e-passport chip from unauthorized reading (skimming or eavesdropping) by requiring that the reader prove knowledge of the passport’s MRZ information. In simpler terms, BAC uses information printed in the passport (MRZ) to derive encryption keys, and establishes a encrypted session between the chip and the reader. Only someone who has physically seen the passport (and thus knows the MRZ) can perform BAC successfully, thereby mitigating the risk of someone reading your passport data without your consent from a distance.
Key derivation. The passport’s MRZ data (specifically, the document number, date of birth, and expiration date, along with their check digits) are used to compute two 56-bit keys (plus parity bits making them into two 64-bit keys) for Triple-DES (3DES) encryption. The process as specified by ICAO: those MRZ fields are concatenated into a 16 or 32 byte value (depending on spec version), then hashed (earlier versions used SHA-1, taking the first 16 bytes of the SHA-1 output as the two keys). The result is two DES keys: one for encryption (called K_ENC
) and one for message authentication (K_MAC
). These keys are the Document Basic Access Keys, essentially a shared secret between the passport and any reader that knows the MRZ. Because MRZs are not highly random, the effective strength of these keys is about 56–64 bits of entropy in early implementations.
The BAC protocol (handshake): BAC is essentially a challenge-response protocol based on ISO/IEC 9798-2. It goes like this (assuming the reader has optically read the MRZ from the passport):
- The reader issues a SELECT command to select the ePassport application, then issues a GET CHALLENGE command. The chip responds with an 8-byte random number
R<sub>ICC</sub>
(the chip’s random challenge). - The reader then generates its own 8-byte random RIFD. The reader now has:
- Chip’s challenge RICC,
- Its own challenge RIFD,
- The two shared secret keys (K_ENC, K_MAC) derived from MRZ.
- The reader constructs a cryptogram consisting of RICC || RIFD || some other data (like a key seed or identifier; in BAC specifically, it includes a 16-byte random and then the two randoms again for key derivation, but that detail is internal). It then encrypts this with K_ENC and appends a MAC (using K_MAC), and sends it to the chip using the EXTERNAL AUTHENTICATE command.
- The chip receives this, decrypts it with its own copy of K_ENC (since the chip also can derive keys from MRZ stored internally) and verifies the MAC with K_MAC. If everything is correct (meaning the reader knew the right keys, and the message integrity is good), the chip then similarly responds by encrypting a cryptogram (often just RIFD maybe modified, or some agreed value) with a MAC in an INTERNAL AUTHENTICATE response (in practice, the standard uses mutual auth so both sides prove knowledge). The details per spec: the chip will take the reader’s random, its own random, maybe do some DES operations (the spec defines this precisely), and send back an 8-byte token encrypted and MACed.
- If the reader successfully decrypts and verifies the chip’s response, both sides are now assured they share the secret keys. At this point, Secure Messaging (SM) is activated: both parties derive session keys from the exchanged randoms for ongoing encryption and MAC of all further APDUs. Typically, they derive new keys (like session K_ENC' and K_MAC') from RICC and RIFD to use thereafter, although some implementations just continue using the same keys for session – the standard suggests deriving fresh session keys to avoid reusing the static MRZ-based ones any longer than needed.
After BAC is successfully performed, the communication channel between the reader and passport is encrypted (with 3DES) and MAC-protected. This means an eavesdropper can no longer read plaintext data or insert commands easily. Also, the chip will refuse to output personal information from DG1, DG2, etc., unless BAC succeeded; if you try to read without doing BAC, it will give an error or no response (this prevents skimming).
BAC’s practical necessity: In early days, some worried that radio chips could be read from a distance without someone opening the passport. BAC mitigates that because you need the MRZ to do it. The MRZ is inside the passport, and often passports have RF shielding in the cover (for instance, the U.S. added a metallic mesh in the cover) to prevent reading when closed. So an attacker would have to physically open the passport or at least know the details to get the keys, making “skimming” much harder. BAC also provides some level of privacy for the basic data (everything remains encrypted on the air).
Known vulnerabilities of BAC: While clever for its time, BAC has a number of weaknesses:
-
Low entropy keys / Guessability: The MRZ data has relatively low entropy. Many countries used sequential passport numbers, and an attacker might often know or guess a person’s birth date or expiration date range. This dramatically reduces the search space. In fact, researchers demonstrated in 2007 that by eavesdropping one BAC exchange (which was 3DES encrypted) from a few meters away, they could brute-force the keys in under a minute for some passports (Germany, Netherlands). They took advantage of known passport number patterns and the limited entropy of date-of-birth (people typically not older than 100, etc.) to shrink the brute force effort. Even without eavesdropping, another attack was possible: if an attacker had physical proximity, they could try to brute-force BAC by repeatedly attempting sessions (though this is slower and chips often have rate limits). But using a recorded session, one can test candidate MRZ keys offline by attempting to decrypt the transcript. As Henderson summarizes: “the combination of Triple DES encryption and a short MRZ means it’s not very secure at all.”. The MRZ key space was effectively around 2^40 to 2^50 for many passports, which by today’s computing is feasible.
-
Eavesdropping and brute force: As mentioned, if BAC is used and an attacker sniffs the communication, they can later brute force the session keys. BAC does not use any forward secrecy – the static keys derived from MRZ protect the whole session. If those keys are found, the attacker can decrypt all the data that was exchanged (which could include the face image, etc.). This is a real concern, especially before PACE was introduced. The 2007 attack referenced by Henderson cracked BAC keys in < 30 seconds with specialized hardware.
-
Replay and tracing: The BAC protocol itself, if badly implemented, could allow replay of an authentication attempt or telltale differences if the wrong key is used. For example, one attack (Chothia 2010) found that some chips took noticeably longer to respond if you sent a properly encrypted (MACed) message versus a random one, even if you hadn’t done BAC with the right key. By recording one valid BAC session message and replaying it, an attacker could basically “ping” a passport to see if that message’s MAC is valid under some key – if the timing is different, they learned something, possibly even allowing them to confirm a passport’s identity (traceability attack) or to brute force the key one byte at a time through timing analysis. One such advanced attack by Sportiello in 2014 combined a timing side channel with partial brute force to recover the BAC key without even eavesdropping a session (it required interacting with the passport for many hours though). These attacks exploit implementation flaws (chips should take constant time for invalid auth attempts, but not all did).
-
Backwards compatibility dependency: BAC is not an elegant protocol by modern standards (it uses 3DES and no forward secrecy). It persisted until mid-2010s, and even when PACE was introduced, passports often had to support BAC as a fallback. This means an attacker could force a downgrade to BAC in some cases if a reader isn’t configured to prefer PACE. The presence of BAC means the vulnerabilities might still be exploitable if an inspection system doesn’t enforce using PACE. By 2023, researchers noted that many passports still support BAC and thus remain vulnerable to any new BAC attacks even if the primary method is PACE.
Despite its weaknesses, BAC did succeed in preventing casual skimming in the early years. There have been no reports of widespread data theft via BAC brute forcing in the field (likely because one needs either physical access or a good antenna very close to the passport, plus significant computing power). However, as a library developer, one should be aware that if a passport supports PACE, it’s far better to use PACE (we’ll cover that next), and that BAC keys can be brute-forced if someone obtains a transcript. Also, some passports might not implement BAC correctly (in the “Implementation notes” we will mention a French passport bug where error codes differed, etc.).
Library implementation: In a library, implementing BAC involves:
// Assuming you have a passport object with methods to read MRZ and perform BAC
final passport = Passport(_nfc);
// Read MRZ from the passport (this is usually done by optical scanning)
final accesKey = DBAKey(
docNumber,
birthDate,
expiryDate,
paceMode: false,
);
await passport.startSession(accessKey as DBAKey);