版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/

为什么需要使用 release key

test-key 是一个公开的、众所周知的开发测试密钥,广泛用于测试阶段。这意味着任何人都可以获取这个密钥,并用它签署自己修改的 APK 或系统文件。

使用 test-key 签署的系统镜像通常无法通过 Google 的 CTS(兼容性测试套件)认证,Google Play 商店、Google 服务框架等应用可能无法正常运行,某些第三方应用(例如银行应用或数字版权管理应用)也可能拒绝在设备上运行。

OTA 更新包必须使用 Release Key 来签名。签名的更新包经过验证,只有具有相同 Release Key 的设备才能接收和安装更新。

image.png

生成 release key

执行 nano make_keys.sh 创建脚本,内容如下

subject='/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=linchaolong.dev@gmail.com'

# 创建 keys 目录(如果不存在)
mkdir -p keys

for cert in bluetooth cyngn-app media networkstack nfc platform releasekey sdk_sandbox shared testcert testkey verity; do \
    ./development/tools/make_key keys/$cert "$subject"; \
done

通过脚本创建 keys 目录并使用 make_key 命令生成你自己的密钥。

运行脚本生成密钥文件。

# 添加执行权限
chmod +x make_keys.sh
# 运行脚本
./make_keys.sh

为了避免密码解密的复杂性,生成一个未加密的私钥,防止签名过程提示输入密码。

Enter password for 'keys/bluetooth' (blank for none; password will be visible):
creating keys/bluetooth.pk8 with no password



Enter password for 'keys/cyngn-app' (blank for none; password will be visible): 
creating keys/cyngn-app.pk8 with no password

Enter password for 'keys/media' (blank for none; password will be visible):
creating keys/media.pk8 with no password

Enter password for 'keys/networkstack' (blank for none; password will be visible):
creating keys/networkstack.pk8 with no password

Enter password for 'keys/nfc' (blank for none; password will be visible):
creating keys/nfc.pk8 with no password

Enter password for 'keys/platform' (blank for none; password will be visible):
creating keys/platform.pk8 with no password

Enter password for 'keys/releasekey' (blank for none; password will be visible):
creating keys/releasekey.pk8 with no password

Enter password for 'keys/sdk_sandbox' (blank for none; password will be visible):
creating keys/sdk_sandbox.pk8 with no password

Enter password for 'keys/shared' (blank for none; password will be visible):
creating keys/shared.pk8 with no password

Enter password for 'keys/testcert' (blank for none; password will be visible):
creating keys/testcert.pk8 with no password

Enter password for 'keys/testkey' (blank for none; password will be visible):
creating keys/testkey.pk8 with no password

Enter password for 'keys/verity' (blank for none; password will be visible):
creating keys/verity.pk8 with no password

生成的密钥都在 keys 目录下,每条命令会生成两个文件:一个 .x509.pem 公钥证书文件和一个 .pk8 私钥文件:

  • releasekey:主要用于签署系统中的所有 APK 文件,确保这些 APK 来自可信任的来源。

  • platform:签署系统框架和其他核心组件,确保这些组件未被篡改。

  • shared:用于签署需要跨应用共享 UID 的 APK,例如具有相同签名的应用可以共享数据。

  • media:专门用于签署与多媒体相关的 APK 文件。

  • networkstack:用于签署与网络堆栈相关的组件和应用,确保网络功能的安全性。

  • testkey:这是 Android 系统中的默认密钥,主要用于开发和测试环境下的签名,但不应在生产环境中使用。

  • cyngn-priv-app:可能与 CyanogenMod 或 LineageOS 特定的私有应用签名有关。

  • bluetooth:用于签署蓝牙服务或相关的 APK 文件。

  • sdk_sandbox:签署与 SDK 沙箱相关的应用或组件,确保开发环境的安全。

  • verity:用于签署与 Verified Boot 相关的组件,确保设备启动时的安全性。

ls keys

bluetooth.pk8       media.pk8              nfc.pk8            releasekey.pk8        shared.pk8         testkey.pk8
bluetooth.x509.pem  media.x509.pem         nfc.x509.pem       releasekey.x509.pem   shared.x509.pem    testkey.x509.pem
cyngn-app.pk8       networkstack.pk8       platform.pk8       sdk_sandbox.pk8       testcert.pk8       verity.pk8
cyngn-app.x509.pem  networkstack.x509.pem  platform.x509.pem  sdk_sandbox.x509.pem  testcert.x509.pem  verity.x509.pem

生成 target files

# 初始化编译环境
source build/envsetup.sh

# 设置构建目标
breakfast wayne

# 开始编译
mka target-files-package otatools

签名 target files

LineageOS 18.1 及以下版本的签名流程

sign_target_files_apks -o -d keys \
    $OUT/obj/PACKAGING/target_files_intermediates/*-target_files-*.zip \
    signed-target_files.zip

注意:对于早于 18.1 的 LineageOS 版本,您必须在 sign_target_files_apks 命令前添加 ./build/tools/releasetools/

./build/tools/releasetools/sign_target_files_apks -o -d keys \
    $OUT/obj/PACKAGING/target_files_intermediates/*-target_files-*.zip \
    signed-target_files.zip

LineageOS 19.1及以上版本的签名流程

sign_target_files_apks -o -d keys \
    --extra_apks AdServicesApk.apk=keys/releasekey \
    --extra_apks FederatedCompute.apk=keys/releasekey \
    --extra_apks HalfSheetUX.apk=keys/releasekey \
    --extra_apks HealthConnectBackupRestore.apk=keys/releasekey \
    --extra_apks HealthConnectController.apk=keys/releasekey \
    --extra_apks OsuLogin.apk=keys/releasekey \
    --extra_apks SafetyCenterResources.apk=keys/releasekey \
    --extra_apks ServiceConnectivityResources.apk=keys/releasekey \
    --extra_apks ServiceUwbResources.apk=keys/releasekey \
    --extra_apks ServiceWifiResources.apk=keys/releasekey \
    --extra_apks WifiDialog.apk=keys/releasekey \
    --extra_apks com.android.adbd.apex=keys/com.android.adbd \
    --extra_apks com.android.adservices.apex=keys/com.android.adservices \
    --extra_apks com.android.adservices.api.apex=keys/com.android.adservices.api \
    --extra_apks com.android.appsearch.apex=keys/com.android.appsearch \
    --extra_apks com.android.art.apex=keys/com.android.art \
    --extra_apks com.android.bluetooth.apex=keys/com.android.bluetooth \
    --extra_apks com.android.btservices.apex=keys/com.android.btservices \
    --extra_apks com.android.cellbroadcast.apex=keys/com.android.cellbroadcast \
    --extra_apks com.android.compos.apex=keys/com.android.compos \
    --extra_apks com.android.configinfrastructure.apex=keys/com.android.configinfrastructure \
    --extra_apks com.android.connectivity.resources.apex=keys/com.android.connectivity.resources \
    --extra_apks com.android.conscrypt.apex=keys/com.android.conscrypt \
    --extra_apks com.android.devicelock.apex=keys/com.android.devicelock \
    --extra_apks com.android.extservices.apex=keys/com.android.extservices \
    --extra_apks com.android.graphics.pdf.apex=keys/com.android.graphics.pdf \
    --extra_apks com.android.hardware.biometrics.face.virtual.apex=keys/com.android.hardware.biometrics.face.virtual \
    --extra_apks com.android.hardware.biometrics.fingerprint.virtual.apex=keys/com.android.hardware.biometrics.fingerprint.virtual \
    --extra_apks com.android.hardware.boot.apex=keys/com.android.hardware.boot \
    --extra_apks com.android.hardware.cas.apex=keys/com.android.hardware.cas \
    --extra_apks com.android.hardware.wifi.apex=keys/com.android.hardware.wifi \
    --extra_apks com.android.healthfitness.apex=keys/com.android.healthfitness \
    --extra_apks com.android.hotspot2.osulogin.apex=keys/com.android.hotspot2.osulogin \
    --extra_apks com.android.i18n.apex=keys/com.android.i18n \
    --extra_apks com.android.ipsec.apex=keys/com.android.ipsec \
    --extra_apks com.android.media.apex=keys/com.android.media \
    --extra_apks com.android.media.swcodec.apex=keys/com.android.media.swcodec \
    --extra_apks com.android.mediaprovider.apex=keys/com.android.mediaprovider \
    --extra_apks com.android.nearby.halfsheet.apex=keys/com.android.nearby.halfsheet \
    --extra_apks com.android.networkstack.tethering.apex=keys/com.android.networkstack.tethering \
    --extra_apks com.android.neuralnetworks.apex=keys/com.android.neuralnetworks \
    --extra_apks com.android.ondevicepersonalization.apex=keys/com.android.ondevicepersonalization \
    --extra_apks com.android.os.statsd.apex=keys/com.android.os.statsd \
    --extra_apks com.android.permission.apex=keys/com.android.permission \
    --extra_apks com.android.resolv.apex=keys/com.android.resolv \
    --extra_apks com.android.rkpd.apex=keys/com.android.rkpd \
    --extra_apks com.android.runtime.apex=keys/com.android.runtime \
    --extra_apks com.android.safetycenter.resources.apex=keys/com.android.safetycenter.resources \
    --extra_apks com.android.scheduling.apex=keys/com.android.scheduling \
    --extra_apks com.android.sdkext.apex=keys/com.android.sdkext \
    --extra_apks com.android.support.apexer.apex=keys/com.android.support.apexer \
    --extra_apks com.android.telephony.apex=keys/com.android.telephony \
    --extra_apks com.android.telephonymodules.apex=keys/com.android.telephonymodules \
    --extra_apks com.android.tethering.apex=keys/com.android.tethering \
    --extra_apks com.android.tzdata.apex=keys/com.android.tzdata \
    --extra_apks com.android.uwb.apex=keys/com.android.uwb \
    --extra_apks com.android.uwb.resources.apex=keys/com.android.uwb.resources \
    --extra_apks com.android.virt.apex=keys/com.android.virt \
    --extra_apks com.android.vndk.current.apex=keys/com.android.vndk.current \
    --extra_apks com.android.vndk.current.on_vendor.apex=keys/com.android.vndk.current.on_vendor \
    --extra_apks com.android.wifi.apex=keys/com.android.wifi \
    --extra_apks com.android.wifi.dialog.apex=keys/com.android.wifi.dialog \
    --extra_apks com.android.wifi.resources.apex=keys/com.android.wifi.resources \
    --extra_apks com.google.pixel.camera.hal.apex=keys/com.google.pixel.camera.hal \
    --extra_apks com.google.pixel.vibrator.hal.apex=keys/com.google.pixel.vibrator.hal \
    --extra_apks com.qorvo.uwb.apex=keys/com.qorvo.uwb \
    --extra_apex_payload_key com.android.adbd.apex=keys/com.android.adbd.pem \
    --extra_apex_payload_key com.android.adservices.apex=keys/com.android.adservices.pem \
    --extra_apex_payload_key com.android.adservices.api.apex=keys/com.android.adservices.api.pem \
    --extra_apex_payload_key com.android.appsearch.apex=keys/com.android.appsearch.pem \
    --extra_apex_payload_key com.android.art.apex=keys/com.android.art.pem \
    --extra_apex_payload_key com.android.bluetooth.apex=keys/com.android.bluetooth.pem \
    --extra_apex_payload_key com.android.btservices.apex=keys/com.android.btservices.pem \
    --extra_apex_payload_key com.android.cellbroadcast.apex=keys/com.android.cellbroadcast.pem \
    --extra_apex_payload_key com.android.compos.apex=keys/com.android.compos.pem \
    --extra_apex_payload_key com.android.configinfrastructure.apex=keys/com.android.configinfrastructure.pem \
    --extra_apex_payload_key com.android.connectivity.resources.apex=keys/com.android.connectivity.resources.pem \
    --extra_apex_payload_key com.android.conscrypt.apex=keys/com.android.conscrypt.pem \
    --extra_apex_payload_key com.android.devicelock.apex=keys/com.android.devicelock.pem \
    --extra_apex_payload_key com.android.extservices.apex=keys/com.android.extservices.pem \
    --extra_apex_payload_key com.android.graphics.pdf.apex=keys/com.android.graphics.pdf.pem \
    --extra_apex_payload_key com.android.hardware.biometrics.face.virtual.apex=keys/com.android.hardware.biometrics.face.virtual.pem \
    --extra_apex_payload_key com.android.hardware.biometrics.fingerprint.virtual.apex=keys/com.android.hardware.biometrics.fingerprint.virtual.pem \
    --extra_apex_payload_key com.android.hardware.boot.apex=keys/com.android.hardware.boot.pem \
    --extra_apex_payload_key com.android.hardware.cas.apex=keys/com.android.hardware.cas.pem \
    --extra_apex_payload_key com.android.hardware.wifi.apex=keys/com.android.hardware.wifi.pem \
    --extra_apex_payload_key com.android.healthfitness.apex=keys/com.android.healthfitness.pem \
    --extra_apex_payload_key com.android.hotspot2.osulogin.apex=keys/com.android.hotspot2.osulogin.pem \
    --extra_apex_payload_key com.android.i18n.apex=keys/com.android.i18n.pem \
    --extra_apex_payload_key com.android.ipsec.apex=keys/com.android.ipsec.pem \
    --extra_apex_payload_key com.android.media.apex=keys/com.android.media.pem \
    --extra_apex_payload_key com.android.media.swcodec.apex=keys/com.android.media.swcodec.pem \
    --extra_apex_payload_key com.android.mediaprovider.apex=keys/com.android.mediaprovider.pem \
    --extra_apex_payload_key com.android.nearby.halfsheet.apex=keys/com.android.nearby.halfsheet.pem \
    --extra_apex_payload_key com.android.networkstack.tethering.apex=keys/com.android.networkstack.tethering.pem \
    --extra_apex_payload_key com.android.neuralnetworks.apex=keys/com.android.neuralnetworks.pem \
    --extra_apex_payload_key com.android.ondevicepersonalization.apex=keys/com.android.ondevicepersonalization.pem \
    --extra_apex_payload_key com.android.os.statsd.apex=keys/com.android.os.statsd.pem \
    --extra_apex_payload_key com.android.permission.apex=keys/com.android.permission.pem \
    --extra_apex_payload_key com.android.resolv.apex=keys/com.android.resolv.pem \
    --extra_apex_payload_key com.android.rkpd.apex=keys/com.android.rkpd.pem \
    --extra_apex_payload_key com.android.runtime.apex=keys/com.android.runtime.pem \
    --extra_apex_payload_key com.android.safetycenter.resources.apex=keys/com.android.safetycenter.resources.pem \
    --extra_apex_payload_key com.android.scheduling.apex=keys/com.android.scheduling.pem \
    --extra_apex_payload_key com.android.sdkext.apex=keys/com.android.sdkext.pem \
    --extra_apex_payload_key com.android.support.apexer.apex=keys/com.android.support.apexer.pem \
    --extra_apex_payload_key com.android.telephony.apex=keys/com.android.telephony.pem \
    --extra_apex_payload_key com.android.telephonymodules.apex=keys/com.android.telephonymodules.pem \
    --extra_apex_payload_key com.android.tethering.apex=keys/com.android.tethering.pem \
    --extra_apex_payload_key com.android.tzdata.apex=keys/com.android.tzdata.pem \
    --extra_apex_payload_key com.android.uwb.apex=keys/com.android.uwb.pem \
    --extra_apex_payload_key com.android.uwb.resources.apex=keys/com.android.uwb.resources.pem \
    --extra_apex_payload_key com.android.virt.apex=keys/com.android.virt.pem \
    --extra_apex_payload_key com.android.vndk.current.apex=keys/com.android.vndk.current.pem \
    --extra_apex_payload_key com.android.vndk.current.on_vendor.apex=keys/com.android.vndk.current.on_vendor.pem \
    --extra_apex_payload_key com.android.wifi.apex=keys/com.android.wifi.pem \
    --extra_apex_payload_key com.android.wifi.dialog.apex=keys/com.android.wifi.dialog.pem \
    --extra_apex_payload_key com.android.wifi.resources.apex=keys/com.android.wifi.resources.pem \
    --extra_apex_payload_key com.google.pixel.camera.hal.apex=keys/com.google.pixel.camera.hal.pem \
    --extra_apex_payload_key com.google.pixel.vibrator.hal.apex=keys/com.google.pixel.vibrator.hal.pem \
    --extra_apex_payload_key com.qorvo.uwb.apex=keys/com.qorvo.uwb.pem \
    $OUT/obj/PACKAGING/target_files_intermediates/*-target_files*.zip \
    signed-target_files.zip

生成安装包

ota_from_target_files -k keys/releasekey \
    --block --backup=true \
    signed-target_files.zip \
    signed-ota_update.zip

注意:对于早于 18.1 的 LineageOS 版本,必须在 ota_from_target_files 命令前添加 ./build/tools/releasetools/

./build/tools/releasetools/ota_from_target_files -k keys/releasekey \
    --block --backup=true \
    signed-target_files.zip \
    signed-ota_update.zip

执行完成后,在当前目录下生成的 signed-ota_update.zip 就是签名后的刷机包



Android.bp    android.ipr~    build        external    libnativehelper  pdk                    signed-target_files.zip
Makefile      android.iws     cts          frameworks  lineage          platform_testing       system
android       art             dalvik       hardware    lineage-sdk      prebuilts              test
android.iml   bionic          developers   kernel      make_keys.sh     sdk                    toolchain
android.iml~  bootable        development  keys        out              sign_ota_wayne.sh      tools
android.ipr   bootstrap.bash  device       libcore     packages         signed-ota_update.zip  vendor

自动化脚本

以 LineageOS17.1(wayne) 为例,nano sign_ota_wayne.sh 创建脚本,内容如下

source build/envsetup.sh

# 设置构建目标
breakfast wayne

# target files
mka target-files-package otatools


# sign target files
./build/tools/releasetools/sign_target_files_apks -o -d keys \
    $OUT/obj/PACKAGING/target_files_intermediates/*-target_files-*.zip \
    signed-target_files.zip


# sign ota package
./build/tools/releasetools/ota_from_target_files -k keys/releasekey \
    --block --backup=true \
    signed-target_files.zip \
    signed-ota_update.zip

通过脚本把生成自定义签名安装包的流程自动化。

# 添加执行权限
chmod +x signing_ota_wayne.sh
# 执行脚本
./sign_ota_wayne.sh

刷机

进入recovery模式(或者同时按住【音量+】和【开机键】)

fastboot reboot recovery

注意:如果目前设备安装包签名和现在刷的安装包不一样,需要格式化 system 分区。格式化流程:【Factory reset】【Format system partition】。

【Apply update】【Apply from adb】开启 adb sideload 截图.png

开始刷机

adb sideload E:\lineageos\signed-ota_update.zip

等待刷机完成重启系统。

screenshot.png

参考: Signing Builds