An toàn hơn khi làm việc với dữ liệuMột phần của Android Jetpack.
Thư viện bảo mật cung cấp việc triển khai các phương pháp hay nhất về bảo mật liên quan đến việc đọc và ghi dữ liệu tĩnh, cũng như việc tạo và xác minh khoá.
Thư viện sử dụng mẫu trình tạo để cung cấp chế độ cài đặt mặc định an toàn cho các mức bảo mật sau:
- Mức bảo mật mạnh cân bằng giữa phương thức mã hoá hiệu quả và hiệu suất cao. Cấp độ bảo mật này phù hợp với các ứng dụng dành cho người dùng thông thường, chẳng hạn như các ứng dụng ngân hàng và trò chuyện, cũng như các ứng dụng doanh nghiệp để thực hiện quy trình kiểm tra việc thu hồi chứng chỉ.
- Mức bảo mật tối đa. Cấp độ bảo mật này phù hợp với các ứng dụng yêu cầu kho khoá dựa trên phần cứng và sự hiện diện của người dùng để cung cấp quyền truy cập khoá.
Hướng dẫn này trình bày cách làm việc với các cấu hình bảo mật đề xuất của thư viện Bảo mật, cũng như cách đọc và ghi dữ liệu đã mã hoá được lưu trữ trong các tệp và các lựa chọn ưu tiên dùng chung.
Quản lý khoá
Thư viện Bảo mật sử dụng hệ thống gồm 2 phần để quản lý khoá:
-
Một tập hợp khoá chứa một hoặc nhiều khoá để mã hoá một tệp hoặc dữ liệu về các lựa chọn ưu tiên dùng chung. Tập hợp khoá sẽ được lưu trữ trong
SharedPreferences
. -
Khoá chính (
master
) mã hoá tất cả các bộ khoá. Khoá này được lưu trữ bằng hệ thống kho khoá của Android.
Các lớp có trong thư viện
Thư viện bảo mật chứa các lớp sau đây để cung cấp thêm dữ liệu tĩnh an toàn:
EncryptedFile
-
Cung cấp các biện pháp triển khai tuỳ chỉnh của
FileInputStream
vàFileOutputStream
, giúp cho các ứng dụng của bạn được an toàn hơn trong việc truyền trực tuyến các thao tác đọc và ghi.Để cung cấp các thao tác đọc và ghi an toàn từ luồng truyền tệp (file streams), Thư viện bảo mật sử dụng phương thức gốc Mã hoá truyền trực tuyến đã xác thực với dữ liệu liên kết (AEAD). Tìm hiểu thêm về phương thức gốc này trong tài liệu về thư viện Tink trên GitHub.
EncryptedSharedPreferences
-
Gói lớp
SharedPreferences
và tự động mã hoá các khoá và giá trị bằng phương thức hai lược đồ:- Khoá được mã hoá bằng một thuật toán mã hoá xác định để khoá có thể được mã hoá và tra cứu đúng cách.
- Giá trị được mã hoá bằng AES-256 GCM và là giá trị không xác định.
Các phần sau đây cho biết cách sử dụng các lớp này để thực hiện các thao tác phổ biến với tệp và tuỳ chọn chung.
Đưa thư viện vào dự án của bạn
Để sử dụng thư viện Bảo mật, hãy thêm các phần phụ thuộc sau vào tệp build.gradle
của mô-đun ứng dụng nếu thích hợp:
Groovy
dependencies { implementation "androidx.security:security-crypto:1.0.0" // For Identity Credential APIs implementation "androidx.security:security-identity-credential:1.0.0-alpha03" // For App Authentication APIs implementation "androidx.security:security-app-authenticator:1.0.0-alpha02" // For App Authentication API testing androidTestImplementation "androidx.security:security-app-authenticator:1.0.0-alpha01" }
Kotlin
dependencies { implementation("androidx.security:security-crypto:1.0.0") // For Identity Credential APIs implementation("androidx.security:security-identity-credential:1.0.0-alpha03") // For App Authentication APIs implementation("androidx.security:security-app-authenticator:1.0.0-alpha02") // For App Authentication API testing androidTestImplementation("androidx.security:security-app-authenticator:1.0.0-alpha01") }
Đọc tệp
Đoạn mã sau đây minh hoạ cách dùng EncryptedFile
để đọc nội dung của tệp:
Kotlin
// Although you can define your own key generation parameter specification, it's // recommended that you use the value specified here. val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC val mainKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec) val fileToRead = "my_sensitive_data.txt" val encryptedFile = EncryptedFile.Builder( File(DIRECTORY, fileToRead), applicationContext, mainKeyAlias, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build() val inputStream = encryptedFile.openFileInput() val byteArrayOutputStream = ByteArrayOutputStream() var nextByte: Int = inputStream.read() while (nextByte != -1) { byteArrayOutputStream.write(nextByte) nextByte = inputStream.read() } val plaintext: ByteArray = byteArrayOutputStream.toByteArray()
Java
Context context = getApplicationContext(); // Although you can define your own key generation parameter specification, it's // recommended that you use the value specified here. KeyGenParameterSpec keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC; String mainKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec); String fileToRead = "my_sensitive_data.txt"; EncryptedFile encryptedFile = new EncryptedFile.Builder( new File(DIRECTORY, fileToRead), context, mainKeyAlias, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build(); InputStream inputStream = encryptedFile.openFileInput(); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); int nextByte = inputStream.read(); while (nextByte != -1) { byteArrayOutputStream.write(nextByte); nextByte = inputStream.read(); } byte[] plaintext = byteArrayOutputStream.toByteArray();
Ghi tệp
Đoạn mã sau đây minh hoạ cách dùng EncryptedFile
để ghi nội dung của tệp:
Kotlin
// Although you can define your own key generation parameter specification, it's // recommended that you use the value specified here. val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC val mainKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec) // Create a file with this name or replace an entire existing file // that has the same name. Note that you cannot append to an existing file, // and the filename cannot contain path separators. val fileToWrite = "my_sensitive_data.txt" val encryptedFile = EncryptedFile.Builder( File(DIRECTORY, fileToWrite), applicationContext, mainKeyAlias, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build() val fileContent = "MY SUPER-SECRET INFORMATION" .toByteArray(StandardCharsets.UTF_8) encryptedFile.openFileOutput().apply { write(fileContent) flush() close() }
Java
Context context = getApplicationContext(); // Although you can define your own key generation parameter specification, it's // recommended that you use the value specified here. KeyGenParameterSpec keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC; String mainKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec); // Create a file with this name or replace an entire existing file // that has the same name. Note that you cannot append to an existing file, // and the filename cannot contain path separators. String fileToWrite = "my_sensitive_data.txt"; EncryptedFile encryptedFile = new EncryptedFile.Builder( new File(DIRECTORY, fileToWrite), context, mainKeyAlias, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build(); byte[] fileContent = "MY SUPER-SECRET INFORMATION" .getBytes(StandardCharsets.UTF_8); OutputStream outputStream = encryptedFile.openFileOutput(); outputStream.write(fileContent); outputStream.flush(); outputStream.close();
Với trường hợp sử dụng yêu cầu tăng cường mức bảo mật, hãy hoàn thành các bước sau:
- Tạo đối tượng
KeyGenParameterSpec.Builder
, chuyểntrue
vàosetUserAuthenticationRequired()
và một giá trị lớn hơn 0 làm đối số đầu tiên củasetUserAuthenticationParameters()
. Nhắc người dùng nhập thông tin xác thực bằng
createConfirmDeviceCredentialIntent()
. Tìm hiểu thêm về cách yêu cầu việc xác thực người dùng để sử dụng khoá.Ghi đè
onActivityResult()
để nhận lệnh gọi lại thông tin xác thực đã xác nhận.
Chỉnh sửa các lựa chọn ưu tiên dùng chung
Đoạn mã sau đây minh hoạ cách dùng EncryptedSharedPreferences
để chỉnh sửa tập hợp các lựa chọn ưu tiên dùng chung của người dùng:
Kotlin
val sharedPrefsFile: String = FILE_NAME val sharedPreferences: SharedPreferences = EncryptedSharedPreferences.create( sharedPrefsFile, mainKeyAlias, applicationContext, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) with (sharedPreferences.edit()) { // Edit the user's shared preferences... apply() }
Java
String sharedPrefsFile = FILE_NAME; SharedPreferences sharedPreferences = EncryptedSharedPreferences.create( sharedPrefsFile, mainKeyAlias, getApplicationContext(), EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ); SharedPreferences.Editor sharedPrefsEditor = sharedPreferences.edit(); // Edit the user's shared preferences... sharedPrefsEditor.apply();
Hỗ trợ các thiết bị chạy Android 5.0 và Android 5.1
Phiên bản 1.1.0 của thư viện Bảo mật cho phép bạn hỗ trợ các thiết bị chạy Android 5.0 (API cấp 21) trở lên. Trên Android 5.0 và Android 5.1 (API cấp 22), bạn không thể dùng kho khoá Android để lưu trữ các bộ khoá.
Đọc tệp
Đoạn mã sau đây minh hoạ cách dùng EncryptedFile
để đọc nội dung của tệp bằng phiên bản 1.1.0 của thư viện Bảo mật:
Kotlin
val mainKey = MasterKey.Builder(applicationContext) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build() val fileToRead = "my_sensitive_data.txt" val encryptedFile = EncryptedFile.Builder(applicationContext, File(DIRECTORY, fileToRead), mainKey, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build() val inputStream = encryptedFile.openFileInput() val byteArrayOutputStream = ByteArrayOutputStream() var nextByte: Int = inputStream.read() while (nextByte != -1) { byteArrayOutputStream.write(nextByte) nextByte = inputStream.read() } val plaintext: ByteArray = byteArrayOutputStream.toByteArray()
Java
Context context = getApplicationContext(); MasterKey mainKey = new MasterKey.Builder(context) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build(); String fileToRead = "my_sensitive_data.txt"; EncryptedFile encryptedFile = new EncryptedFile.Builder(context, new File(DIRECTORY, fileToRead), mainKey, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build(); InputStream inputStream = encryptedFile.openFileInput(); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); int nextByte = inputStream.read(); while (nextByte != -1) { byteArrayOutputStream.write(nextByte); nextByte = inputStream.read(); } byte[] plaintext = byteArrayOutputStream.toByteArray();
Ghi tệp
Đoạn mã sau đây minh hoạ cách dùng EncryptedFile
để ghi nội dung của tệp bằng thư viện Bảo mật phiên bản 1.1.0:
Kotlin
val mainKey = MasterKey.Builder(applicationContext) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build() // Creates a file with this name, or replaces an existing file // that has the same name. Note that the file name cannot contain // path separators. val fileToWrite = File(DIRECTORY, "my_sensitive_data.txt") val encryptedFile = EncryptedFile.Builder(applicationContext, fileToWrite, mainKey, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build() // File cannot exist before using openFileOutput if (fileToWrite.exists()) { fileToWrite.delete() } val fileContent = "MY SUPER-SECRET INFORMATION" .toByteArray(StandardCharsets.UTF_8)) encryptedFile.openFileOutput().apply { write(fileContent) flush() close() }
Java
Context context = getApplicationContext(); MasterKey mainKey = new MasterKey.Builder(context) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build(); // Creates a file with this name, or replaces an existing file // that has the same name. Note that the file name cannot contain // path separators. File fileToWrite = new File(DIRECTORY, "my_sensitive_data.txt"); EncryptedFile encryptedFile = new EncryptedFile.Builder(context, fileToWrite, mainKey, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build(); // File cannot exist before using openFileOutput if (fileToWrite.exists()) { fileToWrite.delete(); } byte[] fileContent = "MY SUPER-SECRET INFORMATION" .getBytes(StandardCharsets.UTF_8); OutputStream outputStream = encryptedFile.openFileOutput(); outputStream.write(fileContent); outputStream.flush(); outputStream.close();
Chỉnh sửa các lựa chọn ưu tiên dùng chung
Đoạn mã sau đây minh hoạ cách dùng EncryptedSharedPreferences
để chỉnh sửa tập hợp các lựa chọn ưu tiên dùng chung của người dùng bằng thư viện Bảo mật phiên bản 1.1.0:
Kotlin
val context = applicationContext val mainKey = MasterKey.Builder(applicationContext) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build() val sharedPreferences = EncryptedSharedPreferences.create( applicationContext, FILE_NAME, mainKey, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) with (sharedPreferences.edit()) { // Edit the user's shared preferences... apply() }
Java
Context context = getApplicationContext(); MasterKey mainKey = new MasterKey.Builder(context) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build(); SharedPreferences sharedPreferences = EncryptedSharedPreferences .create( context, FILE_NAME, mainKey, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ); SharedPreferences.Editor sharedPrefsEditor = sharedPreferences.edit(); // Edit the user's shared preferences... sharedPrefsEditor.apply();