Android 5.x OTA Update官方文档(十、版本签名)

在Android中,一般来说有两个地方使用加密签名。

1.每个.apk文件必须进行签名。Android的程序包管理器通过两种方式使用签名:

  • 当一个应用程序被替换时,只有相同签名的应用才能操作旧版本的数据。
  • 两个应用如果签名一致,那么这两个应用可以共享User ID和用户数据。

2.OTA更新包必须进行签名否则更新程序无法进行安装。(注!我们制作更新包的时候如果不指定key,系统会指定默认的key进行签名,如testkey。)

证书和秘钥

每个秘钥需要两个文件:扩展名为.x509.pem的证书(公钥)和扩展名为.pk8私钥。私钥是用来对包进行签名的,不可公开,而且有必要使用一定策略的密码进行保护,仅仅是让最终发布版本的人知道密码即可。而证书(公钥)相对来说要求并没有那么严格,它通常被用来验证一个包是否进行过密钥签名。

标准的Android通常使用下面4个秘钥,它们位于build/target/product/security目录下:

testkey

默认生成的更新包秘钥,如果我们在制作更新包时没有指定响应的秘钥,系统会默认使用testkey进行签名。

platform

平台使用的测试秘钥

shared

联系人等共享测试秘钥

media

部分多媒体、下载系统等程序包所使用的测试秘钥

我们可以在我们的.mk文件中通过设置LOCAL_CERTIFICATE来为我们的安装包指定秘钥(如果没有指定有效的key,系统会默认使用testkey)。

Device/yoyodyne/apps/SpecialApp/Android.mk

[...]

LOCAL_CERTIFICATE := device/yoyodyne/security/special

通过上面的配置,编译系统就会使用device/yoyodyne/security/special.{.509.pem,pk8}来为我们的应用进行签名。编译系统只能是用没有密码保护的私钥。

生成秘钥

我们可以使用openssl工具来生成我们的秘钥(公钥和私钥),openssl工具下载地址:http://www.openssl.org/

# generate RSA key

% openssl genrsa -3 -out temp.pem 2048

Generating RSA private key, 2048 bit long modulus

....+++

.....................+++

e is 3 (0x3)

# create a certificate with the public part of the key

% 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/[email protected]‘

# create a PKCS#8-formatted version of the private key

% openssl pkcs8 -in temp.pem -topk8 -outform DER -out releasekey.pk8 -nocrypt

# securely delete the temp.pem file

% shred --remove temp.pem

Openssl的pkcs8命令会生成一个没有密码保护的.pk8文件,这种方式适用于编译系统。如果想生成一个带有密码保护的.pk8文件,我们可以使用-passout stdin参数代替nocrypt参数即可。具体可参考http://www.openssl.org/docs/apps/openssl.html#PASS_PHRASE_ARGUMENTS。

签名APP

我们可以使用sign_target_files_apks脚本来对.apk文件进行签名。当我们运行该脚本时,我们需要在命令行中使用”-k src_key=dest_key来指定相应的key。我们也可以使用-d dir来制定一个目录用来替换编译系统所使用的build/target/product/security目录,这就相当于下面这种用法:

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

例如在tardis项目中,使用了5个具有密码保护的秘钥:4个用来替换build/target/product/security,一个用来替换上面提到的keydevice/yoyodyne/security/special,如下:

vendor/yoyodyne/security/tardis/releasekey.x509.pem
vendor/yoyodyne/security/tardis/releasekey.pk8
vendor/yoyodyne/security/tardis/platform.x509.pem
vendor/yoyodyne/security/tardis/platform.pk8
vendor/yoyodyne/security/tardis/shared.x509.pem
vendor/yoyodyne/security/tardis/shared.pk8
vendor/yoyodyne/security/tardis/media.x509.pem
vendor/yoyodyne/security/tardis/media.pk8
vendor/yoyodyne/security/special.x509.pem
vendor/yoyodyne/security/special.pk8           # NOT password protected
vendor/yoyodyne/security/special-release.x509.pem
vendor/yoyodyne/security/special-release.pk8   # password protected

然后我们可以像下面的例子中描述的一样对所有的应用进行签名:

% ./build/tools/releasetools/sign_target_files_apks     -d vendor/yoyodyne/security/tardis     -k vendor/yoyodyne/special=vendor/yoyodyne/special-release     -o \    # explained in the next section
    tardis-target_files.zip signed-tardis-target_files.zip
Enter password for vendor/yoyodyne/security/special-release key>
Enter password for vendor/yoyodyne/security/tardis/media key>
Enter password for vendor/yoyodyne/security/tardis/platform key>
Enter password for vendor/yoyodyne/security/tardis/releasekey key>
Enter password for vendor/yoyodyne/security/tardis/shared key>
    signing: Phone.apk (vendor/yoyodyne/security/tardis/platform)
    signing: Camera.apk (vendor/yoyodyne/security/tardis/media)
    signing: Special.apk (vendor/yoyodyne/security/special-release)
    signing: Email.apk (vendor/yoyodyne/security/tardis/releasekey)
        [...]
    signing: ContactsProvider.apk (vendor/yoyodyne/security/tardis/shared)
    signing: Launcher.apk (vendor/yoyodyne/security/tardis/shared)
rewriting SYSTEM/build.prop:
  replace:  ro.build.description=tardis-user Eclair ERC91 15449 test-keys
     with:  ro.build.description=tardis-user Eclair ERC91 15449 release-keys
  replace: 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
    signing: framework-res.apk (vendor/yoyodyne/security/tardis/platform)
rewriting RECOVERY/RAMDISK/default.prop:
  replace:  ro.build.description=tardis-user Eclair ERC91 15449 test-keys
     with:  ro.build.description=tardis-user Eclair ERC91 15449 release-keys
  replace: 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
using:
    vendor/yoyodyne/security/tardis/releasekey.x509.pem
for OTA package verification
done.

签名OTA包

签名OTA包的流程主要有下面这些:

1.准备好build时所要使用的签名文件

2.对准备创建的ota包进行签名

具体命令如下:

% ./build/tools/releasetools/ota_from_target_files     -k vendor/yoyodyne/security/tardis/releasekey     signed-tardis-target_files.zip     signed-ota_update.zip
unzipping target target-files...
(using device-specific extensions from target_files)
Enter password for vendor/yoyodyne/security/tardis/releasekey key>
done.

签名与侧面安装机制

侧面安装机制并不能绕开安装包签名机制而进行。在安装更新前,recovery会对更新包的签名进行验证,它会验证OTA包签名的私钥是否和recovery分区存放的公钥相符。

对更新包签名的验证通常会有两次,一次是android系统使用Android API中的RecoverySystem.verifyPackage()方法进行验证,一种是recovery系统的验证。RecoverySystem API会检查存储在Android系统中的公钥是否与/system/etc/security/otacerts.zip(默认情况下)。而recovery 系统会验证存储在recovery 分区中的/res/keys中存储的公钥。

一般情况下,两个地方存储的公钥是相同的。在侧面安装机制中我们可以指定额外的key进行校验,通过下面的配置。

vendor/yoyodyne/tardis/products/tardis.mk

[...]
PRODUCT_EXTRA_RECOVERY_KEYS := vendor/yoyodyne/security/tardis/sideload

原文如下:

Android uses cryptographic signatures in two places:

  1. Each .apk file must be signed. Android‘s Package Manager uses an .apk signature in two ways:

    • When an application is replaced, it must be signed by the same key as the old application in order to get access to the old application‘s data.
    • If two or more applications want to share a user ID (so they can share data, etc.), they must be signed with the same key.
  2. OTA update packages must be signed with one of the keys expected by the system or the installation process will reject them.

Certificates and keys



Each key comes in two files: the certificate, which has the extension .x509.pem, and the private key, which has the extension .pk8. The private key should be kept secret and is needed to sign a package. The key may itself be protected by a
password—a reasonable strategy is to store your keys in source control along with the code—but keep them protected by a password known only to the people who make final releases. The certificate, in contrast, contains only the public half of the key, so it
can be distributed widely. It is used to verify a package has been signed by the corresponding private key.

The standard Android build uses four keys, all of which reside in build/target/product/security:

testkey
Generic default key for packages that do not otherwise specify a key.
platform
Test key for packages that are part of the core platform.
shared
Test key for things that are shared in the home/contacts process.
media
Test key for packages that are part of the media/download system.

Individual packages specify one of these keys by setting LOCAL_CERTIFICATE in their Android.mk file. (testkey is used if this variable is not set.) You can also specify an entirely different key by pathname, e.g.:

device/yoyodyne/apps/SpecialApp/Android.mk

 [...]

LOCAL_CERTIFICATE := device/yoyodyne/security/special

Now the build uses the device/yoyodyne/security/special.{x509.pem,pk8} key to sign SpecialApp.apk. The build can use only private keys that are not password protected.

Generating keys



Android uses 2048-bit RSA keys with public exponent 3. You can generate certificate/private key pairs using the openssl tool from openssl.org:

# generate RSA key
% openssl genrsa -3 -out temp.pem 2048
Generating RSA private key, 2048 bit long modulus
....+++
.....................+++
e is 3 (0x3)

# create a certificate with the public part of the key
% 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/[email protected]‘

# create a PKCS#8-formatted version of the private key
% openssl pkcs8 -in temp.pem -topk8 -outform DER -out releasekey.pk8 -nocrypt

# securely delete the temp.pem file
% shred --remove temp.pem

The openssl pkcs8 command given above creates a .pk8 file with no password, suitable for use with the build system. To create a .pk8 secured with a password (which you should do for all actual release keys), replace the -nocrypt argument
with -passout stdin; then openssl will encrypt the private key with a password read from standard input. No prompt is printed, so if stdin is the terminal the program will appear to
hang when it‘s really just waiting for you to enter a password. Other values can be used for the-passout argument to read the password from other locations; for details, see the openssl
documentation
.

The temp.pem intermediate file contains the private key without any kind of password protection, so dispose of it thoughtfully when generating release keys. In particular, the GNUshred utility may not be effective on network or journaled filesystems. You can
use a working directory located in a RAM disk (such as a tmpfs partition) when generating keys to ensure the intermediates are not inadvertently exposed.

Signing apps for release



The first step in preparing a build for release is to sign all the .apk files in it, replacing the test keys used by the build system. This is done with the sign_target_files_apks script.
It takes a target-files .zip as input and produces a new target-files .zip in which all the .apks have been signed with new keys.

When you run this script, you must specify on the command line a replacement key for each key used in the build. The -k src_key= dest_key flag specifies key replacements
one at a time. The flag -d dir lets you specify a directory with four keys to replace all those in build/target/product/security;
it is equivalent to using -k four times to specify the mappings:

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

For the hypothetical tardis product, you need five password-protected keys: four to replace the four inbuild/target/product/security, and one to replace the additional keydevice/yoyodyne/security/specialrequired
by SpecialApp in the example above. If the keys were in the following files:

vendor/yoyodyne/security/tardis/releasekey.x509.pem
vendor/yoyodyne/security/tardis/releasekey.pk8
vendor/yoyodyne/security/tardis/platform.x509.pem
vendor/yoyodyne/security/tardis/platform.pk8
vendor/yoyodyne/security/tardis/shared.x509.pem
vendor/yoyodyne/security/tardis/shared.pk8
vendor/yoyodyne/security/tardis/media.x509.pem
vendor/yoyodyne/security/tardis/media.pk8
vendor/yoyodyne/security/special.x509.pem
vendor/yoyodyne/security/special.pk8           # NOT password protected
vendor/yoyodyne/security/special-release.x509.pem
vendor/yoyodyne/security/special-release.pk8   # password protected

Then you would sign all the apps like this:

% ./build/tools/releasetools/sign_target_files_apks \
    -d vendor/yoyodyne/security/tardis \
    -k vendor/yoyodyne/special=vendor/yoyodyne/special-release \
    -o \    # explained in the next section
    tardis-target_files.zip signed-tardis-target_files.zip
Enter password for vendor/yoyodyne/security/special-release key>
Enter password for vendor/yoyodyne/security/tardis/media key>
Enter password for vendor/yoyodyne/security/tardis/platform key>
Enter password for vendor/yoyodyne/security/tardis/releasekey key>
Enter password for vendor/yoyodyne/security/tardis/shared key>
    signing: Phone.apk (vendor/yoyodyne/security/tardis/platform)
    signing: Camera.apk (vendor/yoyodyne/security/tardis/media)
    signing: Special.apk (vendor/yoyodyne/security/special-release)
    signing: Email.apk (vendor/yoyodyne/security/tardis/releasekey)
        [...]
    signing: ContactsProvider.apk (vendor/yoyodyne/security/tardis/shared)
    signing: Launcher.apk (vendor/yoyodyne/security/tardis/shared)
rewriting SYSTEM/build.prop:
  replace:  ro.build.description=tardis-user Eclair ERC91 15449 test-keys
     with:  ro.build.description=tardis-user Eclair ERC91 15449 release-keys
  replace: 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
    signing: framework-res.apk (vendor/yoyodyne/security/tardis/platform)
rewriting RECOVERY/RAMDISK/default.prop:
  replace:  ro.build.description=tardis-user Eclair ERC91 15449 test-keys
     with:  ro.build.description=tardis-user Eclair ERC91 15449 release-keys
  replace: 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
using:
    vendor/yoyodyne/security/tardis/releasekey.x509.pem
for OTA package verification
done.

After prompting the user for passwords for all password-protected keys, the script re-signs all the .apk files in the input target .zip with the release keys. Before running the command, you can also set the ANDROID_PW_FILE environment variable to a temporary
filename; the script then invokes your editor to allow you to enter passwords for all keys (this may be a more convenient way to enter passwords).

sign_target_files_apks also rewrites the build description and fingerprint in the build properties files to reflect the fact that this is a signed build. The -t flag
can control what edits are made to the fingerprint. Run the script with -h to see documentation on all flags.

Signing OTA packages



You need the following components to sign OTA packages:

  1. Certificates of the keys you want this build to accept.
  2. Sign the newly-created package with the private key (must correspond to the certificate embedded in the current build of any device to which you want to send this package).

To achieve these components:

  • The target-files .zip produced by the build sets the OTA certificate to the certificate of the test key. Passing the-o flag to sign_target_files_apks replaces
    this key with the release key from your build.
  • To sign the OTA update package, use the -k option when generating it to specify the key. You should giveota_from_target_files the signed version
    of the target-files .zip as well:

    % ./build/tools/releasetools/ota_from_target_files \
        -k vendor/yoyodyne/security/tardis/releasekey \
        signed-tardis-target_files.zip \
        signed-ota_update.zip
    unzipping target target-files...
    (using device-specific extensions from target_files)
    Enter password for vendor/yoyodyne/security/tardis/releasekey key>
    done.

Signatures and sideloading

Sideloading does not bypass recovery‘s normal package signature verification mechanism—before installing a package, recovery will verify that it is signed with one of the private keys matching the public keys stored in the recovery partition, just as it would
for a package delivered over-the-air.

Update packages received from the main system are typically verified twice: once by the main system, using theRecoverySystem.
verifyPackage()
 method in the android API, and then again by recovery. The RecoverySystem API checks the signature against public keys stored in the main system, in the file/system/etc/security/otacerts.zip (by
default). Recovery checks the signature against public keys stored in the recovery partition RAM disk, in the file /res/keys.

Normally these two locations store the same set of keys. By adding a key to just the recovery set of keys, it‘s possible to sign packages that can be installed only via sideloading (assuming the main system‘s update download mechanism is correctly
doing verification against otacerts.zip). You can specify extra keys to be included only in recovery by setting the PRODUCT_EXTRA_RECOVERY_KEYS variable in your product definition:

vendor/yoyodyne/tardis/products/tardis.mk

 [...]

PRODUCT_EXTRA_RECOVERY_KEYS := vendor/yoyodyne/security/tardis/sideload

This includes the public key vendor/yoyodyne/security/tardis/sideload. x509.pem in the recovery keys file so it can install packages signed with it. The extra key is not included
in otacerts.zip though, so systems that correctly verify downloaded packages do not invoke recovery for packages signed with this key.

时间: 2024-10-09 21:05:23

Android 5.x OTA Update官方文档(十、版本签名)的相关文章

Android 5.x OTA Update官方文档(八、图说Recovery UI)

写在前面: 若能直译,不会意译,意译不成,为了选择不误导他人也会漏译无伤大雅的部分,英语是硬伤,如果有误译,请路过的朋友帮忙指正,以免误导更多的朋友. RecoveryUI除了之前提到的标题.选项菜单.提示性文字还有另外的一个重要的成员图片.在正常的更新过程中,用户看到的仅仅是图片(这里指的标准的OTA升级流程,如开机进入recovery模式.安装更新时进度条发生变化,最后再开机进入正常模式),而且在这个过程,用户是没有机会与RecoveryUI进行交互的.但是一旦在更新过程中出现了异常,用户所

Android 5.x OTA Update官方文档(九、Sideloading-侧面安装机制)

写在前面: 本篇博文漏译了很多,英文功底比较好的同学可以选择阅读原版文档,如果方便请分享翻译后文档给大家,谢谢. recovery有一个侧面安装(sideloading)机制来方便我们手动的安装更新而不在使用OTA的方式.这种机制对于调试和维护是很有帮助的,特别是当我们无法正常启动我们的系统的时候. 目前来说我们,有了这种机制,我们可以在设备的SD卡中载入更新包.在没有启动设备的情况下,我们可以通过电脑将更新包拷贝到SD卡上,然后再将SD卡插入到设备中进行侧面安装.而且如果Android设备当前

Android 5..x OTA Update官方文档(六、定制Recovery UI)

recovery界面 为了支持不同的硬件设备(物理按键.显示.LEDs等),我们可以定制recovery界面进行可视化显示,并进行相关的操作.那么我们可以通过继承bootable/recovery/defalust_device.cpp,并重写相关的函数来为我们的设备进行可视化定制.因此本篇博文旨在为大家介绍如何构建一个能够实现recovery界面定制的静态库.首先来了解西面这段头文件: device/yoyodyne/tardis/recovery/recovery_ui.cpp #inclu

Android 5..x OTA Update官方文档(七、构建设备)

我们通过调用recovery_ui.cpp中make_device()函数来创建一个Device的实例,如下: class TardisDevice : public Device { // ... all the above methods ... }; Device* make_device() { return new TardisDevice(); } 编译recovery_ui.cpp 再通过前一篇对recovery_ui.cpp的介绍我们来介绍一下如何为recovery_ui.cpp

OTA Update官方文档(二,OTA 打包工具)

写在前面: OTA打包工具ota_from_target_files(build/tools/releasetools/目录下)可以为我们创建两种类型的更新包:整包和增量包.打包工具一般来说会对我们称之为目标文件(target-files.zip)进行打包,该目标文件是有Android编译系统产生,通常可在终端下使用make otapackage生成. 一.整包升级 一个整包包含了Android设备的整个终态(system/boot/recovery分区),只要设备可以接收更新包并且进入reco

OTA Update官方文档(五、Recovery系统分区映射)

Recovery系统包含了很多钩子程序,因此OAT更新除了可以更新Android系统也可以更新设备的其他部分.(如基带.无线电处理器). 分区映射 从Android2.3起,平台开始支持eMMC存储设备和ext4文件系统.它同样支持MTD设备和yaffs2文件系统. 分区映射文件TARGET_RECOVERY_FSTAB一般会被recovery二进制程序和打包工具所使用,我们可以在BoardConfig.mk文件中配置映射文件的文件名为TARGET_RECOVERY_FSTAB. 下面是一个简单

OTA Update官方文档(四、OTA更新包解读)

写在前面: 系统创建通过"bootable/recovery/updater"创建一个二进制更新程序并在OTA包中使用进行更新的安装. 更新包实际上也就是一个.zip格式的压缩文件(如我们之前提到过的ota_update.zip,incremental_ota_update.zip).在这个压缩包中包含了一个可执行的二进制程序-EMTA-INF/com/google/android/update-binary.这个二进制程序我们可以理解成一个升级程序,这个升级程序包含了一系列的内建函数

OTA Updates官方文档(一,OTA 升级)

写在前面: Android设备可以接受和安装基于系统和应用的更新.在设备中有一个特殊recovery分区,在这个分区中有一套特殊的恢复系统可以将下载的更新包进行解压并应用到系统中去. 本节主要描述了更新包的组织架构,并且概述了如何使用更新包打包工具制作系统升级的更新包.OTA 的存在是用来对潜在系统的升级,或者在系统分区安装只读(不可卸载)的应用程序,因此在升级过程中不会影响到用于已经安装到系统中的 应用程序. 本节的内容主要基于Android5.x版本. 一.Android设备布局的设计 通常

Android Studio官方文档之构建和运行你的APP

Android Studio官方文档之构建和运行你的APP 本文由MTJH翻译,jkYishon审校. 前言 默认情况下,Android Studio设置新的项目并且部署到模拟器或者真机设备上,只需要点击几下.使用即时运行,你并不需要构建一个新的APK即可将改变后的方法和现有的应用资源应用到一个正在运行的应用程序中,所以代码的改变是即时可见的. 点击Run来构建并运行你的APP.Android Studio通过Gradle构建你的App,选择一个部署的设备(模拟器或连接的设备),然后把你的APP