Ký bản dựng để phát hành

Hình ảnh hệ điều hành Android sử dụng chữ ký mã hoá ở 2 nơi:

  1. 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á.
  2. 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.
ngăn xếp mạng
Khoá kiểm thử cho các gói thuộc hệ thống mạng. Khoá networkstack được dùng để ký các tệp nhị phân được thiết kế dưới dạng Thành phần hệ thống mô-đun. Nếu bản cập nhật mô-đun được tạo riêng biệt và tích hợp dưới dạng bản dựng trước trong hình ảnh thiết bị, thì bạn có thể không cần tạo khoá ngăn xếp mạng trong cây nguồn Android.

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--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á trong build/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.apexcom.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.apexcom.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 key
openssl 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 key
openssl 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 key
openssl pkcs8 -in temp.pem -topk8 -outform DER -out releasekey.pk8 -nocrypt

# securely delete the temp.pem file
shred --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
Tệ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 tính năng khởi động nhanh làm sau:
fastboot update signed-img.zip