Security guidance
Overview
Use this security guidance when building and releasing an Android digital wallet application that integrates the NFC Wallet SDK.
This guidance is a set of security guidelines you must apply before release.
General security guidelines
Use the latest NFC Wallet SDK release
Use the latest NFC Wallet SDK release. It includes the latest security updates and fixes.
Use the Release build of the NFC Wallet SDK
Before publishing to Google Play Store configure the digital wallet application to use the Release build.
The Dev SDK variant is not allowed in Production Environment.
Strip debug symbols
Do not release with debug symbols. This practice increases the complexity of reverse engineering efforts and prevents the easy identification of sensitive variables, structures, and logic.
Prevent sensitive data leaks
Clear sensitive data from the UI before the application enters the background.
Encrypt or wipe data until the application returns to the foreground.
Avoid logging sensitive information.
Use code obfuscation
Use obfuscation to increase the cost of reverse engineering.
Secure network communication
Use HTTPS for all network calls to the digital wallet backend.
Avoid self-signed certificates.
If you implement certificate pinning, follow these guidelines:
Match the hostname against the leaf certificate.
Validate the full certificate chain against the system trust store.
Reject expired certificates.
Pin the SHA-256 hash of the root CA or leaf certificate.
If you send confidential data containing personally identifiable information (PII), add application-level encryption and authentication when needed.
Add RASP protection
Use a commercial Runtime Application Self Protection (RASP) solution.
Detect and respond to:
Root or jailbreak.
Debugging.
Hooking.
App tampering.
Emulator execution.
Logging
Avoid writing sensitive data to device logs.
Use build flags to exclude debug logs from Production Environment builds.
On Android, logs are a shared resource that are accessible with the READ_LOGS permission, and inappropriate logging of user sensitive information can lead to unintended data leaks to other application.
Adopt secure coding practices
Apply secure coding practices throughout development. For exemple you should:
perform input validation.
proper management of memory.
use secure C functions.
avoide usage of immutable containers for storing sensitive data.
For a baseline checklist, see OWASP Secure Coding Practices.
These practices can be enforced using static code analysis tools such as PMD or HP Fortify.
Perform audits and penetration testing
Perform architecture and code audits, plus penetration testing, to identify vulnerabilities and assessing the overall security posture of the application.
Evaluate the resilience of application security
Check the OWASP MASVS (Mobile Application Security Verification Standard) on OWASP MASVS. This is the security requirements baseline for mobile application.
It is highly recommended to use the OWASP MSTG checklist to evaluate the security stature of your application.
Android developer security guidelines
Use Android security guidance for detailed, defense-in-depth recommendations before release.
Review these topics:
Use Android’s baseline security checklist as an additional reference to this guidance: Android security checklist.
Application-level protection
Verify the installer of your application
Verify your digital wallet application's installer package name at runtime.
Only trust installs from Google Play, which uses com.android.vending.
To prevent side-channel distribution or unauthorized installations from third-party sources.
Enforce security updates (force application update)
Ensure a forced application update in case of security fixes.
Block access to the service when the installed version is below the minimum allowed version.
Store resources in internal storage
Keep your digital wallet application and its resources in internal storage. This reduces the risk of a man-in-the-disk (MITD) attack. In MITD attacks, an attacker may modify or manipulate files stored on external storage.
Application should not allow itself to be moved to external storage using the android:installLocation manifest attribute.
Support SDK-supported OS versions
Run your digital wallet application only on OS versions supported by the NFC Wallet SDK. This reduces functional issues and security gaps on older devices. It also improves the end user experience.
Require a device lock screen
Require the device to have a screen lock. Use a PIN, pattern, or password. Block sensitive flows if no screen lock is set.
Prevent excessive permissions
Declare only the Android permissions required for your digital wallet application.
Unneeded permissions expand the attack surface and can expose privileged data.
Restrict exported components
Android applications are built from components:
Activities
Services
Broadcast receivers
Content providers
Consider:
Inter-application communication as risky.
Every exported component as a public entry point into your digital wallet application, thereby increasing its exposure to risks and attacks.
We recommend to design your application
with only a main activity made publicly accessible.
All other components should explicitly have the attribute
export=false.
For components to be public, consider protecting them with custom permissions.
Disable debugging in release builds
Ensure the release build of your digital wallet application is not debuggable.
You must:
Set
android:debuggable="false"on the<application>element inAndroidManifest.xml.And ensure your final APK is not debuggable.
To verify your final APK:
Run:
In the output, locate the
<application>element. Confirmandroid:debuggableis set to0x0.
Automate this verification as part of your CI pipeline.
Evaluate app links and deep links
Deep links and app links can increase the attack surface of the application. They can introduce risks such as link hijacking and unintended exposure of sensitive functionality. Behavior varies by Android version:
Before Android 12 (API level 31), if the application includes any non-verifiable links, the system may not verify all Android App Links for that application.
Starting from Android 12 (API level 31), the application benefits from a reduced attack surface. Unless the target application is approved for the specific domain in the web intent, the web intent resolves to the end user’s default browser application.
Enumerate all deep links. Verify correct website association.
Test every operation exposed through deep links and app links.
Always validate all input data. Treat all inputs as untrustworthy. Validation ensures the application processes only the data it expects.
Prevent screenshots and app previews
Set FLAG_SECURE on any activity that displays sensitive data. This prevents sensitive data leak through screenshots in the foreground.
Add the flag in Activity.onCreate() before rendering the UI:
Also clear sensitive information in your activities in onPause() method.
Proper app signing
Sign your release APK with:
APK Signature Scheme v1 and v2 for broad Android compatibility.
APK Signature Scheme v3 when targeting Android 9 (API level 28) and later.
Keep the APK signing key under your control. Do not share it.
Verify signatures with apksigner from Android SDK Build Tools:
Prevent backup of application data
Disable Android backup and restore for your digital wallet application.
Set android:allowBackup="false" on the <application> element in AndroidManifest.xml.
By default, android:allowBackup is true. This allows the OS to back up and restore application data. This can have security implications.
The backup feature can also let an end user copy application data when USB debugging is enabled.
Once exported, the data can be inspected outside the app sandbox.
Limit accessibility on sensitive screens
Android accessibility services can read UI content and trigger actions. This is essential for users with disabilities. It can also be abused by malware to capture sensitive data.
Decide, per screen, whether accessibility services should access sensitive content. Use the techniques below to reduce data leakage through accessibility events.
Blocking accessibility can prevent some end users from using your digital wallet application. Apply these controls only to truly sensitive screens.
Detect enabled accessibility services
Check whether any accessibility service is enabled. If needed, limit specific flows when services are enabled.
Allowlist accessibility services
Use the Android APIs to list enabled services. Maintain an allowlist or blocklist based on your risk policy. If a disallowed service is enabled, warn the end user or block the operation.
Block accessibility for a view
You can disable accessibility for a view subtree. This prevents accessibility events from the view and its children.
Prevent sensitive text from being exposed in accessibility events
By default, Android may briefly show the last typed character before masking it. This can expose partial input (for example, ***1) to accessibility services. If this is unacceptable for your threat model, mask characters immediately.
Prevent overlay attacks
Android overlays let one application render UI on top of another. This can enable phishing and data theft. It is a common technique in overlay attacks.
Example phishing scenario: An attacker draws a full-screen overlay on top of your digital wallet application. The overlay impersonates a login or PIN screen. This increases the chance of stealing end user credentials.
Protect sensitive screens and inputs. Examples include login, PIN entry, and provisioning.
Android 12 (API level 31) and later
Call setHideOverlayWindows(true) on sensitive views. This blocks non-system overlays for those views.
Android 2.3 (API level 9) to Android 11 (API level 30)
Use touch filtering on sensitive views. This helps detect touches obscured by overlays.
Use one or more of these options:
Enable
setFilterTouchesWhenObscured(true)on sensitive views.Override
onFilterTouchEventForSecurity()to reject obscured touch events.Check touch events in
onTouch()and reject obscured events.
Touch filtering does not cover every overlay technique. Some overlays can avoid forwarding touch events. Treat this as defense-in-depth, not a complete solution.
For more details, see Protecting against Android Overlay Attacks.
Use a proprietary keyboard
Avoid third-party keyboards for sensitive inputs. Third-party keyboards can capture what an end user types.
Use a proprietary keyboard that is available only in your digital wallet application. Use it for PINs, passcodes, passwords, and personally identifiable information (PII).
If you cannot implement a proprietary keyboard, use a dedicated PIN pad for passcode entry. Randomize the key layout per session. This reduces shoulder surfing risk. It can also reduce the impact of some accessibility malware.
Data protection
Protect data in transit
Use TLS 1.2 or TLS 1.3 for all network traffic between your digital wallet application and your issuer backend.
Configure your issuer backend to use strong cipher suites.
In addition:
Implement certificate pinning in your digital wallet application.
On Android 7.0 (API level 24) and later, use Network security configuration to pin the domains your application calls.
Add application-level encryption and authentication on top of TLS to protect sensitive payloads (for example, personally identifiable information (PII)) between your digital wallet application and your issuer backend.
Protect stored data
Protect sensitive data stored on the device, even inside the application sandbox.
Assume a compromised device can expose local storage to malware.
It's recommended to encrypt and integrity-protect sensitive data at rest, using device-bound keys, and must require end-user authentication before access.
To encrypt all sensitive data at rest, application can use
AndroidX Security Crypto
EncryptedSharedPreferencesfor key-value data.AndroidX Security Crypto
EncryptedFilefor files.
For details, see Android guidance on data storage.
Authentication
Support biometric authentication
The digital wallet application must support biometric authentication for end-user authentication.
Provide a device credentials (keyguard) fallback when biometrics are unavailable.
Use Android Keystore with BiometricPrompt crypto objects when possible.
This binds keys to the device and detects biometric enrollment changes.
Enforce multi-factor authentication
Enforce multi-factor authentication (MFA) for sensitive operations in your digital wallet application.
MFA adds protection by requiring more than one authentication factor before access.
This reduces the risk of unauthorized access if one factor is compromised.
Cryptography guidelines
Keep Google Play security provider up to date
Use the Google Play services security provider to receive cryptography and TLS fixes on devices that do not receive timely OS updates.
The NFC Wallet SDK does not install, update, or prompt for this provider. Your digital wallet application is responsible for ensuring the Google Play services security provider is installed and up to date on the end user’s device.
Use secure random
Use java.security.SecureRandom for all security-sensitive randomness (generate any sensitive cryptographic keys or for any random data generation).
On Android 10 (API level 29) and later, prefer SecureRandom.getInstanceStrong() when you require the strongest available source of randomness.
Application hardening
Detect rooted devices
Detect a compromised device environment (for example, rooting frameworks and su binaries) before you initialize the NFC Wallet SDK and before you perform any sensitive operation.
See OWASP MSTG guidance on Android Anti-Reversing Defenses.
Detect hooking attempts
Hooking injects code into your digital wallet application at runtime. Attackers use it to intercept sensitive data (for example, cryptographic keys or PII), bypass security controls, or change application logic.
See OWASP MASVS: Android Anti-Reversing Defenses / Runtime Integrity Verification.
Detect debugger attachment
On compromised devices, an attacker can attach a debugger to a Release build of your digital wallet application. This enables step-by-step inspection of Java/Kotlin code and native libraries, and can expose sensitive logic and data.
Detect debugger attachment in both Java/Kotlin and native code, especially before you run sensitive flows. For more information.
See OWASP MASVS: Android Anti-Reversing Defenses / Anti-Debugging.
Detect emulator
Emulators are a non-trusted execution environment. They make dynamic analysis and instrumentation easier for attackers.
Detect emulator execution as early as possible. Do it at application startup, and before you initialize the NFC Wallet SDK.
See OWASP MASVS: Android Anti-Reversing Defenses / Emulator Detection.
Detect application tampering
Detect tampering by verifying the digital wallet application signing certificate hash at runtime.
This check helps detect repackaging attacks where an attacker modifies the binary or resources, then re-signs the APK. Attackers cannot reproduce your signing certificate.
Obfuscate the expected certificate hash to make it harder to locate and patch.
For background, see Implement Anti-tamper Techniques.
Optionally, send the signing certificate hash to your backend. Verify it server-side before honoring requests from the digital wallet application.
Obfuscate application
Obfuscate your digital wallet application and its components. This increases the cost of reverse engineering. It also makes it harder to locate sensitive logic and data.
Even if the NFC Wallet SDK is already obfuscated with DexGuard, you must obfuscate the Thales NFC Wallet SDK public APIs:
Ensure the ProGuard/R8 rules provided with the SDK packages are applied.
Pay special attention to the package flattening rule:
Use the package name util to keep obfuscation output consistent with the SDK rules.
Commercial obfuscation tools are available. On Android, we recommend DexGuard.
See OWASP MASVS: Android Anti-Reversing Defenses / Obfuscation.
Secure coding
Wipe sensitive data from memory
Store sensitive data (for example, cryptographic keys and personally identifiable information (PII)) in byte arrays.
In Java, you cannot reliably wipe immutable objects such as String and StringBuilder. You also cannot control how many copies are created in memory or how long they remain reachable.
Wipe sensitive data explicitly. Do not rely on the garbage collector.
Use a finally block to wipe sensitive buffers, even when you do not have a catch block. This reduces the risk of leaks if an exception occurs.
Follow secure coding standards
Follow secure coding standards from trusted sources such as Apple, Google, and OWASP (Open Web Application Security Project).
If you need Thales internal guidance, contact the Thales Handset Security Community to request access.
Enforce these standards with static code analysis tools such as PMD or Fortify. Add them to your CI pipeline to prevent regressions.
Run Android lint checks
Run Android Lint during development and before each release. Fix findings early to reduce security and quality risk.
Android Lint is a static analysis tool. It checks your project for correctness, security, performance, usability, accessibility, and internationalization issues.
Run lint locally and in your CI pipeline:
For details, see Android developer website: Improve your code with lint checks.
Protect assets
This section outlines best practices in app development to protect assets.
Activation code
Use in card tokenization with a limited time life cycle:
Treat as a short-lived secret. Do not log or store
FCM registration token
If the digital wallet application manages FCM at the app level:
Avoid persisting the FCM registration token longer than necessary.
Funding card information
If the digital wallet application collects payment card data:
Disable risky
EditFieldoptions, such as auto-complete, copy, paste, and so on.Use a secure keypad.
Validate inputs before use.
Do not store payment card data persistently.
Before showing the input screen, enforce runtime checks (rooting, hooking, debugging, and tampering detection).
Ensure confidentiality and integrity of this asset.
Apply the same controls to any other sensitive input sourced outside the app.
App signing certificate and TLS certificate
Control access to the app signing certificate.
Do not disclose it to non-trusted parties.
Ensure confidentiality and integrity of this asset.
QR / DSRP inputs data (Amount)
When the digital wallet application collects the amount:
Disable risky
EditFieldoptions, such as auto-complete, copy, paste, and so on.Use a secure keypad.
Apply the same controls to any other sensitive input sourced outside the app.
QR Code (2D barcode)
The app must be implemented to detect and to prevent the capturing of QR code in screenshots or from being viewed on non-secure displays.
Other sensitive assets
Obfuscate code and protect sensitive strings shipped in the binary.
Reassess assets on every release (new features could add new sensitive data).
Assess the value and criticality of each asset and apply the required protection.
Do not persist transient data. Clear sensitive data from memory when no longer needed.
Always consider the device untrusted. Use RASP to help protect the application binary and third-party libraries at runtime.
Last updated
Was this helpful?