Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

BEIDKit

BEIDKit reads a Belgian eID card through an external USB CCID smart card reader on iOS/iPadOS, and returns typed identity, address, and photo data through a small async/await API. No UI coupling, no dictionaries of loosely typed strings as the primary interface.

Requirements

  • iOS/iPadOS 16.0+ — this is the practical floor for the whole SDK, since Apple's native support for external USB CCID smart card readers via CryptoTokenKit landed in iPadOS 16.
  • An external USB CCID smart card reader.
  • A Belgian eID card.

Installation

Building an app in Xcode?

In your app project:

  • File → Add Package Dependencies…
  • Paste https://github.com/whisker-works/BEIDKit.git in the Package URL field
  • Pick a version rule (e.g. "Up to Next Major Version" starting at 0.1.0)
  • Click Add Package, then check BEIDKit for your app's target.

Xcode wires everything up for you — nothing to hand-edit.

Building your own Swift package that depends on BEIDKit?

Add it to your package's Package.swift:

let package = Package(
    ...
    dependencies: [
        .package(url: "https://github.com/whisker-works/BEIDKit.git", from: "0.1.0")
    ],
    targets: [
        .target(name: "YourTarget", dependencies: ["BEIDKit"])
    ]
)

Updating to a newer version

Once BEIDKit is added, Swift Package Manager doesn't automatically move you to newer releases — it pins whatever version it first resolved (recorded in Package.resolved) and keeps using that on every build, even after a newer version is tagged.

In Xcode:

  • File → Packages → Update to Latest Package Versions.

In a Package.swift-based project

  • run swift package update from the command line.

Either way, as long as your version rule allows it (e.g. from: "0.1.0" allows any 0.x release up to, but not including, 1.0.0), this picks up the latest matching version automatically — no manifest changes needed.

Usage

import BEIDKit

let reader = EIDCardReader()
let card = try await reader.readCard { step in
    print("Progress: \(step)")
}

print(card.identity.name, card.identity.firstName)
print(card.address.streetAndNumber, card.address.zip, card.address.municipality)
let photo: Data = card.photo // raw JPEG bytes — you decide how to render it

readCard() is the single entry point. The optional onProgress closure is a lightweight escape hatch for apps that want to show "reading identity…" style UI; the simplest call site is just try await EIDCardReader().readCard().

Errors

readCard() throws EIDCardError, which covers the reader/card not being present, session failures, card communication failures (naming which step and status word failed), and unreadable data:

do {
    let card = try await EIDCardReader().readCard()
} catch let error as EIDCardError {
    print(error.errorDescription ?? "Unknown error")
}

What you get

Identity

The fields citizens will realistically always have, as named, typed (String) properties:

Property Card field
cardNumber Card number
cardValidityDateBegin Card validity begin date
cardValidityDateEnd Card validity end date
cardDeliveryMunicipality Card delivery municipality
nationalNumber National number (see Legal considerations)
name Surname
firstName First name(s) — up to two given names, space-separated
middleName Initial of a third given name, if any (optional — not a "middle name" in the everyday sense; most people's names fit entirely in firstName)
nationality Nationality
placeOfBirth Place of birth
dateOfBirth Date of birth
gender Gender
documentType Document type

Access these directly as properties:

card.identity.cardNumber
card.identity.dateOfBirth

Every other tag the card exposes is still readable via additionalFields: [String: String], keyed by name — access by subscripting with the key from the table below:

card.identity.additionalFields["workPermit"]         // String?
card.identity.additionalFields["cardEUStartDate"]    // String?
Key Card field
nobleCondition Noble condition
specialStatus Special status
duplicate Duplicate indicator
specialOrganisation Special organisation
memberOfFamily Member of family
dateAndCountryOfProtection Date and country of protection
workPermit Work permit
employerVATNumber1 Employer VAT number 1
employerVATNumber2 Employer VAT number 2
regionalFileNumber Regional file number
brexitMention1 Brexit mention 1
brexitMention2 Brexit mention 2
cardAMention1 Card A mention 1
cardAMention2 Card A mention 2
cardEUStartDate Card EU start date

chipNumber, photoDigest, and basicPublicKeyDigest are on the card too, but are raw bytes/a hash digest rather than human-readable text, so BEIDKit drops them rather than surfacing them as garbled strings.

Address

Property Card field
streetAndNumber Street and number
zip ZIP code
municipality Municipality
card.address.streetAndNumber
card.address.zip

Photo

Raw JPEG bytes (Data) — BEIDKit doesn't impose a rendering approach.

Fields like dateOfBirth and gender are exposed as raw strings exactly as decoded off the card, not as typed Date/enum values — see Roadmap below.

Roadmap

Deliberately deferred to a (much) later version:

  • Certificate reading (auth cert, sign cert, CA/root certs).
  • PIN verification and any signing/authentication operations using the card's private keys.
  • Verifying the government's digital signature over the identity/address files against the Belgian root CA.
  • Typed Date/enum representations of fields like dateOfBirth or gender — v1 exposes these as raw strings, exactly as read off the card.

Example app

Examples/EIDReaderDemo is a minimal SwiftUI app demonstrating the API end-to-end against real hardware. See its own README for setup.

Legal considerations

This SDK reads real personal data off a government-issued identity document, including the Belgian national register number (identity.nationalNumber). Once BEIDKit hands that data to your app, how it's handled is on you, not the SDK.

The national register number is a special case. Under Belgian law, processing it is prohibited by default — independently of, and more strictly than, GDPR. It requires explicit authorization from the National Register's Sectoral Committee, granted only for tasks of general interest recognized by law, not for commercial purposes (customer accounts, loyalty programs, membership records, etc.). Using it without that authorization carries real penalties.

More broadly, every other field this SDK exposes (name, address, date of birth, photo, etc.) is personal data under GDPR, and the usual obligations — lawful basis, data minimization, security, retention limits — apply to however your application stores or processes it.

This SDK reads and returns data; it has no opinion on what you do with it afterward, and nothing here is legal advice. Consult a lawyer before using this for anything beyond local development/testing.

License

MIT — see LICENSE.

About

Swift SDK for reading Belgian eID cards via an external USB CCID smart card reader on iOS/iPadOS.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages