Security Best Practices
To maintain compliance with PSD2 (Payment Services Directive 2) and ensure robust application security, it is critical to properly manage how sensitive data is handled in memory.
Overview
When handling authentication and user verification, sensitive data is temporarily loaded into the device's memory. To prevent this data from being exposed in the event of a memory dump or a device-level compromise, our primary recommendation is to overwrite secrets as early as possible after use so they are completely erased from memory.
This guide explains the different types of data handled by the SDK, their classification, and how you should manage them in your application's memory lifecycle.
Classification definitions
- SECRET: This data is highly sensitive. You should overwrite it in memory immediately after it is no longer required.
- NOT SECRET: This data is not considered highly sensitive. You do not need to overwrite it after use, although doing so is safe and acceptable.
Data classification and handling
Below is a breakdown of the specific data types, their security classification, and the reasoning behind their memory management requirements.
1. User inputs and codes
- PIN (
SECRET) The user's PIN must not be stored anywhere and should be overwritten immediately after it's sent to the controller and no longer needed. - Activation code (
SECRET) This is a one-time code. Because it could potentially be copied and used as long as the session remains valid (typically a maximum of 5 minutes), it must be erased from memory right after the activation is triggered. - Recovery code (
SECRET) Similar to a PIN code in terms of its validity lifecycle. It must be overwritten as soon as the recovery process is successfully initiated or rejected.
2. Authorisation token
- Token ID (
NOT SECRET) This is a hash that is only valid for the specific application on the device during recovery operations. Because it cannot be utilized outside of this specific context, it does not strictly need to be overwritten.
You can find more about how the authorisation token is used in the Account recovery feature page.
Memory management in Java and Kotlin
When handling SECRET data in Java or Kotlin, do not store the values as String objects.
Strings are immutable in the JVM. Once a String is created, its value cannot be modified or overwritten. It will remain in memory until the Garbage Collector unpredictably decides to clean it up, leaving the sensitive data vulnerable to memory dumping and analysis.
Instead of strings, you should always use mutable data structures, such as CharArray or ByteArray, to store sensitive information. This allows you to explicitly "shred" or overwrite the data with zeros or null characters the exact moment after sending the sensitive data to the Encap SDK.
How to shred arrays
Once the secret has been used, immediately clear the array contents. It is best practice to wrap your logic in a try-finally block to ensure the memory is shredded even if an exception occurs during processing.
- Kotlin
- Java
fun processPin(pin: CharArray) {
try {
// 1. Process the sensitive data
verifyPin(pin)
} finally {
// 2. Shred the data by overwriting it with zeros
pin.fill('\u0000')
}
}
import java.util.Arrays;
void processPin(char[] pin) {
try {
// 1. Process the sensitive data
verifyPin(pin);
} finally {
// 2. Shred the data by overwriting it with zeros
Arrays.fill(pin, '\u0000');
}
}
- Kotlin
- Java
fun processSecret(secret: ByteArray) {
try {
// 1. Use the sensitive byte array
processSecret(secret)
} finally {
// 2. Shred the data by overwriting it with zeros
secret.fill(0)
}
}
import java.util.Arrays;
void processSecret(byte[] secret) {
try {
// 1. Use the sensitive byte array
processSecret(secret);
} finally {
// 2. Shred the data by overwriting it with zeros
Arrays.fill(secret, (byte) 0);
}
}