From 4b44a087230bf1af730f29e901aba1cf64e8b82b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?simge=20yi=C4=9Fit?= <146586445+simge-yigit@users.noreply.github.com> Date: Sat, 6 Jun 2026 02:22:38 +0300 Subject: [PATCH 1/4] Fixes #3855-Update MASTG-KNOW-0048.md Clarified KeyChain usage and access permissions, emphasizing secure handling of private keys and certificates. Fixes #3855 --- knowledge/android/MASVS-STORAGE/MASTG-KNOW-0048.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/knowledge/android/MASVS-STORAGE/MASTG-KNOW-0048.md b/knowledge/android/MASVS-STORAGE/MASTG-KNOW-0048.md index 24eaf56d704..993196ced3e 100644 --- a/knowledge/android/MASVS-STORAGE/MASTG-KNOW-0048.md +++ b/knowledge/android/MASVS-STORAGE/MASTG-KNOW-0048.md @@ -4,9 +4,9 @@ platform: android title: KeyChain --- -The [KeyChain](https://developer.android.com/reference/android/security/KeyChain.html "Android KeyChain") class is used to store and retrieve _system-wide_ private keys and their corresponding certificates (chain). The user will be prompted to set a lock screen pin or password to protect the credential storage if something is being imported into the KeyChain for the first time. Note that the KeyChain is system-wide, every application can access the materials stored in the KeyChain. +The [KeyChain](https://developer.android.com/reference/android/security/KeyChain.html "Android KeyChain") class is used to store and retrieve _system-wide_ private keys and their corresponding certificates (chain). The user will be prompted to set a lock screen pin or password to protect the credential storage if something is being imported into the KeyChain for the first time.Note that although the KeyChain is system-wide, applications do not have unrestricted access to its contents. An app first requests permission for a specific key via `KeyChain.choosePrivateKeyAlias()`, and only after the user grants access can it retrieve the key with `getPrivateKey()` and the certificate chain with `getCertificateChain()`. For hardware-backed keys, the raw key material is never exposed to the app. Inspect the source code to determine whether native Android mechanisms identify sensitive information. Sensitive information should be encrypted, not stored in clear text. For sensitive information that must be stored on the device, several API calls are available to protect the data via the `KeyChain` class. Complete the following steps: -- Make sure that the app is using the Android KeyStore and Cipher mechanisms to securely store encrypted information on the device. Look for the patterns `AndroidKeystore`, `import java.security.KeyStore`, `import javax.crypto.Cipher`, `import java.security.SecureRandom`, and corresponding usages. -- Use the `store(OutputStream stream, char[] password)` function to store the KeyStore to disk with a password. Make sure that the password is provided by the user, not hard-coded. +- Make sure that private keys and certificates are stored in and accessed through the KeyChain instead of being hardcoded or written to app-private files in clear text. Look for the patterns `import android.security.KeyChain`, `KeyChain.choosePrivateKeyAlias`, `KeyChain.getPrivateKey`, and `KeyChain.getCertificateChain`, and corresponding usages. +- Make sure that the app verifies that the private key retrieved from the KeyChain is bound to secure hardware, so that it cannot be extracted even on a rooted device. Look for the patterns `KeyFactory`, `KeyInfo`, `getKeySpec`, `isInsideSecureHardware()` (deprecated in API level 31), and `getSecurityLevel()` (API level 31+), and corresponding usages. From db0db07297589263ff2bd3878b16b165a28c4666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?simge=20yi=C4=9Fit?= <146586445+simge-yigit@users.noreply.github.com> Date: Sat, 6 Jun 2026 20:14:18 +0300 Subject: [PATCH 2/4] Update MASTG-KNOW-0048.md Add explanation of KeyChain vs AndroidKeyStore differences and references --- knowledge/android/MASVS-STORAGE/MASTG-KNOW-0048.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/knowledge/android/MASVS-STORAGE/MASTG-KNOW-0048.md b/knowledge/android/MASVS-STORAGE/MASTG-KNOW-0048.md index 993196ced3e..152311c2992 100644 --- a/knowledge/android/MASVS-STORAGE/MASTG-KNOW-0048.md +++ b/knowledge/android/MASVS-STORAGE/MASTG-KNOW-0048.md @@ -4,9 +4,13 @@ platform: android title: KeyChain --- -The [KeyChain](https://developer.android.com/reference/android/security/KeyChain.html "Android KeyChain") class is used to store and retrieve _system-wide_ private keys and their corresponding certificates (chain). The user will be prompted to set a lock screen pin or password to protect the credential storage if something is being imported into the KeyChain for the first time.Note that although the KeyChain is system-wide, applications do not have unrestricted access to its contents. An app first requests permission for a specific key via `KeyChain.choosePrivateKeyAlias()`, and only after the user grants access can it retrieve the key with `getPrivateKey()` and the certificate chain with `getCertificateChain()`. For hardware-backed keys, the raw key material is never exposed to the app. +The [KeyChain](https://developer.android.com/reference/android/security/KeyChain) class is used to store and retrieve system-wide private keys and their corresponding certificate chains. The user will be prompted to set a lock screen PIN or password to protect the credential storage if something is being imported into the KeyChain for the first time. -Inspect the source code to determine whether native Android mechanisms identify sensitive information. Sensitive information should be encrypted, not stored in clear text. For sensitive information that must be stored on the device, several API calls are available to protect the data via the `KeyChain` class. Complete the following steps: +Note that although the KeyChain is system-wide, applications do not have unrestricted access to its contents. Access to a given key is mediated either by user consent — typically via `KeyChain.choosePrivateKeyAlias()`, which presents a system UI for the user to select which credential the app may use — or by device policy, where a Device or Profile Owner grants access through [`DevicePolicyManager`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager). Only after access has been granted can the app retrieve the key with `KeyChain.getPrivateKey()` and the certificate chain with `KeyChain.getCertificateChain()`. For hardware-backed keys, the raw key material is never exposed to the app (see the [Android Keystore system](https://developer.android.com/privacy-and-security/keystore)). -- Make sure that private keys and certificates are stored in and accessed through the KeyChain instead of being hardcoded or written to app-private files in clear text. Look for the patterns `import android.security.KeyChain`, `KeyChain.choosePrivateKeyAlias`, `KeyChain.getPrivateKey`, and `KeyChain.getCertificateChain`, and corresponding usages. -- Make sure that the app verifies that the private key retrieved from the KeyChain is bound to secure hardware, so that it cannot be extracted even on a rooted device. Look for the patterns `KeyFactory`, `KeyInfo`, `getKeySpec`, `isInsideSecureHardware()` (deprecated in API level 31), and `getSecurityLevel()` (API level 31+), and corresponding usages. +Note: `AndroidKeyStore` and `KeyChain` serve different purposes and should not be used interchangeably. The [`AndroidKeyStore`](https://developer.android.com/privacy-and-security/keystore) provider is used to store and use an application's *own* cryptographic keys, which only that app can access. `KeyChain`, on the other hand, is designed for user-selected, system-wide shareable private keys and certificate chains. To protect an app's own keys and data, prefer `AndroidKeyStore` (see @MASTG-KNOW-0043). + +Inspect the source code to determine which native Android mechanisms are used to handle sensitive information. Sensitive data should be encrypted, not stored in clear text. Specifically, private keys and certificates that must be stored on the device should be managed through the `KeyChain` class; to protect an app's own data and secrets, use the `AndroidKeyStore` (see @MASTG-KNOW-0043). Complete the following steps: + +* Make sure that private keys and certificates are stored in and accessed through the KeyChain instead of being hardcoded or written to app-private files in clear text. Look for the patterns `import android.security.KeyChain`, `KeyChain.choosePrivateKeyAlias`, `KeyChain.getPrivateKey`, and `KeyChain.getCertificateChain`, and their corresponding usages. +* Make sure that the app verifies that the private key retrieved from the KeyChain is bound to secure hardware, so that it cannot be extracted even on a rooted device. Look for the patterns `KeyFactory`, [`KeyInfo`](https://developer.android.com/reference/android/security/keystore/KeyInfo), `getKeySpec`, `isInsideSecureHardware()` (deprecated in API level 31), and `getSecurityLevel()` (API level 31+), and their corresponding usages. From 44c7797fc1452be336999afdf88472740a8f4086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?simge=20yi=C4=9Fit?= <146586445+simge-yigit@users.noreply.github.com> Date: Sat, 6 Jun 2026 20:21:58 +0300 Subject: [PATCH 3/4] Update MASTG-KNOW-0048.md Add explanation of KeyChain vs AndroidKeyStore differences and reference --- knowledge/android/MASVS-STORAGE/MASTG-KNOW-0048.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/knowledge/android/MASVS-STORAGE/MASTG-KNOW-0048.md b/knowledge/android/MASVS-STORAGE/MASTG-KNOW-0048.md index 152311c2992..fcb56c50747 100644 --- a/knowledge/android/MASVS-STORAGE/MASTG-KNOW-0048.md +++ b/knowledge/android/MASVS-STORAGE/MASTG-KNOW-0048.md @@ -8,9 +8,9 @@ The [KeyChain](https://developer.android.com/reference/android/security/KeyChain Note that although the KeyChain is system-wide, applications do not have unrestricted access to its contents. Access to a given key is mediated either by user consent — typically via `KeyChain.choosePrivateKeyAlias()`, which presents a system UI for the user to select which credential the app may use — or by device policy, where a Device or Profile Owner grants access through [`DevicePolicyManager`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager). Only after access has been granted can the app retrieve the key with `KeyChain.getPrivateKey()` and the certificate chain with `KeyChain.getCertificateChain()`. For hardware-backed keys, the raw key material is never exposed to the app (see the [Android Keystore system](https://developer.android.com/privacy-and-security/keystore)). -Note: `AndroidKeyStore` and `KeyChain` serve different purposes and should not be used interchangeably. The [`AndroidKeyStore`](https://developer.android.com/privacy-and-security/keystore) provider is used to store and use an application's *own* cryptographic keys, which only that app can access. `KeyChain`, on the other hand, is designed for user-selected, system-wide shareable private keys and certificate chains. To protect an app's own keys and data, prefer `AndroidKeyStore` (see @MASTG-KNOW-0043). +Note: `AndroidKeyStore` and `KeyChain` serve different purposes and should not be used interchangeably. The [`AndroidKeyStore`](https://developer.android.com/privacy-and-security/keystore) provider is used to store and use an application's _own_ cryptographic keys, which only that app can access. `KeyChain`, on the other hand, is designed for user-selected, system-wide shareable private keys and certificate chains. To protect an app's own keys and data, prefer `AndroidKeyStore` (see @MASTG-KNOW-0043). Inspect the source code to determine which native Android mechanisms are used to handle sensitive information. Sensitive data should be encrypted, not stored in clear text. Specifically, private keys and certificates that must be stored on the device should be managed through the `KeyChain` class; to protect an app's own data and secrets, use the `AndroidKeyStore` (see @MASTG-KNOW-0043). Complete the following steps: -* Make sure that private keys and certificates are stored in and accessed through the KeyChain instead of being hardcoded or written to app-private files in clear text. Look for the patterns `import android.security.KeyChain`, `KeyChain.choosePrivateKeyAlias`, `KeyChain.getPrivateKey`, and `KeyChain.getCertificateChain`, and their corresponding usages. -* Make sure that the app verifies that the private key retrieved from the KeyChain is bound to secure hardware, so that it cannot be extracted even on a rooted device. Look for the patterns `KeyFactory`, [`KeyInfo`](https://developer.android.com/reference/android/security/keystore/KeyInfo), `getKeySpec`, `isInsideSecureHardware()` (deprecated in API level 31), and `getSecurityLevel()` (API level 31+), and their corresponding usages. +- Make sure that private keys and certificates are stored in and accessed through the KeyChain instead of being hardcoded or written to app-private files in clear text. Look for the patterns `import android.security.KeyChain`, `KeyChain.choosePrivateKeyAlias`, `KeyChain.getPrivateKey`, and `KeyChain.getCertificateChain`, and their corresponding usages. +- Make sure that the app verifies that the private key retrieved from the KeyChain is bound to secure hardware, so that it cannot be extracted even on a rooted device. Look for the patterns `KeyFactory`, [`KeyInfo`](https://developer.android.com/reference/android/security/keystore/KeyInfo), `getKeySpec`, `isInsideSecureHardware()` (deprecated in API level 31), and `getSecurityLevel()` (API level 31+), and their corresponding usages. From 5f16f941df3a4f8786726abd2e0c26fd246145fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?simge=20yi=C4=9Fit?= <146586445+simge-yigit@users.noreply.github.com> Date: Sun, 7 Jun 2026 19:38:55 +0300 Subject: [PATCH 4/4] Update KeyChain documentation with a detailed explanation --- .../android/MASVS-STORAGE/MASTG-KNOW-0048.md | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/knowledge/android/MASVS-STORAGE/MASTG-KNOW-0048.md b/knowledge/android/MASVS-STORAGE/MASTG-KNOW-0048.md index fcb56c50747..ee6cb2355b2 100644 --- a/knowledge/android/MASVS-STORAGE/MASTG-KNOW-0048.md +++ b/knowledge/android/MASVS-STORAGE/MASTG-KNOW-0048.md @@ -4,13 +4,35 @@ platform: android title: KeyChain --- -The [KeyChain](https://developer.android.com/reference/android/security/KeyChain) class is used to store and retrieve system-wide private keys and their corresponding certificate chains. The user will be prompted to set a lock screen PIN or password to protect the credential storage if something is being imported into the KeyChain for the first time. +The [`KeyChain`](https://developer.android.com/reference/android/security/KeyChain) class (`android.security.KeyChain`) provides system-wide access to private keys and their corresponding certificate chains stored in the device's credential storage. It is a shared credential store. Apps request keys and certificates from it. Access is controlled separately for each credential. -Note that although the KeyChain is system-wide, applications do not have unrestricted access to its contents. Access to a given key is mediated either by user consent — typically via `KeyChain.choosePrivateKeyAlias()`, which presents a system UI for the user to select which credential the app may use — or by device policy, where a Device or Profile Owner grants access through [`DevicePolicyManager`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager). Only after access has been granted can the app retrieve the key with `KeyChain.getPrivateKey()` and the certificate chain with `KeyChain.getCertificateChain()`. For hardware-backed keys, the raw key material is never exposed to the app (see the [Android Keystore system](https://developer.android.com/privacy-and-security/keystore)). +The most common use case is client certificate authentication. The app presents a certificate and proves that it holds the matching private key. This is used in mutual TLS (mTLS), VPN, and Wi-Fi EAP authentication. +The store is system-wide, but an app does not gain access to its contents simply because credentials exist on the device. -Note: `AndroidKeyStore` and `KeyChain` serve different purposes and should not be used interchangeably. The [`AndroidKeyStore`](https://developer.android.com/privacy-and-security/keystore) provider is used to store and use an application's _own_ cryptographic keys, which only that app can access. `KeyChain`, on the other hand, is designed for user-selected, system-wide shareable private keys and certificate chains. To protect an app's own keys and data, prefer `AndroidKeyStore` (see @MASTG-KNOW-0043). +## Accessing keys and certificates -Inspect the source code to determine which native Android mechanisms are used to handle sensitive information. Sensitive data should be encrypted, not stored in clear text. Specifically, private keys and certificates that must be stored on the device should be managed through the `KeyChain` class; to protect an app's own data and secrets, use the `AndroidKeyStore` (see @MASTG-KNOW-0043). Complete the following steps: +Credentials enter the store in two ways. They are imported through the `Intent` returned by `createInstallIntent()`, or they are provisioned by device policy. -- Make sure that private keys and certificates are stored in and accessed through the KeyChain instead of being hardcoded or written to app-private files in clear text. Look for the patterns `import android.security.KeyChain`, `KeyChain.choosePrivateKeyAlias`, `KeyChain.getPrivateKey`, and `KeyChain.getCertificateChain`, and their corresponding usages. -- Make sure that the app verifies that the private key retrieved from the KeyChain is bound to secure hardware, so that it cannot be extracted even on a rooted device. Look for the patterns `KeyFactory`, [`KeyInfo`](https://developer.android.com/reference/android/security/keystore/KeyInfo), `getKeySpec`, `isInsideSecureHardware()` (deprecated in API level 31), and `getSecurityLevel()` (API level 31+), and their corresponding usages. +An app receives a credential after an `X509KeyManager` callback requests one. `choosePrivateKeyAlias()` presents a system UI where the user selects an available key. `getPrivateKey()` and `getCertificateChain()` then return the credential. + +An alias is the string identifier that names a credential. The app receives this alias and may reuse it. Remembering a chosen alias lets the app skip the selection prompt on later connections. A lookup with an invalid alias returns `null`. + +`getPrivateKey()` returns a `PrivateKey` handle. When a key is bound to secure hardware, the raw key material is not exposed to the app. The system performs the cryptographic operations on the app's behalf. + +## Access control + +Access to a given key is granted in one of three ways: user selection, device policy, or a credential management app. + +With user selection, `choosePrivateKeyAlias()` grants the app access to a specific alias through a system UI. + +With device policy, a Device Owner or Profile Owner grants the app access to a key pair through [`DevicePolicyManager`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager), for example with `grantKeyPairToApp()`. No user interaction is involved. + +A credential management app is a single app that holds the credential management app role. Since Android 12 (API level 31), this app can manage KeyChain credentials on the user's behalf. + +## Hardware-backed keys + +A private key from the KeyChain may be backed by secure hardware, or it may be implemented in software. Secure hardware here means a Trusted Execution Environment (TEE) or a StrongBox secure element. + +A [`KeyInfo`](https://developer.android.com/reference/android/security/keystore/KeyInfo) instance exposes the key's security level. It is obtained through `KeyFactory` and `getKeySpec()`. `KeyInfo.getSecurityLevel()` reports this level on API level 31 and above. It replaces `KeyInfo.isInsideSecureHardware()`, which was deprecated in API level 31. + +When a key is backed by secure hardware, the key material does not leave the secure environment (see the [Android Keystore system](https://developer.android.com/privacy-and-security/keystore)).