Our Android mobile payments solution uses industry-recognized standard cryptographic algorithms and operations to generate cryptographic keys, to protect assets, and to encrypt sensitive data for transportation between the components of the solution.
This chapter provides an overview of all keys used in our solution, including details like the algorithms used to create them.
Key hierarchy
This section describes the hierarchy of keys used in our solution. For the details of the keys shown in the diagram, refer to the inventory of keys.
The following key hierarchy diagram illustrates that:
- The Android Keystore system on the COTS device is used for generating the Local Storage key and the Device key.
- The white-box cryptography library inside the SDK is used for generating the Sensitive Storage key, the SDK key, and the TR-34 encryption key. The SDK key is used for signing the Device key.
- The HSM is used for generating separate Base Derivation Keys (BDK) for PIN and for cardholder data, and for generating the Server key.
The key hierarchy diagram also illustrates that:
- There are separate initial encryption keys for PIN and for cardholder data. Each IPEK key is generated using the corresponding BDK and then TR-34 wrapped using an Ephemeral key (KE) that is encrypted using the TR-34 encryption key.
- The resulting Derived Unique Key per Transaction (DUKPT) state for PIN and the DUKPT state for cardholder data are initialized using the TR-34 wrapped IPEK and stored on the device, protected by the Sensitive Storage Key and a corresponding Local Storage Key.
Inventory of keys
The following sections describe the cryptographic keys used in our solution:
Authentication keys
For authentication, we use the following cryptographic keys:
SDK key pair
Characteristic | Description |
---|---|
Purpose | Authenticate the setup token. Sign the TR-34 encryption public key that is sent to the backend to create the TR-34 block. |
Protection | Protected by Zimperium zKeyBox. |
Uniqueness | Unique per SDK version. |
Algorithm, key size | ECDSA, p256-sha256. |
Key lifetime | A single SDK version. |
Key generation location | Generated in the build environment. |
Key generation method | Generated while building the SDK, using the Zimperium zKeyBox white-box encryption solution. |
Key usage location | SDK CryptoLib Native, Adyen backend. |
Key loading | Not applicable. |
Transport | The public key is extracted from the build environment. |
Storage | The public key is stored on the Adyen backend. The private key is stored in the SDK in obfuscated/encrypted form. |
Removal | Revoked by the Adyen backend. |
Device key pair
Characteristic | Description |
---|---|
Purpose | Authenticate the COTS device. Enable the backend to validate requests from the SDK. |
Protection | Protected by Android Keystore. |
Uniqueness | Unique per COTS device. |
Algorithm, key size | ECDSA, p256-sha256. |
Key lifetime | Single session. |
Key generation location | The Android Keystore system on the COTS device. |
Key generation method | Generated using the Android Keystore system on the COTS device. |
Key usage location | SDK, Adyen backend. |
Key loading | Not applicable. |
Transport | The public key is sent in the setup token which is signed by the SDK key, and is then embedded in the session token. See mutual authentication. |
Storage | Android Keystore. |
Removal | Single session. |
Server key pair
Characteristic | Description |
---|---|
Purpose | Enable the SDK to validate responses from the backend. |
Protection | Protected by HSM. |
Uniqueness | Unique per solution. |
Algorithm, key size | ECDSA, p256-sha256. |
Key lifetime | Long, approximately one year. |
Key generation location | HSM machine. |
Key generation method | Generated in the HSM machine. |
Key usage location | SDK (public component), Adyen backend |
Key loading | Not applicable. |
Transport | Encrypted in a TLS channel. |
Storage | SDK Secure Storage, HSM. |
Removal | Made expired by the Adyen backend after 1 year. |
Transaction and PIN protection keys
We use:
- Base Derivation Key for Cardholder Data (BDK_CHD)
- Base Derivation Key for PIN (BDK_PIN)
- TR-34 encryption key pair
- Derived Unique Key per Transaction for Cardholder Data (DUKPT_CHD)
- Derived Unique Key per Transaction for PIN (DUKPT_PIN)
- Local Storage Key for DUKPT_CHD (LSK_CHD)
- Local Storage Key for DUKPT_PIN (LSK_PIN)
- Sensitive Storage Key (SSK)
Base Derivation Key for Cardholder Data (BDK_CHD)
Characteristic | Description |
---|---|
Purpose | Key that is shared between HSMs so that all HSMs can derive the same keys using DUKPT CHD. |
Protection | Protected by HSM. |
Uniqueness | Unique per environment. |
Algorithm, key size | AES-128. |
Key lifetime | Very long. |
Key generation location | HSM machine. |
Key generation method | Key ceremony ensuring dual control. |
Key usage location | HSM. |
Key loading | Key ceremony in a secure room. |
Transport | Not applicable. |
Storage | HSM. |
Removal | Keys in the HSM are removed by destroying their aliases, thus rendering them inaccessible. |
Base Derivation Key for PIN (BDK_PIN)
Characteristic | Description |
---|---|
Purpose | Key that is shared between HSMs so that all HSMs can derive the same keys using DUKPT PIN. |
Protection | Protected by HSM. |
Uniqueness | Unique per environment. |
Algorithm, key size | AES-128. |
Key lifetime | Very long. |
Key generation location | HSM machine. |
Key generation method | Key ceremony ensuring dual control. |
Key usage location | HSM. |
Key loading | Key ceremony in a secure room. |
Transport | Not applicable. |
Storage | HSM. |
Removal | Keys in the HSM are removed by destroying their aliases, thus rendering them inaccessible. |
TR-34 encryption key pair
Characteristic | Description |
---|---|
Purpose | Encryption key for TR-34 (KKRD in the TR-34 standard). Used in the key loading process to encrypt the Ephemeral key (KE), which in turn encrypts the actual payload (the IPEK) within the TR-34 block. |
Protection | Protected by Zimperium zKeyBox. Signed by device key pair. |
Uniqueness | Unique per key loading operation. |
Algorithm, key size | RSA-2048. |
Key lifetime | Ephemeral: one key loading operation. |
Key generation location | White-box inside the SDK. |
Key generation method | Zimperium zKeyBox white-box encryption solution. The key loading request itself is signed using the Device key. |
Key usage location | SDK, Adyen backend. |
Key loading | Not applicable. |
Transport | The TR-34 encryption public key is signed using the SDK key before sending the public key to the backend. The key loading request itself is signed using the Device key. |
Storage | Not applicable. |
Removal | The key buffer is cleared on the SDK side immediately after the operation is completed. |
Derived Unique Key per Transaction for Cardholder Data (DUKPT_CHD)
Characteristic | Description |
---|---|
Purpose | Encrypt sensitive card data. |
Protection | Protected by Zimperium zKeyBox. |
Uniqueness | Unique per transaction. |
Algorithm, key size | AES-128. |
Key lifetime | App installation. |
Key generation location | The initial key "IPEK" is generated by the HSM machine. The SDK derives DUKPT future keys using the white-box library. |
Key generation method | Generated using the TR-34 wrapped IPEK and the KSN. |
Key usage location | SDK, Adyen backend. |
Key loading | Loaded throw TR34, using the TR-34 encryption key pair. |
Transport | Protected in TR-34 block. |
Storage | The DUKPT state is only generated and updated inside of the white-box library and then exported in a protected format (encrypted under the white-box key). Whenever we export this state, we generate a new AES-128 key and encrypt the DUKPT state with it, returning to the Kotlin code a blob of data that contains Encrypt(protected DUKPT)+protected AES key . The Kotlin code then encrypts this blob of data again using the default storage mechanism described above with an integrity check and encrypted under the device Keystore. |
Removal | Removed when the app is uninstalled. |
Derived Unique Key per Transaction for PIN (DUKPT_PIN)
Characteristic | Description |
---|---|
Purpose | Encrypt PIN data. |
Protection | Protected by Zimperium zKeyBox. |
Uniqueness | Unique per transaction. |
Algorithm, key size | AES-128. |
Key lifetime | App installation. |
Key generation location | The initial key "IPEK" is generated by the HSM machine. The SDK derives DUKPT future keys using the white-box library. |
Key generation method | Generated using the TR-34 wrapped IPEK and the KSN. |
Key usage location | SDK, Adyen backend. |
Key loading | Loaded throw TR34, using the TR-34 encryption key pair. |
Transport | Protected in the TR-34 block. |
Storage | The DUKPT state is only generated and updated inside of the white-box library and then exported in a protected format (encrypted under the white-box key). Whenever we export this state, we generate a new AES-128 key and encrypt the DUKPT state with it, returning to the Kotlin code a blob of data that contains Encrypt(protected DUKPT)+protected AES key . The Kotlin code then encrypts this blob of data again using the default storage mechanism described above with an integrity check and encrypted under the device Keystore. |
Removal | Removed when the app is uninstalled. |
Local Storage Key for DUKPT_CHD (LSK_CHD)
Characteristic | Description |
---|---|
Purpose | Second layer of protection of the DUKPT Cardholder Data state. |
Protection | Protected by Android Keystore. |
Uniqueness | Unique per DUKPT. |
Algorithm, key size | AES-128. |
Key lifetime | App installation. |
Key generation location | The Android Keystore system on the COTS device. |
Key generation method | Generated using the Android Keystore system on the COTS device. |
Key usage location | The SDK. |
Key loading | Not applicable. |
Transport | Not applicable. |
Storage | Android Keystore. |
Removal | Removed when the app is uninstalled. |
Local Storage Key for DUKPT_PIN (LSK_PIN)
Characteristic | Description |
---|---|
Purpose | Second layer of protection of the DUKPT PIN state. |
Protection | Protected by Android Keystore. |
Uniqueness | Unique per DUKPT. |
Algorithm, key size | AES-128. |
Key lifetime | App installation. |
Key generation location | The Android Keystore system on the COTS device. |
Key generation method | Generated using the Android Keystore system on the COTS device. |
Key usage location | The SDK. |
Key loading | Not applicable. |
Transport | Not applicable. |
Storage | Android Keystore. |
Removal | Removed when the app is uninstalled. |
Sensitive Storage Key (SSK)
Characteristic | Description |
---|---|
Purpose | First layer of protection of the DUKPT state. |
Protection | Protected by Zimperium zKeyBox. |
Uniqueness | Pair DUKPT derivation. |
Algorithm, key size | AES-128. |
Key lifetime | Persistent between transactions. |
Key generation location | White-box inside the SDK. |
Key generation method | Zimperium zKeyBox white-box encryption solution. |
Key usage location | Zimperium zKeyBox white-box encryption solution. |
Key loading | Not applicable. |
Transport | Not applicable. |
Storage | Zimperium zKeyBox white-box encryption solution. |
Removal | This single-use key is dropped after a new DUKPT state is generated. |
Key Serial Number
The Key Serial Number (KSN) is not a key, but is listed in this chapter because it is used in the DUKPT process.
Characteristic | Description |
---|---|
Purpose | Used for generating the IPEK on the backend using DUKPT to ensure that all HSMs generate the same key. |
Uniqueness | Unique per key exchange. |
Lifetime | Used for a single key exchange. |
The KSN scheme is as shown in the following table.
Hex digits | Value | Field | Usage |
---|---|---|---|
1 | - | Prefix | Identifies the KSN scheme:
|
2 - 4 | 0xFFF | Prefix | Reserved for storing more information in the future. |
5 | - | BDK identifier | Region. |
6 | - | BDK identifier | Payment terminal vendor. |
7 | - | BDK identifier | Purpose (PIN, DATA, MAC, and so on). |
8 | - | BDK identifier | Algorithm (AES, TDES). |
9 - 10 | - | BDK identifier | Version of the BDK. |
11 - 16 | - | Terminal ID | Increasing counter that represents a single terminal or SDK installation. |
17 - 24 | - | Transaction counter | Increasing counter that represents the transaction number of the terminal or SDK installation. |