apksigner

Công cụ apksigner, có trong bản sửa đổi 24.0.3 trở lên của Công cụ bản dựng SDK Android, cho phép bạn ký các tệp APK và xác nhận rằng chữ ký của APK sẽ được xác minh thành công trên tất cả các phiên bản của thiết bị Android mà APK đó hỗ trợ.

Trang này trình bày hướng dẫn ngắn gọn về cách sử dụng công cụ này và đóng vai trò là tài liệu tham khảo cho các tuỳ chọn dòng lệnh khác nhau mà công cụ hỗ trợ. Để xem nội dung mô tả đầy đủ hơn về cách dùng công cụ apksigner để ký tệp APK, vui lòng xem bài viết Ký ứng dụng.

Chú ý: Nếu bạn ký APK bằng apksigner và thực hiện các thay đổi khác đối với APK thì chữ ký của APK này sẽ mất hiệu lực. Do đó, bạn phải sử dụng các công cụ như zipalign trước khi ký APK.

Mức sử dụng

Ký APK

Cú pháp để ký một tệp APK bằng công cụ apksigner như sau:

apksigner sign --ks keystore.jks |
  --key key.pk8 --cert cert.x509.pem
  [signer_options] app-name.apk

Khi ký APK bằng công cụ apksigner, bạn phải cung cấp chứng chỉ và khoá riêng tư của trình ký. Bạn có thể cung cấp thông tin này theo 2 cách:

  • Chỉ định một tệp KeyStore bằng cách sử dụng tuỳ chọn --ks.
  • Hãy xác định riêng tệp khoá riêng tư và tệp chứng chỉ bằng cách sử dụng lần lượt các tuỳ chọn --key--cert. Tệp khoá riêng tư phải sử dụng định dạng PKCS #8 và tệp chứng chỉ phải sử dụng định dạng X.509.

Thông thường, bạn chỉ ký một APK bằng một trình ký. Nếu bạn cần ký một APK bằng nhiều trình ký, hãy sử dụng tuỳ chọn --next-signer để phân tách nhóm các tuỳ chọn chung áp dụng cho từng trình ký:

apksigner sign [signer_1_options] --next-signer [signer_2_options] app-name.apk

Xác minh chữ ký của APK

Cú pháp xác nhận quy trình xác minh thành công đối với chữ ký của APK trên các nền tảng được hỗ trợ như sau:

apksigner verify [options] app-name.apk

Xoay vòng khoá ký

Cú pháp để xoay loạt chứng chỉ ký nối tiếp hoặc một chuỗi chữ ký mới như sau:

$ apksigner rotate --in /path/to/existing/lineage \
  --out /path/to/new/file \
  --old-signer --ks old-signer-jks \
  --new-signer --ks new-signer-jks

Tuỳ chọn

Các danh sách sau đây bao gồm tập hợp các tuỳ chọn cho mỗi lệnh mà công cụ apksigner này hỗ trợ.

Lệnh ký

Lệnh ký apksigner có các tuỳ chọn sau.

Tuỳ chọn chung

Sau đây là một số lựa chọn cài đặt cơ bản áp dụng cho một chữ ký:

--out <apk-filename>
Vị trí bạn muốn lưu APK đã ký. Nếu tuỳ chọn này không được cung cấp rõ ràng, thì gói APK sẽ được ký tại chỗ và ghi đè lên tệp APK đầu vào.
--min-sdk-version <integer>
Cấp độ API thấp nhất dành cho khung Android mà apksigner sử dụng để xác nhận rằng chữ ký của APK sẽ được xác minh. Giá trị cao hơn cho phép công cụ sử dụng các tham số có khả năng bảo mật cao hơn khi ký ứng dụng nhưng cũng sẽ hạn chế khả năng hiển thị của APK tới các thiết bị đang chạy thêm các phiên bản hiện tại của Android. Theo mặc định, apksigner sử dụng giá trị của minSdkVersion thuộc tính từ tệp kê khai của ứng dụng.
--max-sdk-version <integer>
Cấp độ API thấp nhất dành cho khung Android mà apksigner sử dụng để xác nhận rằng chữ ký của APK sẽ được xác mình. Theo mặc định, công cụ này sử dụng cấp độ API cao nhất có thể.
--rotation-min-sdk-version <integer>
Cấp độ API thấp nhất mà khoá ký xoay vòng của APK phải sử dụng để tạo chữ ký của APK. Khoá ký ban đầu (chưa xoay vòng) cho APK sẽ được dùng cho tất cả các phiên bản trước của nền tảng. Theo mặc định, các khoá ký xoay vòng (được hỗ trợ trên các thiết bị chạy Android 13 (API cấp 33) trở lên) sẽ được sử dụng cùng với khối ký phiên bản 3.1.

Lưu ý: Nếu ứng dụng đã được ký bằng khoá ký xoay vòng trên thiết bị chạy Android 12L (API cấp 32) trở xuống, thì bạn phải dùng --rotation-min-sdk-version 28 để tiếp tục ký ứng dụng bằng khoá ký xoay vòng cho Android 9 (API cấp 28).

--v1-signing-enabled <true | false>
Xác định xem apksigner có ký gói APK đã cho bằng giao thức ký truyền thống dựa trên JAR hay không. Theo mặc định, công cụ này sử dụng các giá trị của --min-sdk-version--max-sdk-version để quyết định thời điểm áp dụng lược đồ chữ ký này.
--v2-signing-enabled <true | false>
Xác định xem apksigner có ký gói APK đã cho hay không bằng cách sử dụng Giao thức ký APK v2. Theo mặc định, công cụ này sử dụng các giá trị của --min-sdk-version--max-sdk-version để xác định thời điểm áp giao thức ký này.
--v3-signing-enabled <true | false>
Xác định xem apksigner có dùng Giao thức ký APK v3 để ký gói APK đã cho hay không. Theo mặc định, công cụ này sử dụng các giá trị của --min-sdk-version--max-sdk-version để xác định thời điểm áp giao thức ký này.
--v4-signing-enabled <true | false | only>

Xác định xem apksigner có dùng Giao thức ký APK v4 để ký gói APK đã cho hay không Giao thức này tạo ra chữ ký trong một tệp riêng biệt (apk-name.apk.idsig). Nếu true và APK chưa được ký thì chữ ký v2 hoặc v3 sẽ được tạo dựa trên các giá trị của --min-sdk-version--max-sdk-version. Sau đó, lệnh này sẽ tạo tệp .idsig dựa trên nội dung của APK đã ký.

Chỉ sử dụng only để tạo chữ ký v4 mà không cần chỉnh sửa APK và mọi chữ ký có trước khi gọi. only sẽ lỗi nếu APK chưa có chữ ký v2 hoặc v3, hoặc nếu chữ ký đã sử dụng khoá khác với khoá đã cung cấp cho lệnh gọi hiện tại.

Theo mặc định, công cụ này sử dụng các giá trị của --min-sdk-version--max-sdk-version để xác định thời điểm áp dụng giao thức ký này.

-v, --verbose
Sử dụng chế độ dữ liệu đầu ra chi tiết.

Tuỳ chọn đối với mỗi chữ ký

Các tuỳ chọn sau đây xác định cấu hình cho một chữ ký cụ thể. Các tuỳ chọn này không cần thiết nếu bạn chỉ ký ứng dụng bằng một trình ký duy nhất.

--next-signer <signer-options>
Dùng để xác định các tuỳ chọn chung cho từng trình ký.
--v1-signer-name <basename>
Tên gốc cho các tệp bao gồm chữ ký dựa trên JAR dành cho trình ký hiện tại. Theo mặc định, apksigner sử dụng bí danh khoá cho kho khoá hoặc basename của tệp khoá cho chữ ký này.

Tuỳ chọn đối với khoá và chứng chỉ

Các tuỳ chọn sau đây xác định khoá riêng tư và chứng chỉ của chữ ký:

--ks <filename>
Khoá riêng tư và chuỗi chứng chỉ của chữ ký có trong tệp kho khoá dựa trên Java đã cung cấp. Nếu tên tệp được đặt thành "NONE" thì kho khoá chứa khoá và chứng chỉ sẽ không cần tệp được chỉ định, tệp này chỉ cần thiết trong trường hợp của một số kho khoá PKCS #11.
--ks-key-alias <alias>
Tên của bí danh đại diện cho dữ liệu khoá riêng tư và chứng chỉ của chữ ký trong KeyStore. Nếu KeyStore liên kết với ký hiệu có chứa nhiều khoá thì bạn phải xác định rõ tuỳ chọn này.
--ks-pass <input-format>

Mật khẩu cho KeyStore chứa khoá riêng tư và chứng chỉ của chữ ký. Bạn phải cung cấp mật khẩu để mở KeyStore. Công cụ apksigner hỗ trợ các định dạng sau:

  • pass:<password> – Mật khẩu được cung cấp khớp với phần còn lại của lệnh apksigner sign.
  • env:<name> – Mật khẩu được lưu trữ dưới dạng biến môi trường được cung cấp.
  • file:<filename> – Mật khẩu được lưu trữ dưới dạng một dòng trong tệp được cung cấp.
  • stdin – Mật khẩu được cung cấp dưới dạng một dòng trong luồng dữ liệu nhập tiêu chuẩn. Đây là hành vi mặc định cho --ks-pass.

Lưu ý: Nếu bạn đặt nhiều mật khẩu trong cùng một tệp, hãy đặt các mật khẩu đó tại các dòng riêng biệt. Công cụ apksigner liên kết mật khẩu với các trình ký của APK dựa trên thứ tự mà bạn chỉ định cho trình ký. Nếu bạn đã cung cấp hai mật khẩu cho một trình ký, thì apksigner sẽ hiểu mật khẩu đầu tiên là mật khẩu KeyStore và mật khẩu thứ hai là mật khẩu khoá.

--pass-encoding <charset>
Bao gồm chế độ mã hoá ký tự được chỉ định, chẳng hạn như ibm437 hoặc utf-8, khi cố gắng xử lý các mật khẩu có chứa ký tự không phải là ASCII.

Keytool thường mã hoá các kho khoá bằng cách chuyển đổi mật khẩu bằng bộ ký tự mặc định của bảng điều khiển. Theo mặc định, apksigner sẽ cố giải mã thông qua một vài dạng mật khẩu:

  • Dạng Unicode
  • Dạng được mã hoá bằng bộ ký tự JVM mặc định
  • Trên Java 8 trở xuống, dạng được mã hoá bằng bộ ký tự mặc định của bảng điều khiển
  • Trên Java 9, apksigner không thể phát hiện bộ ký tự của bảng điều khiển. Vì vậy, bạn có thể cần chỉ định --pass-encoding khi sử dụng mật khẩu không phải ASCII. Bạn cũng có thể cần xác định tuỳ chọn này bằng các KeyStore mà keytool được tạo trên một hệ điều hành khác hoặc ở một ngôn ngữ khác.

    --key-pass <input-format>

    Mật khẩu cho khoá riêng tư của trình ký, cần thiết trong trường hợp khoá riêng tư được bảo vệ bằng mật khẩu. Công cụ apksigner hỗ trợ các định dạng sau:

    • pass:<password> – Mật khẩu được cung cấp khớp với phần còn lại của lệnh apksigner sign.
    • env:<name> – Mật khẩu được lưu trữ dưới dạng biến môi trường được cung cấp.
    • file:<filename> – Mật khẩu được lưu trữ dưới dạng một dòng trong tệp được cung cấp.
    • stdin – Mật khẩu được cung cấp dưới dạng một dòng trong luồng dữ liệu nhập tiêu chuẩn. Đây là hành vi mặc định cho --key-pass.
    --ks-type <algorithm>
    Loại hoặc thuật toán liên kết với KeyStore có chứa khoá riêng tư và chứng chỉ của trình ký. Theo mặc định, apksigner sử dụng loại được xác định là hằng số keystore.type trong tệp thuộc tính bảo mật.
    --ks-provider-name <name>
    Tên của Nhà cung cấp JCA để sử dụng khi yêu cầu triển khai KeyStore của chữ ký. Theo mặc định, apksigner sử dụng nhà cung cấp có mức độ ưu tiên cao nhất.
    --ks-provider-class <class-name>
    Tên lớp đủ điều kiện của Nhà cung cấp JCA để sử dụng khi yêu cầu triển khai KeyStore của trình ký. Tuỳ chọn này thay thế cho --ks-provider-name. Theo mặc định, apksigner sử dụng nhà cung cấp được chỉ định với tuỳ chọn --ks-provider-name.
    --ks-provider-arg <value>
    Một giá trị chuỗi cần chuyển vào làm đối số cho hàm khởi tạo của lớp Nhà cung cấp JCA; bản thân lớp này được xác định thông qua tuỳ chọn --ks-provider-class. Theo mặc định, apksigner sử dụng hàm khởi tạo không có đối số của lớp này.
    --key <filename>
    Tên tệp có chứa khoá riêng tư của trình ký. Tệp này phải sử dụng định dạng DER PKCS #8. Trường hợp khoá được bảo vệ bằng mật khẩu thì apksigner sẽ yêu cầu mật khẩu bằng cách sử dụng phương thức nhập tiêu chuẩn, trừ phi bạn chỉ định một loại định dạng nhập khác bằng tuỳ chọn --key-pass.
    --cert <filename>
    Tên của tệp chứa chuỗi chứng chỉ của trình ký. Tệp này phải sử dụng định dạng X.509 PEM hoặc DER.

    Lệnh xác minh

    Lệnh xác minh apksigner có các tuỳ chọn sau.

    --print-certs
    Hiển thị thông tin về chứng chỉ ký của APK.
    --min-sdk-version <integer>
    Cấp độ API thấp nhất dành cho khung Android mà apksigner sử dụng để xác nhận rằng chữ ký của APK sẽ được xác minh. Giá trị cao hơn cho phép công cụ sử dụng các tham số có khả năng bảo mật cao hơn khi ký ứng dụng nhưng cũng sẽ hạn chế khả năng hiển thị của APK tới các thiết bị đang chạy thêm các phiên bản hiện tại của Android. Theo mặc định, apksigner sử dụng giá trị của minSdkVersion thuộc tính từ tệp kê khai của ứng dụng.
    --max-sdk-version <integer>
    Cấp độ API thấp nhất dành cho khung Android mà apksigner sử dụng để xác nhận rằng chữ ký của APK sẽ được xác mình. Theo mặc định, công cụ này sử dụng cấp độ API cao nhất có thể.
    -v, --verbose
    Sử dụng chế độ dữ liệu đầu ra chi tiết.
    -Werr
    Cảnh báo lỗi.

    Ví dụ

    Sau đây là ví dụ về cách sử dụng apksigner.

    Ký tệp APK

    Ký APK bằng cách sử dụng release.jks. Đây là khoá duy nhất trong KeyStore:

    $ apksigner sign --ks release.jks app.apk
    

    Ký APK bằng cách sử dụng một khoá riêng tư và chứng chỉ, được lưu trữ dưới dạng tệp riêng biệt:

    $ apksigner sign --key release.pk8 --cert release.x509.pem app.apk
    

    Ký APK bằng 2 khoá:

    $ apksigner sign --ks first-release-key.jks --next-signer --ks second-release-key.jks app.apk
    

    Ký APK bằng khoá ký xoay vòng và SDK nhắm mục tiêu xoay vòng phiên bản 28 trở lên:

    $ apksigner sign --ks release.jks --next-signer --ks release2.jks \
      --lineage /path/to/signing/history/lineage app.apk \
      --rotation-min-sdk-version 28
    

    Ký APK bằng khoá ký xoay vòng và SDK nhắm mục tiêu xoay vòng phiên bản 33 trở lên:

    $ apksigner sign --ks release.jks --next-signer --ks release2.jks \
      --lineage /path/to/signing/history/lineage app.apk
    

    Xác minh chữ ký của APK

    Kiểm tra xem chữ ký của APK dự kiến được xác nhận có hợp lệ trên tất cả các nền tảng Android mà APK đó hỗ trợ hay không:

    $ apksigner verify app.apk
    

    Kiểm tra xem chữ ký của APK dự kiến sẽ được xác nhận có hợp lệ trên Android 4.0.3 (API cấp 15) trở lên hay không:

    $ apksigner verify --min-sdk-version 15 app.apk
    

    Xoay vòng mã khoá chữ ký

    Bật loạt chứng chỉ ký nối tiếp hỗ trợ xoay vòng khoá:

    $ apksigner rotate --out /path/to/new/file --old-signer \
        --ks release.jks --new-signer --ks release2.jks

    Xoay lại các khoá ký:

    $ apksigner rotate --in /path/to/existing/lineage \
      --out /path/to/new/file --old-signer --ks release2.jks \
      --new-signer --ks release3.jks