Lược đồ chữ ký APK phiên bản 4

Android 11 hỗ trợ lược đồ chữ ký tương thích với tính năng truyền trực tuyến bằng lược đồ chữ ký APK v4. Chữ ký v4 dựa trên cây băm Merkle được tính toán trên tất cả các byte của tệp APK. Giá trị này tuân theo cấu trúc của cây băm fs-verity một cách chính xác (ví dụ: thêm số 0 vào phần đệm của muối và thêm số 0 vào khối cuối cùng). Android 11 lưu trữ chữ ký trong một tệp riêng biệt, <apk name>.apk.idsigChữ ký v4 yêu cầu chữ ký bổ sung v2 hoặc v3.

Định dạng tệp

Tất cả các trường số đều ở định dạng little endian. Tất cả các trường đều chiếm đúng số lượng byte như sizeof(), không thêm khoảng đệm hoặc căn chỉnh ngầm ẩn.

Dưới đây là một cấu trúc trình trợ giúp để đơn giản hoá các định nghĩa.

template <class SizeT>
struct sized_bytes {
        SizeT size;
        byte bytes[size];
};

Nội dung tệp chính:

struct V4Signature {
        int32 version; // only version 2 is supported as of now
        sized_bytes<int32> hashing_info;
        sized_bytes<int32> signing_info;
        sized_bytes<int32> merkle_tree;  // optional
};

hashing_info là các tham số dùng để tạo cây băm + hàm băm gốc:

struct hashing_info.bytes {
    int32 hash_algorithm;    // only 1 == SHA256 supported
    int8 log2_blocksize;     // only 12 (block size 4096) supported now
    sized_bytes<int32> salt; // used exactly as in fs-verity, 32 bytes max
    sized_bytes<int32> raw_root_hash; // salted digest of the first Merkle tree page
};

signing_info là cấu trúc sau:

struct signing_info.bytes {
    sized_bytes<int32> apk_digest;  // used to match with the corresponding APK
    sized_bytes<int32> x509_certificate; // ASN.1 DER form
    sized_bytes<int32> additional_data; // a free-form binary data blob
    sized_bytes<int32> public_key; // ASN.1 DER, must match the x509_certificate
    int32 signature_algorithm_id; // see the APK v2 doc for the list
    sized_bytes<int32> signature;
};
  • apk_digest được lấy từ khối ký v3 của APK hoặc nếu không có thì lấy từ khối v2 (xem apk_digest)

Để tạo và xác minh mã signature, bạn phải chuyển đổi tuần tự dữ liệu sau đây thành blob nhị phân và truyền dữ liệu đó vào thuật toán ký / xác minh dưới dạng dữ liệu đã ký:

struct V4DataForSigning {
        int32 size;
        int64 file_size; // the size of the file that's been hashed.
        hashing_info.hash_algorithm;
        hashing_info.log2_blocksize;
        hashing_info.salt;
        hashing_info.raw_root_hash;
        signing_info.apk_digest;
        signing_info.x509_certificate;
        signing_info.additional_data;
};
  1. merkle_treetoàn bộ cây Merkle của tệp APK, được tính toán như mô tả trong tài liệu fs-verity.

Nhà sản xuất và người tiêu dùng

Công cụ SDK Android apksigner hiện tạo tệp chữ ký v4 nếu bạn chạy công cụ này bằng các thông số mặc định. Bạn có thể tắt tính năng ký v4 theo cách tương tự như các lược đồ ký khác. Phương thức này cũng có thể xác minh xem chữ ký v4 có hợp lệ hay không.

adb dự kiến tệp .apk.idsig sẽ nằm bên cạnh tệp .apk khi chạy lệnh adb install --incremental
. Tệp này cũng sẽ sử dụng tệp .idsig để thử cài đặt gia tăng theo mặc định và sẽ quay lại cài đặt thông thường nếu tệp này bị thiếu hoặc không hợp lệ.

Khi một phiên cài đặt được tạo, API cài đặt trực tuyến mới trong PackageInstaller sẽ chấp nhận chữ ký v4 đã loại bỏ dưới dạng một đối số riêng biệt khi thêm tệp vào phiên. Tại thời điểm này, signing_info được truyền vào incfs dưới dạng một blob toàn bộ. Incfs trích xuất hàm băm gốc từ blob.

Khi phiên cài đặt đang được thực hiện, PackageManagerService sẽ thực hiện một ioctl để truy xuất blob signing_info từ incfs, phân tích cú pháp và xác minh chữ ký.

Thành phần Trình tải dữ liệu gia tăng dự kiến sẽ truyền phần cây Merkle của chữ ký thông qua API gốc của trình tải dữ liệu.
package lệnh shell dịch vụ install-incremental chấp nhận tệp chữ ký v4 đã loại bỏ được mã hoá dưới dạng base64 làm tham số cho mỗi tệp đã thêm. Bạn phải gửi cây Merkle tương ứng vào stdin của lệnh.

apk_digest

apk_digest là bản tóm tắt nội dung đầu tiên có sẵn theo thứ tự:

  1. V3, khối 1 MB, SHA2-512 (CONTENT_DIGEST_CHUNKED_SHA512),
  2. V3, khối 4 KB, SHA2-256 (CONTENT_DIGEST_VERITY_CHUNKED_SHA256),
  3. V3, khối 1 MB, SHA2-256 (CONTENT_DIGEST_CHUNKED_SHA256),
  4. V2, SHA2-512,
  5. Phiên bản 2, SHA2-256.

Xem trình tự có tiền tố độ dài của chữ ký có tiền tố độ dài trong lược đồ chữ ký APK phiên bản 3.

quy trình xác thực tệp apk phiên bản 4
Hình 1: Quy trình xác thực APK phiên bản 4

Xác thực và kiểm thử

Xác thực quá trình triển khai bằng cách sử dụng Kiểm thử đơn vị tính năng và CTS.

  • CtsIncrementalInstallHostTestCases
    • /android/cts/hostsidetests/incrementalinstall

Kiểm thử định dạng chữ ký

Để kiểm thử định dạng chữ ký, hãy thiết lập môi trường phát triển và chạy các kiểm thử thủ công sau:

$ atest PackageManagerShellCommandTest
PackageManagerShellCommandIncrementalTest

Kiểm thử định dạng chữ ký bằng SDK Android (ADB và apksigner)

Để kiểm thử định dạng chữ ký bằng SDK Android, hãy thiết lập môi trường phát triển và đảm bảo bạn đã hoàn tất việc triển khai IncFS. Sau đó, hãy cài đặt ROM cho bản dựng trên một trình mô phỏng hoặc thiết bị thực tế mục tiêu. Bạn cần tạo hoặc lấy một tệp APK hiện có, sau đó tạo một khoá ký gỡ lỗi. Cuối cùng, hãy ký và cài đặt tệp APK có định dạng chữ ký v4 từ thư mục công cụ xây dựng.

$ ./apksigner sign --ks debug.keystore game.apk

Cài đặt

$ ./adb install game.apk

Tôi có thể tìm thấy các bài kiểm thử này ở đâu?

/android/cts/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java