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 nhiều tuỳ chọn dòng lệnh 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.
Nếu bạn sử dụng zipalign
để căn chỉnh APK, hãy sử dụng APK này trước khi ký APK.
Cách 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
và--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á chữ 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 trình 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ủaminSdkVersion
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.
--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
và--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
và--max-sdk-version
để xác định thời điểm áp dụng 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
và--max-sdk-version
để xác định thời điểm áp dụng 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ếutrue
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
và--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
và--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.
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).
Tuỳ chọn đối với mỗi trình 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ệnhapksigner 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 2 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 Kho khoá 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ặcutf-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ệnhapksigner 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 Kho khoá 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 Kho khoá của trình 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ủaminSdkVersion
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 Kho khoá:
$ 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 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