Android操作系统映像在两个地方使用加密签名:.apk和/data。发布密钥存储在build/target/product/securitymake.apk中。要生成您自己的唯一发布密钥集,请在Android树的根目录下运行以下命令:
```bash
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 \n ./development/tools/make_key ~/.android-certs/$x "$subject"; \ndone
$subject
```
要生成发布映像,请使用以下命令:
```bash
make dist
sign_target_files_apks \n -o \n # explained in the next section --default_key_mappings ~/.android-certs \n out/dist/*-target_files-*.zip \n signed-target_files.zip
sign_target_files_apks.zip.zip.apksigned-target_files.zipIMAGES/
```
对OTA软件包进行签名时,您可以按照以下步骤将已签名的目标文件zip转换为已签名的OTA更新zip:
```bash
ota_from_target_files \n -k (--package_key) \n signed-target_files.zip \n signed-ota_update.zip
```
旁加载不会绕过Recovery流程中的正常软件包签名验证机制。在安装一个软件包之前,Recovery会验证该软件包是否由与Recovery分区中存储的公钥相匹配的私钥进行签名,这与利用无线方式传输的软件包的处理方式一样。
通常情况下,系统映像和 Recovery 映像存储的是相同的 OTA 公钥集。通过将密钥仅添加至 Recovery 密钥集,可对只能通过旁加载安装的 apk 包(假设主系统的更新下载机制正确地对照 otacerts.zip 进行验证)签名。您可以通过在产品定义中设置 PRODUCT_EXTRA_RECOVERY_KEYS 变量来指定其他仅可纳入 Recovery 中的密钥:
```makefile
vendor/yoyodyne/tardis/products/tardis.mk
[...]
PRODUCT_EXTRA_RECOVERY_KEYS := vendor/yoyodyne/security/tardis/sideload
vendor/yoyodyne/security/tardis/sideload.x509.pem
证书和私钥
每个密钥都包含两个文件:一个是扩展名为 .x509.pem 的证书,另一个是扩展名为 .pk8 的私钥。私钥需要加以保密,并用于对 apk 包进行签名。密钥本身也可能受密码保护。相比之下,证书只包含公开的一半密钥,因此可以大范围地分发。证书用于验证某个 apk 包是否由相应的私钥进行签名。
build/target/product/security
testkey
适用于未另外指定密钥的 apk 包的通用默认密钥。
```
平台、共享、媒体、网络stack等不同类型的测试密钥:
```makefile
platform
适用于核心平台所包含的 apk 包的测试密钥。
shared
适用于家庭/联系人进程中的共享内容的测试密钥。
media
适用于媒体/下载系统所包含的 apk 包的测试密钥。
networkstack
适用于网络系统所包含的 apk 包的测试密钥。networkstack 密钥用于为设计为模块化系统组件的二进制文件签名。如果您的模块更新是单独构建的,并且以预构建的形式集成到设备映像中,您可能就不需要在 Android 源代码树中生成 networkstack 密钥。
```
单个 apk 包会在其 Android.mk 文件中设置 LOCAL_CERTIFICATE 以指定其中一个密钥。如果未设置此变量,则使用 testkey。您还可以通过路径名指定完全不同的密钥,例如:
```makefile
device/yoyodyne/apps/SpecialApp/Android.mk
```
以下是根据提供的内容重构的代码段,并保持了段落结构:
```plaintext
LOCAL_CERTIFICATE := device/yoyodyne/security/special
device/yoyodyne/security/special.{x509.pem,pk8}
高级签名选项
APK 签名密钥替换
sign_target_files_apks
--key_mapping--default_key_mappings
--key_mapping src_key=dest_key--default_key_mappings dirbuild/target/product/security--key_mapping
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
--extra_apks apk_name1,apk_name2,...=keykey
build/target/product/securitydevice/yoyodyne/security/special
```
请注意,我已将代码格式化为纯文本形式以便阅读。如果您需要将其转换回Markdown格式,请告诉我。
以下是重构后的内容,并保持了段落结构:
```
所有应用签名如下所示:
- vendor/yoyodyne/security/tardis/releasekey.x509.pem (release key)
- vendor/yoyodyne/security/tardis/releasekey.pk8 (PKCS#8 格式的 release key)
- vendor/yoyodyne/security/tardis/platform.x509.pem (平台证书)
- vendor/yoyodyne/security/tardis/platform.pk8 (PKCS#8 格式的平台证书)
- vendor/yoyodyne/security/tardis/shared.x509.pem (共享证书)
- vendor/yoyodyne/security/tardis/shared.pk8 (PKCS#8 格式的共享证书)
- vendor/yoyodyne/security/tardis/media.x509.pem (媒体证书)
- vendor/yoyodyne/security/tardis/media.pk8 (PKCS#8 格式的媒体证书)
- vendor/yoyodyne/security/tardis/networkstack.x509.pem (网络栈证书)
- vendor/yoyodyne/security/tardis/networkstack.pk8 (PKCS#8 格式的网络栈证书)
- vendor/yoyodyne/security/special.x509.pem (特殊应用证书)
- vendor/yoyodyne/security/special.pk8 (PKCS#8 格式的特殊应用证书)
注意:前者未加密码保护,后者已加密码保护。
```
以下是重构后的内容:
```
在当前目录下的build/make/tools/releasetools/sign_target_files_apks目录中执行以下命令:
./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
```
执行上述命令后,会将结果保存在名为tardis-target_files.zip的文件中。
以下是重构后的内容:
```
输入供应商/yoyodyne/security/special-release密钥的密码:
输入供应商/yoyodyne/security/tardis/networkstack密钥的密码:
输入供应商/yoyodyne/security/tardis/media密钥的密码:
输入供应商/yoyodyne/security/tardis/platform密钥的密码:
输入供应商/yoyodyne/security/tardis/releasekey密钥的密码:
输入供应商/yoyodyne/security/tardis/shared密钥的密码:
签名:Phone.apk (供应商/yoyodyne/security/tardis/platform)
签名:Camera.apk (供应商/yoyodyne/security/tardis/media)
签名:NetworkStack.apk (供应商/yoyodyne/security/tardis/networkstack)
签名:Special.apk (供应商/yoyodyne/security/special-release)
签名:Email.apk (供应商/yoyodyne/security/tardis/releasekey)
[...]
签名:ContactsProvider.apk (供应商/yoyodyne/security/tardis/shared)
签名:Launcher.apk (供应商/yoyodyne/security/tardis/shared) 不签名:PresignedApp.apk(由于特殊证书字符串而跳过)
重写 SYSTEM/build.prop: 替换: ro.build.description=tardis-user Eclair ERC91 15449 test-keys with: ro.build.description=tardis-user Eclair ERC91 15449 release-keys 替换: 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
签名:framework-res.apk (供应商/yoyodyne/security/tardis/platform)
重写 RECOVERY/RAMDISK/default.prop: 替换: ro.build.description=tardis-user Eclair ERC91 15449 test-keys with: ro.build.description=tardis-user Eclair ERC91 15449 release-keys 替换: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/test-keys with: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair
在 Android 10 中,引入了 APEX 文件格式,用于安装较低级别的系统模块。APEX 签名中提到,每个 APEX 文件都需要使用两个密钥进行签名:一个用于 APEX 中的迷你文件系统映像,另一个用于整个 APEX。为了实现这一目标,需要替换签名密钥。
要替换签名密钥,可以使用 `--extra_apex_payload` 和 `--extra_apks` 参数。以下是一个示例命令:
```bash
zip --output my_apex.zip ANDROID_PW_FILE EXTRA_APEX_PAYLOAD EXTRA_APKS
```
其中:
- `ANDROID_PW_FILE` 是包含签名密钥的文件;
- `EXTRA_APEX_PAYLOAD` 是包含 APEX 文件的文件;
- `EXTRA_APKS` 是包含额外 APK 文件的文件。
在这个示例中,我们将这些文件打包成一个名为 `my_apex.zip` 的 ZIP 文件。
以下是重构后的文本内容:
```csharp
{
"name": ["com.android.conscrypt.apex", "com.android.media.apex", "com.android.runtime.release.apex"],
"public_key": ["PRESIGNED", "PRESIGNED", "vendor/yoyodyne/security/testkeys/com.android.runtime.avbpubkey"],
"private_key": ["PRESIGNED", "PRESIGNED", "vendor/yoyodyne/security/testkeys/com.android.runtime.pem"],
"container_certificate": ["PRESIGNED", "PRESIGNED", "vendor/yoyodyne/security/testkeys/com.google.android.runtime.release_container.x509.pem"],
"container_private_key": ["PRESIGNED", "PRESIGNED", "vendor/yoyodyne/security/testkeys/com.google.android.runtime.release_container.pk8"]
}
您拥有以下包含发布密钥的文件:
- vendor/yoyodyne/security/runtime_apex_container.x509.pem
- vendor/yoyodyne/security/runtime_apex_container.pk8
- vendor/yoyodyne/security/runtime_apex_payload.pem
```
```
2019-10-25 14:36:47,788 INFO: [com.android.runtime.release.apex] com.yoyodyne.security.SignApkTask#execute(List) called
2019-10-25 14:36:47,788 INFO: [com.android.runtime.release.apex] Task is executing for target apex_container
2019-10-25 14:36:47,788 INFO: [com.android.runtime.release.apex] Setting up key mappings and payload keys
2019-10-25 14:36:47,788 INFO: [com.android.runtime.release.apex] Key mappings are set to: runtime=tardis_payload=runtime_apex_container
2019-10-25 14:36:47,788 INFO: [com.android.runtime.release.apex] Payload keys are set to: runtime_apex_container=tardis_payload=runtime_apex_payload.pem
2019-10-25 14:36:47,788 INFO: [com.android.runtime.release.apex] Additional APKs are set to: com.android.runtime.release.apex=vendor/yoyodyne/security/runtime_apex_container
2019-10-25 14:36:47,788 INFO: [com.android.runtime.release.apex] Additional APKPEMs are set to: com.android.runtime.release.apex=vendor/yoyodyne/security/runtime_apex_payload
2019-10-25 14:36:47,788 INFO: [com.android.runtime.release.apex] Additional APKs are set to: com.android.media.apex=
2019-10-25 14:36:47,788 INFO: [com.android.runtime.release.apex] Additional APKPEMs are set to: com.android.media.apex=
2019-10-25 14:36:47,788 INFO: [com.android.runtime.release.apex] Creating tardis-target_files.zip
2019-10-25 14:36:47,788 INFO: [com.android.runtime.release.apex] Signing target files with the specified key mappings and payload keys
2019-10-25 14:36:47,788 INFO: [com.android.runtime.release.apex] Tardis target files have been signed and zipped as tardis-target_files.zip in the current working directory
```
以下是根据提供的内容重构后的代码示例:
```python
# 生成RSA密钥对
openssl genrsa -3 -out temp.pem 2048
# 使用公钥部分生成证书
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'
```
上述代码使用`openssl`工具生成了一个RSA密钥对。首先,使用`genrsa`命令生成一个具有2048位长度的RSA私钥,并将输出存储在名为`temp.pem`的文件中。然后,使用`req`命令结合私钥部分和指定的证书信息生成一个自签名的X.509证书,并将输出保存为名为`releasekey.x509.pem`的文件。最后,证书的有效期设置为10,000天。
以下是重构后的内容:
首先,我们需要创建一个PKCS#8格式的私钥版本。在终端中执行以下命令:
```bash
openssl pkcs8 -in temp.pem -topk8 -outform DER -out releasekey.pk8 -nocrypt
```
接下来,我们需要安全地删除临时文件temp.pem。在终端中执行以下命令:
```bash
shred --remove temp.pem
```
请注意,中间文件(temp.pem)包含不受任何类型密码保护的私钥。因此,在生成发布密钥时,应谨慎处理该文件。需要特别指出的是,GNUshred实用程序可能对网络或日志文件系统无效。在生成密钥时,您可以使用位于RAM磁盘(如tmpfs分区)中的工作目录以确保中间文件不会无意间被暴露。
然后,我们需要创建一个包含签名目标文件的zip文件。在终端中执行以下命令:
```bash
img_from_target_files signed-target_files.zip signed-img.zip
```
生成的文件包括:
- signed-img.zip
- 包含所有.img文件。
要将映像加载到设备上,请使用fastboot,如下所示:
```bash
fastboot update signed-img.zip
```