Keystore (Android): khái niệm, kiến trúc và nguyên lý hoạt động

Tác giả: IT Sectr Đã đăng: 2026-03-14 Thời gian đọc: 10 phút

Android Keystore là cơ chế hệ thống trong Android để lưu trữ an toàn các khóa mật mã trong cách ly phần cứng. Hệ thống sử dụng Trusted Execution Environment (TEE) trên các thiết bị có ARM TrustZone hoặc Secure Element chuyên dụng để bảo vệ khóa ở cấp độ chip. Theo Android Open Source Project, Keystore hỗ trợ các thuật toán RSA, EC, AES và HMAC với việc tạo khóa trực tiếp trong môi trường an toàn.

Những điểm chính

  • Android Keystore là nhà cung cấp KeyStore cách ly các khóa mật mã khỏi không gian người dùng Android
  • Các khóa được tạo bên trong TEE hoặc Secure Element và không bao giờ rời khỏi môi trường an toàn ở dạng văn bản thuần
  • Android 9+ thêm KeyGenParameterSpec.Builder với các tham số: purpose, digest, padding, userAuthenticationRequired
  • Bảo vệ khóa sinh trắc học yêu cầu xác nhận người dùng qua BiometricPrompt trước mỗi thao tác
  • Keymaster HAL là lớp trừu tượng hóa phần cứng thực hiện các thao tác mật mã trong TEE hoặc Secure Element

Android Keystore là gì?

Android Keystore là nhà cung cấp mật mã được triển khai trong Android từ API 1 (Android 1.0), nhưng hỗ trợ phần cứng đầy đủ xuất hiện từ Android 4.3 (API 18). Keystore giải quyết vấn đề lưu trữ an toàn các khóa riêng tư để ngay cả khi hệ điều hành bị xâm phạm, kẻ tấn công không thể trích xuất khóa ở dạng văn bản thuần.

Kiến trúc KeyStore trên Android

Kiến trúc Android Keystore bao gồm ba lớp: API ứng dụng (java.security.KeyStore), dịch vụ hệ thống (keystore daemon) và lớp phần cứng (Keymaster HAL). Ứng dụng truy cập qua API Java Cryptography Architecture (JCA) tiêu chuẩn, và dịch vụ hệ thống định tuyến yêu cầu đến Keymaster chạy trong TEE.

Tất cả các thao tác mật mã với khóa (ký, giải mã) được thực hiện bên trong TEE hoặc Secure Element. Các khóa không bao giờ rời khỏi môi trường an toàn — ứng dụng chỉ nhận được một handle (bí danh) để tham chiếu đến khóa. Đây là sự khác biệt cơ bản so với KeyStore phần mềm, nơi các khóa có thể truy cập trong bộ nhớ tiến trình.

Khác biệt với Java KeyStore

JKS (Java KeyStore) tiêu chuẩn hoặc BKS (Bouncy Castle) lưu trữ khóa trong các tệp được bảo vệ bằng mật khẩu. Android Keystore lưu trữ khóa trong cách ly phần cứng, nơi chúng được bảo vệ ngay cả khỏi người dùng root. JKS dễ bị tổn thương khi truy cập trực tiếp vào hệ thống tệp; Android Keystore thì không.

Một điểm khác biệt nữa: trong Android Keystore, các khóa có các tham số sử dụng nghiêm ngặt (purpose — chỉ sign/verify/encrypt/decrypt) được chỉ định khi tạo. Chúng không thể thay đổi sau đó, ngăn chặn việc sử dụng sai khóa.

Android Keystore hoạt động như thế nào?

Khi tạo khóa mới, ứng dụng gọi KeyPairGenerator hoặc KeyGenerator với KeyGenParameterSpec, chứa tất cả các tham số của khóa tương lai. Hệ thống chuyển yêu cầu đến Keymaster HAL, tạo khóa bên trong TEE và trả về một handle.

Quy trình tạo khóa

Phương thức KeyGenParameterSpec.Builder chấp nhận các tham số bắt buộc: tên khóa trong Keystore, mục đích (PURPOSE_SIGN, PURPOSE_ENCRYPT), thuật toán (RSA, EC, AES). Bổ sung: digest (SHA-256), padding (PKCS7), userAuthenticationRequired (sinh trắc học), keyValidityStart/End (giới hạn thời gian).

Sau khi đặt tham số, KeyPairGenerator.generateKeyPair() trả về KeyPair, trong đó PrivateKey là đối tượng ủy thác thao tác cho Keymaster. Khóa công khai có thể được trích xuất, khóa riêng tư thì không. Nó chỉ tồn tại bên trong TEE.

kotlin
import java.security.KeyPairGenerator
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties

fun generateKey(alias: String) {
    val spec = KeyGenParameterSpec.Builder(alias,
        KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFY
    ).setDigests(KeyProperties.DIGEST_SHA256)
     .setSignaturePaddings(KeyProperties.SIGN_PADDING_RSA_PKCS1)
     .setUserAuthenticationRequired(true)
     .build()

    val kpGen = KeyPairGenerator.getInstance(
        KeyProperties.KEY_ALGORITHM_RSA,
        "AndroidKeyStore"
    )
    kpGen.initialize(spec)
    kpGen.generateKeyPair()
}

Ký và xác minh

Signature cho ECDSA hoặc RSA-PSS được tạo qua API tiêu chuẩn: Signature.getInstance(algorithm).initSign(privateKey). Thao tác ký được thực hiện trong TEE: ứng dụng gửi dữ liệu, Keymaster ký bằng phần cứng và trả về chữ ký. Khóa và dữ liệu không trộn lẫn trong bộ nhớ dùng chung.

Để bảo vệ sinh trắc học, người dùng phải xác thực qua BiometricPrompt trước khi ký. Nếu không xác thực thành công, Keymaster không thực hiện thao tác và trả về CryptoAuthenticationException.

kotlin
import java.security.KeyStore
import java.security.Signature
import androidx.biometric.BiometricPrompt

fun signWithBiometric(alias: String) {
    val ks = KeyStore.getInstance("AndroidKeyStore")
    ks.load(null)
    val entry = ks.getEntry(alias, null) as KeyStore.PrivateKeyEntry
    val signature = Signature.getInstance("SHA256withRSA")
    signature.initSign(entry.privateKey)
    // BiometricPrompt với CryptoObject(signature) yêu cầu FaceID/PIN
}

Các loại lưu trữ KeyStore

Android hỗ trợ hai chế độ lưu trữ khóa: phần mềm (trên thiết bị không có TEE) và phần cứng (trên thiết bị có TEE hoặc Secure Element). Chế độ phụ thuộc vào khả năng của SoC và phiên bản Android.

KeyStore phần mềm (chỉ phần mềm)

Trên thiết bị không có Trusted Execution Environment (trước Android 4.3 hoặc SoC giá rẻ), các khóa được lưu trữ mã hóa bằng khóa chủ derived từ mật khẩu màn hình khóa. Chế độ này kém an toàn hơn — các khóa có thể truy cập trong bộ nhớ tiến trình trong các thao tác mật mã.

Mức bảo vệ dựa trên mã hóa tệp KeyStore bằng AES-256-GCM. Khóa mã hóa được tạo từ mật khẩu hoặc mã PIN của người dùng qua Scrypt (PBKDF2 với số lần lặp cao).

KeyMaster phần cứng (TEE/Secure Element)

Trên thiết bị hiện đại, Keymaster 4.x được sử dụng trong TEE (ARM TrustZone). Các khóa được tạo, lưu trữ và sử dụng độc quyền bên trong TrustZone. Ngay cả nhân Linux cũng không có quyền truy cập vào khóa riêng tư — chỉ Keymaster HAL mới có thể thực hiện thao tác.

Secure Element (ví dụ: eSE trong Samsung Knox hoặc StrongBox trong Google Pixel 3+) là chip riêng biệt với bộ xử lý và bộ nhớ riêng. Nó được chứng nhận Common Criteria EAL 4+ và cung cấp mức bảo vệ tối đa, bao gồm bảo vệ chống can thiệp vật lý.

LoạiVị trí lưu trữMức bảo vệCó từ API
Phần mềmTệp /data/misc/keystoreTrung bình (AES-256)API 1+
Keymaster 3TEE (TrustZone)CaoAPI 23+
Keymaster 4TEE + Secure I/ORất caoAPI 28+
StrongBoxSecure Element phần cứngTối đaAPI 28+, tùy chọn

Làm việc với API KeyStore

Android Keystore được tích hợp vào Java Cryptography Architecture (JCA). Để truy cập nhà cung cấp, sử dụng KeyStore.getInstance("AndroidKeyStore"). API có sẵn từ API 18.

Tạo và tải KeyStore

Phương thức KeyStore.load(null) tải vùng chứa KeyStore của ứng dụng. Không cần mật khẩu — Android sử dụng ngữ cảnh ứng dụng và UID của nó để kiểm soát truy cập. Mỗi ứng dụng chỉ thấy các mục nhập của riêng mình trừ khi sử dụng UID dùng chung.

Các phương thức setEntrygetEntry làm việc với KeyStore.PrivateKeyEntry, SecretKeyEntry hoặc TrustedCertificateEntry. Tham số ProtectionParameter luôn là null cho Android Keystore (bảo vệ được thực hiện ở cấp hệ thống).

kotlin
import java.security.KeyStore
import java.security.cert.Certificate
import android.security.keystore.KeyProtection

fun storeSecretKey(alias: String, key: SecretKey) {
    val ks = KeyStore.getInstance("AndroidKeyStore")
    ks.load(null)
    val prot = KeyProtection.Builder(
        KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
    ).setBlockModes(KeyProperties.BLOCK_MODE_GCM)
     .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
     .setUserAuthenticationRequired(true)
     .build()
    ks.setEntry(alias, KeyStore.SecretKeyEntry(key), prot)
}

Kiểm tra loại lưu trữ

Sử dụng KeyCharacteristics, bạn có thể xác định môi trường lưu trữ khóa: KeyStore phần mềm, TEE hoặc StrongBox. Phương thức getKeyCharacteristics() trả về một tập cờ: FLAG_HARDWARE (keymaster), FLAG_SECURE_ELEMENT (StrongBox), FLAG_TRUSTED_USER_PRESENCE_REQUIRED (sinh trắc học).

Thuật toán và bảo mật

Android Keystore hỗ trợ nhiều loại thuật toán mật mã được chia thành ba loại: bất đối xứng, đối xứng và MAC. Hỗ trợ thuật toán cụ thể phụ thuộc vào phiên bản Keymaster HAL.

Các thuật toán được hỗ trợ

RSA (1024–4096 bit) — để ký (PKCS1, PSS) và mã hóa (OAEP, PKCS1). EC (P-224, P-256, P-384, P-521) — để ký ECDSA và thỏa thuận khóa ECDH. AES (128, 256 bit) — để mã hóa đối xứng ở chế độ CBC, CTR, GCM. HMAC (SHA1, SHA256, SHA512) — để xác thực tin nhắn.

Cho mỗi khóa, setPurposes được chỉ định để hạn chế các thao tác có thể. Khóa RSA với PURPOSE_SIGN không thể được sử dụng để mã hóa, ngay cả khi kẻ tấn công có quyền truy cập API. Đây là việc thực thi sử dụng khóa ở cấp phần cứng.

Bảo vệ khỏi xâm phạm

Keymaster bao gồm bộ đếm số lần xác thực sinh trắc học thất bại. Sau một số lần thất bại nhất định (có thể cấu hình qua setInvalidatedByBiometricEnrollment), khóa trở nên không khả dụng và cần xóa/tạo lại. Khi tất cả các mẫu sinh trắc học bị xóa, tất cả khóa có userAuthenticationRequired=true tự động bị vô hiệu hóa.

Key Attestation (Android 8.1+) cũng được hỗ trợ: theo yêu cầu của ứng dụng, Keymaster ký một chứng chỉ với thông tin về đặc tính của khóa (phần cứng/phần mềm, thuật toán, mục đích). Máy chủ có thể xác minh chứng chỉ này để xác nhận rằng khóa được tạo trong môi trường đáng tin cậy.

Câu hỏi thường gặp

Sự khác biệt giữa Android Keystore và Java KeyStore là gì?

Java KeyStore lưu trữ khóa trong tệp được bảo vệ bằng mật khẩu (JKS, BKS). Android Keystore sử dụng cách ly phần cứng qua TEE hoặc Secure Element. Java KeyStore dễ bị tổn thương với truy cập root; Android Keystore thì không, vì các khóa riêng tư không bao giờ rời khỏi môi trường an toàn.

Có thể nhập khóa hiện có vào Android Keystore không?

Có, qua KeyStore.setEntry với KeyProtection. Tuy nhiên, khóa được nhập sẽ không có bảo vệ phần cứng — nó sẽ được lưu trữ trong Keystore phần mềm, được mã hóa bằng khóa chủ. Để bảo mật tối đa, hãy luôn tạo khóa bên trong Keystore.

Làm thế nào để kiểm tra thiết bị có hỗ trợ KeyStore phần cứng không?

Sử dụng KeyChain.isBoundKeyAlgorithm hoặc kiểm tra KeyCharacteristics sau khi tạo khóa. Sự hiện diện của FLAG_HARDWARE trong các đặc tính có nghĩa là khóa được tạo trong TEE. Bạn cũng có thể kiểm tra android.security.keystore.isHardwareBacked().

Điều gì xảy ra với các khóa khi gỡ cài đặt ứng dụng?

Khi gỡ cài đặt ứng dụng, Android xóa tất cả khóa của nó khỏi Keystore. Dữ liệu bị mất không thể khôi phục. Khi cài đặt lại, ứng dụng phải tạo khóa mới. Sao lưu khóa qua TEE là không thể về mặt kiến trúc.

KeyStore bảo vệ khỏi các cuộc tấn công gỡ lỗi như thế nào?

Trên thiết bị bị khóa, Keymaster không thực hiện bất kỳ thao tác nào. Khóa có userAuthenticationRequired=true yêu cầu xác nhận sinh trắc học mỗi lần. Ngay cả với quyền truy cập root, kẻ tấn công không thể gọi Keymaster trực tiếp — chỉ thông qua dịch vụ Android Keystore.

Tổng kết

  • Android Keystore là nhà cung cấp mật mã JCA với cách ly khóa phần cứng qua TEE hoặc Secure Element
  • Các khóa được tạo bên trong TrustZone và không bao giờ rời khỏi môi trường an toàn ở dạng văn bản thuần
  • KeyGenParameterSpec định nghĩa các tham số khóa: purpose, digest, padding, userAuthenticationRequired, keyValidity
  • Keymaster HAL triển khai ba cấp độ: phần mềm, TEE (Keymaster 3/4) và StrongBox (Secure Element phần cứng)
  • Bảo vệ khóa sinh trắc học được cung cấp qua setUserAuthenticationRequired và BiometricPrompt với CryptoObject
  • Key Attestation (API 28+) cho phép xác minh phía máy chủ rằng khóa được tạo trong môi trường phần cứng
  • Sử dụng Android Keystore để lưu trữ khóa riêng tư cho ký, mã hóa và xác thực trong ứng dụng Android

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm