Hình ảnh hệ điều hành Android sử dụng chữ ký mật mã ở hai nơi:
- Mỗi
.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 một ứng dụng được thay thế, nó phải được ký bằng khóa giống như ứ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à 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ẻ ID người dùng (để chúng có thể chia sẻ dữ liệu, v.v.), chúng phải được ký bằng cùng một khóa.
- Khi một ứng dụng được thay thế, nó phải được ký bằng khóa giống như ứ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 đè
- Các gói cập nhật OTA phải được ký bằng một trong các khóa mà hệ thống mong đợi, nếu không quá trình cài đặt sẽ từ chối chúng.
Phím phát hành
Cây Android bao gồm các khóa kiểm tra trong bản build/target/product/security
. Tạo hình ảnh hệ điều hành Android bằng make
sẽ ký tất cả các .apk
bằng các phím kiểm tra. Vì các khóa kiểm tra được biết đến công khai, nên bất kỳ ai cũng có thể ký các tệp .apk của riêng họ bằng các khóa giống nhau, điều này có thể cho phép họ thay thế hoặc chiếm quyền điều khiển các ứng dụng hệ thống được tích hợp trong hình ảnh hệ điều hành của bạn. Vì lý do này, điều quan trọng là phải ký bất kỳ hình ảnh hệ điều hành Android được phát hành hoặc triển khai công khai nào bằng một bộ khóa phát hành đặc biệt mà chỉ bạn mới có quyền truy cập.
Để tạo bộ khóa phát hành duy nhất của riêng bạn, hãy chạy các lệnh sau từ gốc của cây Android của bạn:
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
$subject
phải được thay đổi để phản ánh thông tin của tổ chức của bạn. Bạn có thể sử dụng bất kỳ thư mục nào, nhưng hãy cẩn thận chọn một vị trí được sao lưu và bảo mật. Một số nhà cung cấp chọn mã hóa khóa cá nhân của họ bằng cụm mật khẩu mạnh và lưu trữ khóa được mã hóa trong kiểm soát nguồn; những người khác lưu trữ các khóa phát hành của họ ở một nơi khác hoàn toàn, chẳng hạn như trên một máy tính có ga.
Để tạo hình ảnh 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 tệp đích .zip
làm đầu vào và tạo ra tệp đích .zip
mới, trong đó tất cả .apk
đã được ký bằng các khóa mới. Các hình ảnh mới được ký có thể được tìm thấy trong IMAGES/
in signed-target_files.zip
.
Ký các gói OTA
Có thể chuyển đổi zip tệp đích-tệp đã ký thành tệp zip cập nhật OTA đã ký bằng quy trình sau:
ota_from_target_files \
-k (--package_key)
signed-target_files.zip \
signed-ota_update.zip
Chữ ký và sideloading
Sideloading không bỏ qua cơ chế xác minh chữ ký gói thông thường của khôi phục — trước khi cài đặt gói, khôi phục sẽ xác minh rằng gói được ký bằng một trong các khóa riêng phù hợp với khóa công khai được lưu trữ trong phân vùng khôi phục, giống như đối với gói được phân phối qua -không khí.
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 và sau đó một lần nữa bằng cách khôi phục. API RecoverySystem kiểm tra chữ ký dựa trên các khóa 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). Khôi phục kiểm tra chữ ký đối với các khóa công khai được lưu trữ trong đĩa RAM của phân vùng khôi phục, trong tệp /res/keys
.
Theo mặc định, tệp đích .zip
do bản dựng tạo ra sẽ đặt chứng chỉ OTA để khớp với khóa kiểm tra. Trên hình ảnh đã phát hành, một chứng chỉ khác phải được sử dụng để 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
cho sign_target_files_apks
, như được hiển thị trong phần trước, sẽ thay thế chứng chỉ khóa kiểm tra bằng chứng chỉ khóa phát hành từ thư mục certs của bạn.
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 bộ khóa công khai OTA. Bằng cách thêm khóa vào chỉ bộ khóa khôi phục, bạn có thể ký các gói chỉ có thể được cài đặt thông qua sideloading (giả sử cơ chế tải xuống bản cập nhật của hệ thống chính đang thực hiện xác minh chính xác đối với otacerts.zip). Bạn có thể chỉ định các khóa phụ chỉ được đưa vào khôi phục bằng cách đặt biến PRODUCT_EXTRA_RECOVERY_KEYS trong định nghĩa sản phẩm của mình:
vendor/yoyodyne/tardis/products/tardis.mk
[...] PRODUCT_EXTRA_RECOVERY_KEYS := vendor/yoyodyne/security/tardis/sideload
Điều này bao gồm nhà cung cấp khóa công khai vendor/yoyodyne/security/tardis/sideload.x509.pem
trong tệp khóa khôi phục để nó có thể cài đặt các gói đã ký với nó. Tuy nhiên, khóa bổ sung không được bao gồm 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 khôi phục cho các gói được ký bằng khóa này.
Chứng chỉ và khóa cá nhân
Mỗi khóa có hai tệp: chứng chỉ có phần mở rộng là .x509.pem và khóa riêng tư có phần mở rộng là .pk8. Khóa riêng tư nên được giữ bí mật và cần thiết để ký một gói. Bản thân khóa 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 công khai của khóa, vì vậy nó có thể được phân phối rộng rãi. Nó được sử dụng để xác minh một gói đã được ký bằng khóa cá nhân tương ứng.
Bản dựng Android tiêu chuẩn sử dụng năm khóa, tất cả đều nằm trong bản build/target/product/security
:
- khóa kiểm tra
- Khóa mặc định chung cho các gói không chỉ định khóa khác.
- nền tảng
- Khóa kiểm tra cho các gói là một phần của nền tảng cốt lõi.
- đã chia sẻ
- Khóa kiểm tra những thứ được chia sẻ trong quá trình gia đình / danh bạ.
- phương tiện truyền thông
- Khóa kiểm tra cho các gói là một phần của hệ thống tải xuống / phương tiện.
Các gói riêng lẻ chỉ định một trong các khóa này bằng cách đặt LOCAL_CERTIFICATE trong tệp Android.mk của chúng. (khóa kiểm tra được sử dụng nếu biến này không được đặt.) Bạn cũng có thể chỉ định một khóa 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
Giờ đây, bản dựng sử dụng khóa device/yoyodyne/security/special.{x509.pem,pk8}
để ký SpecialApp.apk. Bản dựng chỉ có thể sử dụng các khóa riêng tư không được bảo vệ bằng mật khẩu.
Tùy chọn ký nâng cao
Thay thế khóa ký APK
Tập lệnh ký sign_target_files_apks
hoạt động trên các tệp đích được tạo cho một bản dựng. Tất cả thông tin về chứng chỉ và khóa cá nhân được sử dụng tại thời điểm xây dựng được bao gồm trong các tệp đích. Khi chạy tập lệnh ký để ký phát hành, khóa ký có thể được thay thế dựa trên tên khóa hoặc tên APK.
Sử dụng cờ --key_mapping
và --default_key_mappings
để chỉ định thay thế khóa dựa trên tên khóa:
-
--key_mapping src_key = dest_key
chỉ định thay thế cho một khóa tại một thời điểm. -
--default_key_mappings dir
chỉ định một thư mục có năm khóa để thay thế tất cả các khóa trongbuild/target/product/security
; nó tương đương với việc sử dụng--key_mapping
năm lần để chỉ định các ánh xạ.
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 --extra_apks apk_name1,apk_name2,... = key
để chỉ định thay thế khóa ký dựa trên tên APK. Nếu để trống key
, tập lệnh sẽ coi các APK được chỉ định là được ký trước.
Đối với sản phẩm tardis giả định, bạn cần sáu khóa được bảo vệ bằng mật khẩu: năm khóa để thay thế năm khóa trong bản build/target/product/security
và một khóa để thay thế device/yoyodyne/security/special
theo yêu cầu của SpecialApp trong ví dụ trên. Nếu các khóa nằm trong các tệp sau:
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ư thế này:
./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
Điều này dẫn đến những điều sau:
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 khóa được bảo vệ bằng mật khẩu, tập lệnh sẽ ký lại tất cả các tệp APK trong mục tiêu đầu vào .zip
bằng các khóa phát hành. 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 soạn thảo của bạn để cho phép bạn nhập mật khẩu cho tất cả các khóa (đây có thể là một cách thuận tiện hơn để nhập mật khẩu).
Thay thế khóa ký APEX
Android 10 giới thiệu định dạng tệp APEX để cài đặt các mô-đun hệ thống cấp thấp hơn. Như đã giải thích trong ký APEX , mỗi tệp APEX được ký bằng hai khóa: một cho hình ảnh hệ thống tệp nhỏ trong APEX và khóa còn lại cho toàn bộ APEX.
Khi ký phát hành, hai khóa ký cho tệp APEX được thay thế bằng khóa phát hành. Khóa tải của hệ thống tệp được chỉ định bằng cờ --extra_apex_payload
và toàn bộ khóa ký tệp APEX được chỉ định bằng cờ --extra_apks
.
Đối với sản phẩm tardis, giả sử rằng bạn có cấu hình khóa sau cho các tệp com.android.conscrypt.apex
, com.android.media.apex
và com.android.runtime.release.apex
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 chứa khóa 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 sẽ ghi đè các khóa 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 các khóa phát hành được chỉ định ( runtime_apex_container
cho tệp APEX và runtime_apex_payload
cho tải hình ảnh tệp). com.android.tzdata.apex
được coi là đã ký trước. Tất cả các tệp APEX khác được xử lý bởi cấu hình mặc định như được liệt kê trong các tệp đích.
./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
Chạy lệnh trên sẽ cho các bản ghi 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) [...]
Sự lựa chọn khác
Tập lệnh ký sign_target_files_apks
ghi lại mô tả bản dựng và tệp tham chiếu trong tệp thuộc tính bản dựng để phản ánh rằng bản dựng đó là bản dựng đã ký. Cờ --tag_changes
kiểm soát những chỉnh sửa nào được thực hiện đối với tệp tham chiếu. Chạy tập lệnh với -h
để xem tài liệu về tất cả các cờ.
Tạo khóa theo cách thủ công
Android sử dụng các khóa RSA 2048-bit với số mũ công khai 3. Bạn có thể tạo các cặp khóa cá nhân / 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 ở trên tạo tệp .pk8 không có mật khẩu, phù hợp để sử dụng với hệ thống xây dựng. Để tạo .pk8 được bảo mật bằng mật khẩu (điều bạn nên làm đối với tất cả các khóa phát hành thực tế), hãy thay thế đối số -nocrypt
bằng -passout stdin
; thì openssl sẽ mã hóa khóa cá nhân bằng mật khẩu được đọc từ đầu vào tiêu chuẩn. Không có lời nhắc nào được in, vì vậy nếu stdin là terminal, chương trình sẽ có vẻ như bị treo khi nó thực sự chỉ chờ bạn nhập mật khẩu. Các giá trị khác có thể được sử dụng cho đối số-passout để đọc mật khẩu từ các vị trí khác; để biết chi tiết, hãy xem tài liệu openssl .
Tệp trung gian temp.pem chứa khóa riêng tư mà không có bất kỳ loại bảo vệ bằng mật khẩu nào, vì vậy hãy loại bỏ nó một cách cẩn thận khi tạo khóa phát hành. Đặc biệt, 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ể sử dụng thư mục làm việc nằm trong đĩa RAM (chẳng hạn như phân vùng tmpfs) khi tạo khóa để đảm bảo các thành phần trung gian không vô tình bị lộ ra ngoài.
Tạo tệp hình ảnh
Khi bạn đã ký-target-files.zip, bạn cần tạo hình ảnh để có thể đưa vào thiết bị. Để tạo hình ảnh đã ký từ các tệp đích, 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.zipTệp kết quả,
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 fastboot như sau:fastboot update signed-img.zip