Key Verifier cho Android cung cấp một cách thức hợp nhất và an toàn để người dùng xác minh rằng họ đang giao tiếp với đúng người trong ứng dụng được mã hoá hai đầu (E2EE) của bạn. Dịch vụ này bảo vệ người dùng khỏi các cuộc tấn công trung gian bằng cách cho phép họ xác nhận tính xác thực của khoá mã hoá công khai của một người liên hệ thông qua một giao diện người dùng hệ thống nhất quán và đáng tin cậy.
Tính năng này do Trình xác minh khoá cung cấp. Đây là một dịch vụ hệ thống thuộc Dịch vụ hệ thống của Google và được phân phối thông qua Cửa hàng Play. Đây là một kho lưu trữ khoá công khai E2EE tập trung trên thiết bị.
Lý do bạn nên tích hợp với Key Verifier
- Mang đến trải nghiệm người dùng hợp nhất: Thay vì tự xây dựng quy trình xác minh, bạn có thể chạy giao diện người dùng tiêu chuẩn của hệ thống, mang đến cho người dùng trải nghiệm nhất quán và đáng tin cậy trên tất cả các ứng dụng của họ.
- Tăng mức độ tin tưởng của người dùng: Trạng thái xác minh rõ ràng do hệ thống hỗ trợ đảm bảo với người dùng rằng các cuộc trò chuyện của họ đều an toàn và riêng tư.
- Giảm chi phí phát triển: Chuyển sự phức tạp của giao diện người dùng xác minh khoá, bộ nhớ và hoạt động quản lý trạng thái sang dịch vụ hệ thống.
Từ khóa
- lookupKey: Giá trị nhận dạng không công khai, cố định cho một người liên hệ, được lưu trữ trong cột LOOKUP_KEY của trình cung cấp danh bạ. Không giống như
contact ID
,lookupKey
vẫn ổn định ngay cả khi thông tin liên hệ cơ bản bị thay đổi hoặc hợp nhất, khiến đây là cách được đề xuất để tham chiếu một người liên hệ. - accountId: Giá trị nhận dạng dành riêng cho ứng dụng cho tài khoản của người dùng trên một thiết bị. Mã nhận dạng này do ứng dụng của bạn xác định và giúp phân biệt giữa nhiều tài khoản mà một người dùng có thể có. Thông tin này sẽ xuất hiện với người dùng trong giao diện người dùng. Bạn nên sử dụng thông tin có ý nghĩa như số điện thoại, địa chỉ email hoặc tên người dùng
- deviceId: Giá trị nhận dạng duy nhất cho một thiết bị cụ thể được liên kết với tài khoản của người dùng. Điều này cho phép người dùng có nhiều thiết bị, mỗi thiết bị có một bộ khoá mã hoá riêng. Không nhất thiết phải đại diện cho một thiết bị thực, nhưng có thể là một cách để phân biệt giữa nhiều khoá được dùng cho cùng một tài khoản
Bắt đầu
Trước khi bắt đầu, hãy thiết lập ứng dụng để giao tiếp với dịch vụ KeyVerifier.
Khai báo quyền: Trong AndroidManifest.xml, hãy khai báo các quyền sau. Bạn cũng phải yêu cầu người dùng cấp các quyền này trong thời gian chạy.
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
Lấy thực thể ứng dụng: Lấy một thực thể của ContactKeys
, đây là điểm truy cập vào API.
import com.google.android.gms.contactkeys.ContactKeys
val contactKeyClient = ContactKeys.getClient(context)
Hướng dẫn dành cho nhà phát triển ứng dụng nhắn tin
Là một nhà phát triển ứng dụng nhắn tin, vai trò chính của bạn là xuất bản khoá công khai của người dùng và khoá của người liên hệ của họ cho dịch vụ Key Verifier.
Xuất bản khoá công khai của người dùng
Để cho phép người khác tìm và xác minh người dùng của bạn, hãy xuất bản khoá công khai của họ vào kho lưu trữ trên thiết bị. Để tăng cường bảo mật, hãy cân nhắc việc tạo khoá trong Kho khoá Android.
import com.google.android.gms.contactkeys.ContactKeyClient
import com.google.android.gms.tasks.Tasks
suspend fun publishSelfKey(
contactKeyClient: ContactKeyClient,
accountId: String,
deviceId: String,
publicKey: ByteArray
) {
try {
Tasks.await(
contactKeyClient.updateOrInsertE2eeSelfKey(
deviceId,
accountId,
publicKey
)
)
// Self key published successfully.
} catch (e: Exception) {
// Handle error.
}
}
Liên kết khoá công khai với người liên hệ
Khi ứng dụng của bạn nhận được khoá công khai cho một trong các số liên hệ của người dùng, bạn phải lưu trữ khoá đó và liên kết với số liên hệ đó trong kho lưu trữ trung tâm. Nhờ đó, khoá có thể được xác minh và các ứng dụng khác có thể hiển thị trạng thái xác minh cho người liên hệ. Để làm việc này, bạn cần có lookupKey của người liên hệ từ Trình cung cấp danh bạ Android. Điều này thường xảy ra khi tìm nạp khoá từ máy chủ phân phối khoá hoặc trong quá trình đồng bộ hoá định kỳ các khoá cục bộ.
import com.google.android.gms.contactkeys.ContactKeyClient
import com.google.android.gms.tasks.Tasks
suspend fun storeContactKey(
contactKeyClient: ContactKeyClient,
contactLookupKey: String,
contactAccountId: String,
contactDeviceId: String,
contactPublicKey: ByteArray
) {
try {
Tasks.await(
contactKeyClient.updateOrInsertE2eeContactKey(
contactLookupKey,
contactDeviceId,
contactAccountId,
contactPublicKey
)
)
// Contact's key stored successfully.
} catch (e: Exception) {
// Handle error.
}
}
Truy xuất khoá và trạng thái xác minh
Sau khi bạn xuất bản khoá, người dùng có thể xác minh khoá đó thông qua tính năng quét mã QR trực tiếp. Giao diện người dùng của ứng dụng phải phản ánh việc một cuộc trò chuyện có đang sử dụng khoá đã xác minh hay không. Mỗi khoá đều có một trạng thái xác minh mà bạn có thể dùng để thông báo cho giao diện người dùng.
Tìm hiểu về các trạng thái xác minh:
UNVERIFIED
: Đây là trạng thái mặc định cho mọi khoá mới. Điều này có nghĩa là khoá tồn tại nhưng người dùng chưa xác nhận tính xác thực của khoá. Trong giao diện người dùng, bạn nên coi đây là trạng thái trung lập và thường không hiển thị chỉ báo đặc biệt nào.VERIFIED
: Trạng thái này cho biết mức độ tin cậy cao. Điều này có nghĩa là người dùng đã hoàn tất thành công một quy trình xác minh (chẳng hạn như quét mã QR) và xác nhận rằng khoá thuộc về người liên hệ dự kiến. Trong giao diện người dùng, bạn nên hiển thị một chỉ báo rõ ràng, tích cực, chẳng hạn như dấu kiểm màu xanh lục hoặc biểu tượng khiên.VERIFICATION_FAILED
: Đây là trạng thái cảnh báo. Điều này có nghĩa là khoá được liên kết với người liên hệ không khớp với khoá đã được xác minh trước đó. Điều này có thể xảy ra nếu một người liên hệ có thiết bị mới, nhưng cũng có thể cho thấy nguy cơ bảo mật tiềm ẩn. Trong giao diện người dùng, hãy cảnh báo người dùng bằng một cảnh báo nổi bật và đề xuất họ xác minh lại trước khi gửi thông tin nhạy cảm.
Bạn có thể truy xuất trạng thái tổng hợp cho tất cả các khoá được liên kết với một người liên hệ. Bạn nên sử dụng VerificationState.leastVerifiedFrom()
để giải quyết trạng thái khi có nhiều khoá, vì khoá này sẽ ưu tiên VERIFICATION_FAILED
hơn VERIFIED
một cách chính xác.
- Nhận trạng thái tổng hợp ở cấp người liên hệ
import com.google.android.gms.contactkeys.ContactKeyClient
import com.google.android.gms.contactkeys.constants.VerificationState
import com.google.android.gms.tasks.Tasks
suspend fun displayContactVerificationStatus(
contactKeyClient: ContactKeyClient,
contactLookupKey: String
) {
try {
val keysResult = Tasks.await(contactKeyClient.getAllE2eeContactKeys(contactLookupKey))
val states =
keysResult.keys.map { VerificationState.fromState(it.localVerificationState) }
val contactStatus = VerificationState.leastVerifiedFrom(states)
updateUi(contactLookupKey, contactStatus)
} catch (e: Exception) {
// Handle error.
}
}
- Nhận trạng thái tổng hợp ở cấp tài khoản
import com.google.android.gms.contactkeys.ContactKeyClient
import com.google.android.gms.contactkeys.constants.VerificationState
import com.google.android.gms.tasks.Tasks
suspend fun displayAccountVerificationStatus(
contactKeyClient: ContactKeyClient,
accountId: String
) {
try {
val keys = Tasks.await(contactKeyClient.getE2eeAccountKeysForAccount(accountId))
val states = keys.map { VerificationState.fromState(it.localVerificationState) }
val accountStatus = VerificationState.leastVerifiedFrom(states)
updateUi(accountId, accountStatus)
} catch (e: Exception) {
// Handle error.
}
}
Theo dõi những thay đổi chính theo thời gian thực
Để xác minh giao diện người dùng của ứng dụng luôn cho thấy trạng thái tin cậy chính xác, bạn nên theo dõi các bản cập nhật. Bạn nên sử dụng API dựa trên luồng. API này sẽ phát ra một danh sách khoá mới bất cứ khi nào một khoá cho tài khoản đã đăng ký được thêm, xoá hoặc thay đổi trạng thái xác minh. Điều này đặc biệt hữu ích khi bạn muốn danh sách thành viên của một cuộc trò chuyện nhóm luôn được cập nhật. Trạng thái xác minh của một khoá có thể thay đổi khi:
- Người dùng hoàn tất thành công quy trình xác minh (ví dụ: quét mã QR).
- Khoá của một người liên hệ bị sửa đổi, khiến khoá đó không còn khớp với giá trị đã xác minh trước đó.
fun observeKeyUpdates(contactKeyClient: ContactKeyClient, accountIds: List<String>) {
lifecycleScope.launch {
contactKeyClient.getAccountContactKeysFlow(accountIds)
.collect { updatedKeys ->
// A key was added, removed, or updated.
// Refresh your app's UI and internal state.
refreshUi(updatedKeys)
}
}
}
Thực hiện quy trình xác minh khoá trực tiếp
Cách an toàn nhất để người dùng xác minh khoá là thông qua quy trình xác minh trực tiếp, thường là bằng cách quét mã QR hoặc so sánh một chuỗi số. Ứng dụng Key Verifier cung cấp các quy trình chuẩn trên giao diện người dùng cho quy trình này mà ứng dụng của bạn có thể khởi chạy. Sau một lần xác minh, API sẽ tự động cập nhật trạng thái xác minh của khoá và ứng dụng của bạn sẽ nhận được thông báo nếu bạn đang theo dõi các bản cập nhật khoá.
- Bắt đầu quy trình xác minh khoá cho một người liên hệ do người dùng chọn
Khởi chạy
PendingIntent
dogetScanQrCodeIntent
cung cấp bằng cách sử dụnglookupKey
của người liên hệ đã chọn. Giao diện người dùng cho phép người dùng xác minh tất cả các khoá cho một người liên hệ nhất định.
import android.app.ActivityOptions
import android.app.PendingIntent
import com.google.android.gms.contactkeys.ContactKeyClient
import com.google.android.gms.tasks.Tasks
suspend fun initiateVerification(contactKeyClient: ContactKeyClient, lookupKey: String) {
try {
val pendingIntent = Tasks.await(contactKeyClient.getScanQrCodeIntent(lookupKey))
val options =
ActivityOptions.makeBasic()
.setPendingIntentBackgroundActivityStartMode(
ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
)
.toBundle()
pendingIntent.send(options)
} catch (e: Exception) {
// Handle error.
}
}
- Bắt đầu quy trình xác minh khoá cho một tài khoản do người dùng chọn
Nếu người dùng muốn xác minh một tài khoản không được liên kết trực tiếp với một người liên hệ (hoặc một tài khoản cụ thể của một người liên hệ), bạn có thể khởi chạy
PendingIntent
dogetScanQrCodeIntentForAccount
cung cấp. Thông thường, bạn sẽ dùng tên gói và mã tài khoản của ứng dụng riêng.
import android.app.ActivityOptions
import android.app.PendingIntent
import com.google.android.gms.contactkeys.ContactKeyClient
import com.google.android.gms.tasks.Tasks
suspend fun initiateVerification(contactKeyClient: ContactKeyClient, packageName: String, accountId: String) {
try {
val pendingIntent = Tasks.await(contactKeyClient.getScanQrCodeIntentForAccount(packageName, accountId))
// Allow activity start from background on Android SDK34+
val options =
ActivityOptions.makeBasic()
.setPendingIntentBackgroundActivityStartMode(
ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
)
.toBundle()
pendingIntent.send(options)
} catch (e: Exception) {
// Handle error.
}
}