Hình ảnh hệ điều hành Android sử dụng chữ ký mã hoá ở 2 nơi:
- Mỗi tệp
.apk
bên trong hình ảnh phải được ký. Trình quản lý gói của Android sử dụng chữ ký.apk
theo hai cách:- Khi được thay thế, ứng dụng phải được ký bằng cùng một khoá với ứng dụng cũ để có quyền truy cập vào dữ liệu của ứng dụng cũ. Điều này đúng cả khi cập nhật ứng dụng của người dùng bằng cách ghi đè
.apk
và khi ghi đè ứng dụng hệ thống bằng phiên bản mới hơn được cài đặt trong/data
. - Nếu hai hoặc nhiều ứng dụng muốn chia sẻ một mã nhận dạng người dùng (để chúng có thể chia sẻ) dữ liệu, v.v.), các dữ liệu này phải được ký bằng cùng một khoá.
- Khi được thay thế, ứng dụng phải được ký bằng cùng một khoá với ứng dụng cũ để có quyền truy cập vào dữ liệu của ứng dụng cũ. Điều này đúng cả khi cập nhật ứng dụng của người dùng bằng cách ghi đè
- Gói cập nhật OTA phải được ký bằng một trong các khoá mà hệ thống hoặc quá trình cài đặt sẽ từ chối quảng cáo.
Phím nhả
Cây Android bao gồm test-keys trong build/target/product/security
. Việc tạo hình ảnh hệ điều hành Android bằng make
sẽ ký tất cả tệp .apk
bằng khoá kiểm thử. Vì khoá kiểm thử được công khai, nên bất kỳ ai cũng có thể ký tệp .apk của riêng mình bằng cùng một khoá. Điều này có thể cho phép họ thay thế hoặc xâm nhập vào các ứng dụng hệ thống được tích hợp vào hình ảnh hệ điều hành của bạn. Vì lý do này, bạn cần phải ký mọi hình ảnh hệ điều hành Android được phát hành công khai hoặc triển khai bằng một bộ khoá phát hành đặc biệt mà chỉ bạn mới có quyền truy cập.
Để tạo một tập hợp khoá phát hành riêng biệt, hãy chạy các lệnh sau từ thư mục gốc của cây Android:
subject='/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
mkdir ~/.android-certs
for x in releasekey platform shared media networkstack; do \ ./development/tools/make_key ~/.android-certs/$x "$subject"; \ done
Bạn nên thay đổi $subject
để phản ánh thông tin của tổ chức. Bạn có thể sử dụng bất kỳ thư mục nào, nhưng hãy cẩn thận khi chọn một
sao lưu và an toàn. Một số nhà cung cấp chọn mã hoá
khoá riêng tư của họ bằng một cụm mật khẩu mạnh và lưu trữ khoá đã mã hoá
trong kiểm soát nguồn; những người khác lưu trữ toàn bộ khoá phát hành của họ ở một nơi khác,
chẳng hạn như trên một chiếc máy tính ngăn cách không khí.
Để tạo hình ảnh bản phát hành, hãy sử dụng:
make dist
sign_target_files_apks \ -o \ # explained in the next section --default_key_mappings ~/.android-certs out/dist/*-target_files-*.zip \ signed-target_files.zip
Tập lệnh sign_target_files_apks
lấy các tệp đích
.zip
làm đầu vào và tạo một tệp mục tiêu mới .zip
trong
tất cả tệp .apk
đã được ký bằng khoá mới. Bạn có thể tìm thấy các hình ảnh mới ký trong IMAGES/
trong signed-target_files.zip
.
Ký gói OTA
Bạn có thể chuyển đổi tệp zip mục tiêu đã ký thành tệp zip cập nhật OTA đã ký bằng cách sử dụng quy trình sau:
ota_from_target_files \
-k (--package_key)
signed-target_files.zip \
signed-ota_update.zip
Chữ ký và cài đặt không qua cửa hàng ứng dụng
Tính năng tải không qua cửa hàng không bỏ qua cơ chế xác minh chữ ký gói thông thường của tính năng khôi phục. Trước khi cài đặt một gói, tính năng khôi phục sẽ xác minh rằng gói đó được ký bằng một trong các khoá riêng tư khớp với khoá công khai được lưu trữ trong phân vùng khôi phục, giống như đối với một gói được phân phối qua mạng không dây.
Các gói cập nhật nhận được từ hệ thống chính thường được xác minh hai lần: một lần bởi hệ thống chính, sử dụng phương thức RecoverySystem.verifyPackage()
trong API Android, sau đó xác minh lại bằng cách khôi phục. API RecoverySystem kiểm tra chữ ký dựa trên khoá công khai được lưu trữ trong hệ thống chính, trong tệp /system/etc/security/otacerts.zip
(theo mặc định). Quá trình khôi phục sẽ kiểm tra chữ ký dựa trên các khoá công khai được lưu trữ trong ổ RAM của phân vùng khôi phục, trong tệp /res/keys
.
Theo mặc định, các tệp mục tiêu .zip
do bản dựng tạo ra sẽ đặt giá trị
Chứng chỉ OTA để khớp với khoá kiểm tra. Trên hình ảnh đã phát hành, bạn phải sử dụng một chứng chỉ khác để các thiết bị có thể xác minh tính xác thực của gói cập nhật. Chuyển cờ -o
đến
sign_target_files_apks
, như được hiển thị trong phần trước, thay thế
chứng chỉ khoá kiểm tra có chứng chỉ khoá phát hành từ các chứng chỉ của bạn
thư mục.
Thông thường, hình ảnh hệ thống và hình ảnh khôi phục lưu trữ cùng một nhóm OTA khoá công khai. Bằng cách thêm một khoá vào chỉ tập hợp khoá khôi phục, bạn có thể ký các gói chỉ có thể cài đặt thông qua tính năng cài đặt không qua cửa hàng (giả sử cơ chế tải bản cập nhật xuống của hệ thống chính đang xác minh chính xác với otacerts.zip). Bạn có thể chỉ định các khoá bổ sung chỉ được đưa vào quá trình khôi phục bằng cách đặt biến PRODUCT_EXTRA_RECOVERY_KEYS trong định nghĩa sản phẩm:
vendor/yoyodyne/tardis/products/tardis.mk
[...] PRODUCT_EXTRA_RECOVERY_KEYS := vendor/yoyodyne/security/tardis/sideload
Tệp này bao gồm khoá công khai vendor/yoyodyne/security/tardis/sideload.x509.pem
trong tệp khoá khôi phục để có thể cài đặt các gói được ký bằng khoá đó. Tuy nhiên, khoá bổ sung không có trong otacerts.zip, vì vậy, các hệ thống xác minh chính xác các gói đã tải xuống sẽ không gọi tính năng khôi phục cho các gói được ký bằng khoá này.
Chứng chỉ và khoá riêng tư
Mỗi khoá có hai tệp: chứng chỉ, trong đó có tiện ích mở rộng .x509.pem và khoá riêng tư (có đuôi tệp là .pk8). Bạn phải giữ bí mật khoá riêng tư và cần khoá này để ký gói. Khoá có thể được bảo vệ bằng mật khẩu. Ngược lại, chứng chỉ chỉ chứa một nửa khoá công khai, vì vậy, chứng chỉ có thể được phân phối rộng rãi. Dùng để xác minh một gói đã được ký bằng khoá riêng tương ứng.
Bản dựng Android tiêu chuẩn dùng 5 khoá, tất cả đều nằm trong
build/target/product/security
:
- testkey
- Khoá mặc định chung cho các gói không chỉ định khoá.
- nền tảng
- Kiểm thử khoá cho các gói là một phần của nền tảng cốt lõi.
- đã chia sẻ
- Kiểm tra chìa khoá cho những nội dung được chia sẻ trong quy trình liên hệ tại nhà/danh bạ.
- truyền-thông
- Khoá kiểm thử cho các gói thuộc hệ thống nội dung nghe nhìn/hệ thống tải xuống.
Các gói riêng lẻ chỉ định một trong các khoá này bằng cách đặt LOCAL_CERTIFICATE trong tệp Android.mk. (khoá kiểm thử sẽ được dùng nếu biến này chưa được đặt.) Bạn cũng có thể chỉ định một khoá hoàn toàn khác theo tên đường dẫn, ví dụ:
device/yoyodyne/apps/SpecialApp/Android.mk
[...] LOCAL_CERTIFICATE := device/yoyodyne/security/special
Hiện bản dựng này sử dụng khoá device/yoyodyne/security/special.{x509.pem,pk8}
để ký SpecialApp.apk. Bản dựng chỉ có thể sử dụng các khoá riêng tư
không được bảo vệ bằng mật khẩu.
Tuỳ chọn ký nâng cao
Thay thế khoá ký APK
Tập lệnh ký sign_target_files_apks
hoạt động trên mục tiêu
tệp được tạo cho một bản dựng. Tất cả thông tin về chứng chỉ và khoá riêng tư được sử dụng tại thời điểm tạo bản dựng đều có trong các tệp mục tiêu. Khi chạy tập lệnh ký để ký phát hành, bạn có thể thay thế khoá ký dựa trên tên khoá hoặc tên APK.
Sử dụng --key_mapping
và --default_key_mappings
cờ để chỉ định việc thay thế khoá dựa trên tên khoá:
- Cờ
--key_mapping src_key=dest_key
chỉ định việc thay thế cho một khoá tại một thời điểm. - Cờ
--default_key_mappings dir
chỉ định một có 5 khoá để thay thế tất cả các khoá trongbuild/target/product/security
; thì tương đương với việc sử dụng--key_mapping
5 lần để chỉ định mối liên kết.
build/target/product/security/testkey = dir/releasekey build/target/product/security/platform = dir/platform build/target/product/security/shared = dir/shared build/target/product/security/media = dir/media build/target/product/security/networkstack = dir/networkstack
Sử dụng cờ --extra_apks apk_name1,apk_name2,...=key
để chỉ định các khoá ký thay thế dựa trên tên APK. Nếu
key
bị để trống, tập lệnh sẽ xử lý các APK được chỉ định
dưới dạng được ký trước.
Đối với sản phẩm tardis giả định, bạn cần 6 khoá được bảo vệ bằng mật khẩu: 5 khoá để thay thế 5 khoá trong build/target/product/security
và 1 khoá để thay thế khoá bổ sung device/yoyodyne/security/special
mà SpecialApp yêu cầu trong ví dụ trên. Nếu các khoá nằm trong các trường hợp sau
tệp:
vendor/yoyodyne/security/tardis/releasekey.x509.pem vendor/yoyodyne/security/tardis/releasekey.pk8 vendor/yoyodyne/security/tardis/platform.x509.pem vendor/yoyodyne/security/tardis/platform.pk8 vendor/yoyodyne/security/tardis/shared.x509.pem vendor/yoyodyne/security/tardis/shared.pk8 vendor/yoyodyne/security/tardis/media.x509.pem vendor/yoyodyne/security/tardis/media.pk8 vendor/yoyodyne/security/tardis/networkstack.x509.pem vendor/yoyodyne/security/tardis/networkstack.pk8 vendor/yoyodyne/security/special.x509.pem vendor/yoyodyne/security/special.pk8 # NOT password protected vendor/yoyodyne/security/special-release.x509.pem vendor/yoyodyne/security/special-release.pk8 # password protected
Sau đó, bạn sẽ ký tất cả các ứng dụng như sau:
./build/make/tools/releasetools/sign_target_files_apks \
--default_key_mappings vendor/yoyodyne/security/tardis \
--key_mapping vendor/yoyodyne/security/special=vendor/yoyodyne/security/special-release \
--extra_apks PresignedApp= \
-o tardis-target_files.zip \
signed-tardis-target_files.zip
Thao tác này sẽ hiển thị:
Enter password for vendor/yoyodyne/security/special-release key> Enter password for vendor/yoyodyne/security/tardis/networkstack key> Enter password for vendor/yoyodyne/security/tardis/media key> Enter password for vendor/yoyodyne/security/tardis/platform key> Enter password for vendor/yoyodyne/security/tardis/releasekey key> Enter password for vendor/yoyodyne/security/tardis/shared key> signing: Phone.apk (vendor/yoyodyne/security/tardis/platform) signing: Camera.apk (vendor/yoyodyne/security/tardis/media) signing: NetworkStack.apk (vendor/yoyodyne/security/tardis/networkstack) signing: Special.apk (vendor/yoyodyne/security/special-release) signing: Email.apk (vendor/yoyodyne/security/tardis/releasekey) [...] signing: ContactsProvider.apk (vendor/yoyodyne/security/tardis/shared) signing: Launcher.apk (vendor/yoyodyne/security/tardis/shared) NOT signing: PresignedApp.apk (skipped due to special cert string) rewriting SYSTEM/build.prop: replace: ro.build.description=tardis-user Eclair ERC91 15449 test-keys with: ro.build.description=tardis-user Eclair ERC91 15449 release-keys replace: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/test-keys with: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/release-keys signing: framework-res.apk (vendor/yoyodyne/security/tardis/platform) rewriting RECOVERY/RAMDISK/default.prop: replace: ro.build.description=tardis-user Eclair ERC91 15449 test-keys with: ro.build.description=tardis-user Eclair ERC91 15449 release-keys replace: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/test-keys with: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/release-keys using: vendor/yoyodyne/security/tardis/releasekey.x509.pem for OTA package verification done.
Sau khi nhắc người dùng nhập mật khẩu cho tất cả các khoá được bảo vệ bằng mật khẩu,
tập lệnh sẽ ký lại tất cả tệp APK trong mục tiêu đầu vào .zip
bằng
phím giải phóng. Trước khi chạy lệnh, bạn cũng có thể đặt biến môi trường ANDROID_PW_FILE
thành tên tệp tạm thời; sau đó, tập lệnh sẽ gọi trình chỉnh sửa để cho phép bạn nhập mật khẩu cho tất cả các khoá (đây có thể là cách nhập mật khẩu thuận tiện hơn).
Thay thế khoá ký APEX
Android 10 ra mắt Định dạng tệp APEX để cài đặt các mô-đun hệ thống cấp thấp hơn. Như được giải thích trong Ký APEX, mỗi tệp APEX được ký bằng hai khoá: một cho hình ảnh hệ thống tệp nhỏ trong một APEX và khác cho toàn bộ APEX.
Khi ký để phát hành, hai khoá ký cho tệp APEX sẽ được thay thế bằng khoá phát hành. Khoá tải trọng hệ thống tệp được chỉ định bằng cờ --extra_apex_payload
và toàn bộ khoá ký tệp APEX được chỉ định bằng cờ --extra_apks
.
Đối với sản phẩm tardis, giả sử bạn có cấu hình khoá sau đây cho các tệp APEX com.android.conscrypt.apex
, com.android.media.apex
và com.android.runtime.release.apex
.
name="com.android.conscrypt.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED" name="com.android.media.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED" name="com.android.runtime.release.apex" public_key="vendor/yoyodyne/security/testkeys/com.android.runtime.avbpubkey" private_key="vendor/yoyodyne/security/testkeys/com.android.runtime.pem" container_certificate="vendor/yoyodyne/security/testkeys/com.google.android.runtime.release_container.x509.pem" container_private_key="vendor/yoyodyne/security/testkeys/com.google.android.runtime.release_container.pk8"
Và bạn có các tệp sau đây chứa khoá phát hành:
vendor/yoyodyne/security/runtime_apex_container.x509.pem vendor/yoyodyne/security/runtime_apex_container.pk8 vendor/yoyodyne/security/runtime_apex_payload.pem
Lệnh sau đây ghi đè các khoá ký cho
com.android.runtime.release.apex
và
com.android.tzdata.apex
trong quá trình ký phát hành. Cụ thể,
com.android.runtime.release.apex
được ký bằng
khoá phát hành (runtime_apex_container
cho tệp APEX, và
runtime_apex_payload
cho tải trọng hình ảnh của tệp).
com.android.tzdata.apex
được coi là đã ký trước. Tất cả tệp APEX khác đều được xử lý theo cấu hình mặc định như được liệt kê trong tệp mục tiêu.
./build/make/tools/releasetools/sign_target_files_apks \
--default_key_mappings vendor/yoyodyne/security/tardis \
--extra_apks com.android.runtime.release.apex=vendor/yoyodyne/security/runtime_apex_container \
--extra_apex_payload_key com.android.runtime.release.apex=vendor/yoyodyne/security/runtime_apex_payload.pem \
--extra_apks com.android.media.apex= \
--extra_apex_payload_key com.android.media.apex= \
-o tardis-target_files.zip \
signed-tardis-target_files.zip
Việc chạy lệnh trên cung cấp các nhật ký sau:
[...] signing: com.android.runtime.release.apex container (vendor/yoyodyne/security/runtime_apex_container) : com.android.runtime.release.apex payload (vendor/yoyodyne/security/runtime_apex_payload.pem) NOT signing: com.android.conscrypt.apex (skipped due to special cert string) NOT signing: com.android.media.apex (skipped due to special cert string) [...]
Tùy chọn khác
Tập lệnh ký sign_target_files_apks
sẽ viết lại bản dựng
trong các tệp thuộc tính bản dựng để phản ánh rằng
là một bản dựng đã ký. Cờ --tag_changes
kiểm soát nội dung chỉnh sửa
được tạo đối với vân tay. Chạy tập lệnh bằng -h
để xem tài liệu về tất cả cờ.
Tạo khoá theo cách thủ công
Android sử dụng khoá RSA 2048 bit với số mũ công khai 3. Bạn có thể tạo cặp khoá riêng tư/chứng chỉ bằng công cụ openssl từ openssl.org:
# generate RSA keyopenssl genrsa -3 -out temp.pem 2048
Generating RSA private key, 2048 bit long modulus ....+++ .....................+++ e is 3 (0x3) # create a certificate with the public part of the keyopenssl req -new -x509 -key temp.pem -out releasekey.x509.pem -days 10000 -subj '/C=US/ST=California/L=San Narciso/O=Yoyodyne, Inc./OU=Yoyodyne Mobility/CN=Yoyodyne/emailAddress=yoyodyne@example.com'
# create a PKCS#8-formatted version of the private keyopenssl pkcs8 -in temp.pem -topk8 -outform DER -out releasekey.pk8 -nocrypt
# securely delete the temp.pem fileshred --remove temp.pem
Lệnh openssl pkcs8 nêu trên sẽ tạo một tệp .pk8 chứa no
mật khẩu, thích hợp để sử dụng với hệ thống xây dựng. Để tạo tệp .pk8 được bảo mật bằng mật khẩu (bạn nên làm điều này cho tất cả các khoá phát hành thực tế), hãy thay thế đối số -nocrypt
bằng -passout stdin
; sau đó, openssl sẽ mã hoá khoá riêng tư bằng mật khẩu đọc được từ dữ liệu đầu vào chuẩn. Không
câu lệnh sẽ được in, vì vậy nếu stdin là thiết bị đầu cuối thì chương trình sẽ treo
khi thực sự chỉ chờ bạn nhập mật khẩu. Bạn có thể sử dụng các giá trị khác cho đối số the-passout để đọc mật khẩu từ các vị trí khác; để biết thông tin chi tiết, hãy xem tài liệu về openssl.
Tệp trung gian temp.pem chứa khoá riêng tư mà không có bất kỳ loại bảo vệ mật khẩu nào, vì vậy, hãy xử lý tệp này một cách thận trọng khi tạo khoá phát hành. Cụ thể, tiện ích GNUshred có thể không hiệu quả trên mạng hoặc hệ thống tệp nhật ký. Bạn có thể dùng một thư mục đang hoạt động nằm trong ổ đĩa RAM (chẳng hạn như phân vùng tmpfs) khi tạo khoá để đảm bảo trung gian không vô tình bị hiển thị.
Tạo tệp hình ảnh
Khi có signed-target_files.zip
, bạn cần tạo hình ảnh để có thể đưa hình ảnh đó vào thiết bị.
Để tạo hình ảnh đã ký từ các tệp mục tiêu, hãy chạy lệnh sau từ thư mục gốc của cây Android:
img_from_target_files signed-target_files.zip signed-img.zip
signed-img.zip
chứa tất cả các tệp .img
.
Để tải hình ảnh vào thiết bị, hãy sử dụng tính năng khởi động nhanh làm
sau:
fastboot update signed-img.zip