Package-level declarations

The wallet (Wallet, WalletConfiguration), its sessions (Issuance, Presentation, MdocPresentation, ProximityPresentation), the reader (ProximityReader), the platform interfaces and their standard implementations, and the results they return.

Types

Link copied to clipboard
class AndroidKeystoreKeyStore(val options: AndroidKeystoreKeyStore.Options = Options(), authenticator: HolderAuthenticator? = null) : KeyStore, KeyAgreement

The wallet's keys, in Android Keystore: P-256 keys whose private halves never leave its secure hardware — StrongBox where the device has it (Options.strongBox), else the TEE. Each key's ID is its Keystore alias after Options.aliasPrefix. Keys are usable only while the device is unlocked, and holder keys, if Options.holderUserAuthentication, each time they sign only after authenticator has authenticated the holder: the store refuses to be made without one then.

Link copied to clipboard
@RequiresApi(value = 30)
class BiometricPromptAuthenticator(activity: () -> Activity?, title: String = "Confirm it's you", subtitle: String? = "Your credential's key signs what you share.") : HolderAuthenticator

The system's biometric prompt over the app's current activity (activity's, null when none is showing), allowing a strong biometric or the screen lock, as Face ID or the passcode on iOS.

Link copied to clipboard
data class CredentialDetail(val summary: CredentialSummary, val claims: JsonElement)

A credential with its claims, for display.

Link copied to clipboard
@Serializable
data class CredentialDisplay(val issuerName: String? = null, val issuerLogo: Logo? = null, val name: String? = null, val description: String? = null, val logo: Logo? = null, val backgroundColor: String? = null, val textColor: String? = null)

How to show a credential, from the issuer's metadata (OpenID4VCI 1.0 §12.2.4) in the holder's language: each part only when the issuer gives it. Colours are CSS colours, such as "#12107c".

Link copied to clipboard
@Serializable
data class CredentialStatus(val rawValue: String, val checkedAt: Instant)

A credential's revocation status in the issuer's status list, as last checked (Wallet.checkStatus).

Link copied to clipboard
interface CredentialStore

The wallet's credentials, as opaque records kept by ID under the platform's data protection. An exception it throws reaches Go and comes back as a WalletException.Code.platform error.

Link copied to clipboard
@Serializable
data class CredentialSummary(val id: String, val credentialIssuer: String, val configurationID: String, val format: String, val vct: String? = null, val doctype: String? = null, val receivedAt: Instant, val holderKeyPresent: Boolean? = null, val display: CredentialDisplay? = null, val validUntil: Instant? = null, val status: CredentialStatus? = null, val copies: Int = 0, val copiesLeft: Int = 0, val refreshable: Boolean = false, val linkable: Boolean = false, val shownToVerifier: Boolean? = null, val linkableHere: Boolean? = null)

A credential the wallet holds, as the app shows it.

Link copied to clipboard
@Serializable
data class DeferredCredential(val id: String, val credentialIssuer: String, val configurationID: String, val intervalSeconds: Double, val deferredAt: Instant, val accessTokenExpiresAt: Instant? = null)

A credential an issuer will issue later (OpenID4VCI 1.0 §9). It's kept in the credential store until it's issued, denied or abandoned, so it survives the app quitting.

Link copied to clipboard
sealed interface DeferredStatus

A deferred credential's state, from Wallet.pollDeferred.

Link copied to clipboard

Credential Manager's side of the Digital Credentials API: what an app needs so Chrome, or another app, can ask the wallet for a credential.

Link copied to clipboard
class FileCredentialStore(val directory: File, val options: FileCredentialStore.Options = Options()) : CredentialStore

A credential store of files: one per credential record, in a directory of the app's (noBackupFilesDir/credentials, by default, which no backup or device transfer copies). Each record is encrypted (AES-256-GCM, its ID as associated data) under an Android Keystore key that, by default, works only while the device is unlocked — iOS's complete file protection. A credential is useless without its holder key, which is in this device's Keystore and can't be restored elsewhere; so is a record without the store's key.

Link copied to clipboard
fun interface HolderAuthenticator

Authenticates the holder for one signature by a holder key: a key that needs the holder's biometrics or screen lock for each use. The key store calls it on Go's thread, which waits. BiometricPromptAuthenticator is the standard one.

Link copied to clipboard

A credential store in memory, for tests and development.

Link copied to clipboard
class Issuance

Receives one offer's credentials: show offer; then beginAuthorization, open the URL in an Auth Tab or Custom Tab and completeAuthorization, or redeemPreAuthorizedCode; then requestCredentials; close when done. An issuance dropped without close leaves its keys until Wallet.sweepOrphanedKeys.

Link copied to clipboard
fun interface KeyAgreement

ECDH with the wallet's holder keys inside the key store, for deviceMac in person (ISO/IEC 18013-5 §9.1.3.5). A KeyStore that is also one is used for it when WalletConfiguration.proximityDeviceAuth is WalletConfiguration.ProximityDeviceAuth.MAC_PREFERRED.

Link copied to clipboard

A key that can't agree keys: the wallet signs instead of using a MAC.

Link copied to clipboard

What a key is for.

Link copied to clipboard
interface KeyStore

The wallet's keys: P-256 keys whose private halves never leave the store (Android Keystore). An exception it throws reaches Go and comes back as a WalletException.Code.platform error. Go calls it on its own thread, never the main one.

Link copied to clipboard
@Serializable
data class Logo(val uri: String, val altText: String? = null)

An image the issuer names for display: an https URL or a data: image (nothing else reaches the app), with alternative text.

Link copied to clipboard

An org-iso-mdoc request (ISO/IEC TS 18013-7 Annex C): show request for the holder's consent, then respond once; to decline, cancel the platform's request — nothing is sent to the reader.

Link copied to clipboard
@Serializable
data class Offer(val credentialIssuer: String, val issuerName: String? = null, val issuerLogo: Logo? = null, val grant: Offer.Grant, val txCode: Offer.TxCode? = null, val credentials: List<Offer.Credential>)

What a Credential Offer offers.

Link copied to clipboard
object OID4VC

OID4VCgo's mobile API. Every call runs off the caller's thread: Go calls block, and must never run on the main thread.

Link copied to clipboard
@Serializable(with = PathElementSerializer::class)
sealed interface PathElement

One claim path element: a key, an array index, or every element.

Link copied to clipboard

Answers one OpenID4VP request: show verifier, queries and credentialSets, choose a selection (or start from defaultSelection), preview it, then respond or decline. The wallet presents exactly the selection, after checking it answers the request (WalletException.Code.invalidSelection otherwise).

Link copied to clipboard

The BLE roles a holder offers in its QR code (ISO/IEC 18013-5 §8.3.3.1.1); the reader picks one, central client mode when offered both.

Link copied to clipboard

An in-person session failed over Bluetooth, rather than in the protocol (WalletException).

Link copied to clipboard

The runtime permissions an in-person session needs, for the app to request.

Link copied to clipboard

The holder's side of an ISO/IEC 18013-5 in-person presentation over BLE: show qrCode, and the reader that scans it connects, or advertises for the holder to connect, in one of the ProximityBLEModes the session offers. Follow state: on State.RequestReceived, ask the holder, then respond or decline. cancel ends it at any point. One request per session.

Link copied to clipboard
class ProximityReader(configuration: ProximityReaderConfiguration, keyStore: KeyStore? = null)

An ISO/IEC 18013-5 mdoc reader: a verifier asking for an mdoc in person over BLE. It needs no Wallet. keyStore holds the reader's key, ProximityReaderConfiguration.readerKeyID; null for a reader that doesn't sign.

Link copied to clipboard
@Serializable
data class ProximityReaderConfiguration(val issuerRoots: String, val readerKeyID: String? = null, val readerChain: String? = null, val maxClockSkewSeconds: Long? = null, val requireMDLSignerEKU: Boolean = false, val issuerRootsByDocType: Map<String, String> = emptyMap())

A ProximityReader's configuration.

Link copied to clipboard
data class ProximityReaderIdentity(val status: ProximityReaderIdentity.Status, val name: String, val chain: List<X509Certificate>, val error: String?)

Who sent a request, as the holder sees it.

Link copied to clipboard

One reader session: follow state to State.Verified or another final state.

Link copied to clipboard
data class ProximityTimeouts(val connect: Duration = 60.seconds, val request: Duration = 30.seconds, val idle: Duration = 300.seconds)

How long an in-person session waits (ISO/IEC 18013-5 recommends at least 30 seconds from engagement to the request, §8.2.3, and 300 seconds of inactivity before ending a session, §9.1.1.4).

Link copied to clipboard
@Serializable
data class RequestLink(val clientID: String, val requestURI: String, val requestURIMethod: String? = null)

An OpenID4VP request link's parts.

Link copied to clipboard
typealias Selection = Map<String, List<String>>

What to present: for each query ID, the IDs of the credentials chosen to answer it.

Link copied to clipboard
class StoreException(message: String) : Exception

A store's or provider's own failure.

Link copied to clipboard
data class VerifiedMdoc(val doctype: String, val claims: JsonObject, val deviceSignedClaims: JsonObject?, val issuer: String, val trustAnchor: String, val validFrom: Instant, val validUntil: Instant, val deviceAuth: String, val statusList: VerifiedMdoc.StatusListReference?)

A verified mdoc, as a ProximityReaderSession received it.

Link copied to clipboard
class Wallet(configuration: WalletConfiguration, keyStore: KeyStore, credentialStore: CredentialStore, provider: WalletProvider?)

A holder's wallet: OID4VCgo's walletflow over the app's key store, credential store and Wallet Provider. Creating it makes no network calls; provider is needed to receive credentials, not to present them.

Link copied to clipboard
@Serializable
data class WalletConfiguration(val clientID: String = "", val redirectURI: String = "", val issuerRoots: String = "", val verifierRoots: String = "", val registrarRoots: String = "", val mdocReaderRoots: String = "", val mdocReaderRequireEKU: Boolean = false, val requireTrustedMdocReader: Boolean = false, val requireSignedDCAPIRequests: Boolean = false, val development: Boolean = false, val developmentRoots: String = "", val locales: List<String> = defaultLocales(), val batchSize: Int = 0, val requestRefresh: Boolean = false, val copyPolicy: WalletConfiguration.CopyPolicy = CopyPolicy.PER_PRESENTATION, val tlsPins: Map<String, List<String>> = emptyMap(), val issuanceProfile: WalletConfiguration.IssuanceProfile = IssuanceProfile.OPENID4VCI, val proximityDeviceAuth: WalletConfiguration.ProximityDeviceAuth = ProximityDeviceAuth.SIGNATURE, val verifierRequireEKU: String = "", val registrarRequireEKU: String = "", val statusIssuers: Map<String, List<String>> = emptyMap(), val requireIssuerName: Boolean = false, val issuerMetadataRoots: String = "", val requireSignedIssuerMetadata: Boolean = false, val requireIssuerMetadataName: Boolean = false, val maxIssuerMetadataAgeSeconds: Long = 0)

NewWallet's configuration.

Link copied to clipboard

An error from OID4VCgo: a stable code, the issuer's, Authorization Server's or Verifier's own error code when it gave one (protocolError), and a message for logs: it never carries personal data, a remote party's own description, a URL's path or query, or control characters. description is a sentence fit to show the holder; isRetryable says whether trying the same step again may succeed.

Link copied to clipboard
interface WalletProvider

The Wallet Provider's backend, which attests the wallet and its keys (HAIP 1.0 §4.4.1, §4.5.1). Keys are public JWKs, as JSON; the results are compact JWTs. A real one attests only after checking platform evidence (Key Attestation) that it's talking to the genuine app.