1page.title=Signing Builds for Release 2@jd:body 3 4<!-- 5 Copyright 2015 The Android Open Source Project 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18--> 19 20<div id="qv-wrapper"> 21 <div id="qv"> 22 <h2>In this document</h2> 23 <ol id="auto-toc"> 24 </ol> 25 </div> 26</div> 27 28<p>Android uses cryptographic signatures in two places:</p> 29<ol> 30<li>Each .apk file must be signed. Android's Package Manager uses an .apk 31signature in two ways:<ul> 32<li>When an application is replaced, it must be signed by the same key as the 33old application in order to get access to the old application's data.</li> 34<li>If two or more applications want to share a user ID (so they can share 35data, etc.), they must be signed with the same key.</ul></li> 36<li>OTA update packages must be signed with one of the keys expected by the 37system or the installation process will reject them.</ul></li> 38</ol> 39<h2 id="certificates-keys">Certificates and keys</h2> 40<p>Each key comes in two files: the <i>certificate</i>, which has the 41extension .x509.pem, and the <i>private key</i>, which has the extension .pk8. 42The private key should be kept secret and is needed to sign a package. The key 43may itself be protected by a password—a reasonable strategy is to store your 44keys in source control along with the code—but keep them protected by a 45password known only to the people who make final releases. The certificate, in 46contrast, contains only the public half of the key, so it can be distributed 47widely. It is used to verify a package has been signed by the corresponding 48private key.</p> 49<p>The standard Android build uses four keys, all of which reside in <code> 50build/target/product/security</code>:</p> 51 52<dl> 53<dt>testkey</dt> 54<dd>Generic default key for packages that do not otherwise specify a key.</dd> 55<dt>platform</dt> 56<dd>Test key for packages that are part of the core platform.</dd> 57<dt>shared</dt> 58<dd>Test key for things that are shared in the home/contacts process.</dd> 59<dt>media</dt> 60<dd>Test key for packages that are part of the media/download system.</dd></dl> 61 62<p>Individual packages specify one of these keys by setting LOCAL_CERTIFICATE 63in their Android.mk file. (testkey is used if this variable is not set.) You 64can also specify an entirely different key by pathname, e.g.:</p> 65 66<p><code>device/yoyodyne/apps/SpecialApp/Android.mk</code></p> 67<pre> 68 [...] 69 70LOCAL_CERTIFICATE := device/yoyodyne/security/special 71</pre> 72 73<p>Now the build uses the <code>device/yoyodyne/security/special.{x509.pem,pk8} 74</code> key to sign SpecialApp.apk. The build can use only private keys that 75are <i>not </i>password protected.</p> 76 77<h2>Generating keys</h2> 78<p>Android uses 2048-bit RSA keys with public exponent 3. You can generate 79certificate/private key pairs using the openssl tool from 80<a href="http://www.openssl.org/">openssl.org</a>:</p> 81 82<pre> 83# generate RSA key 84% <b>openssl genrsa -3 -out temp.pem 2048</b> 85Generating RSA private key, 2048 bit long modulus 86....+++ 87.....................+++ 88e is 3 (0x3) 89 90# create a certificate with the public part of the key 91% <b>openssl req -new -x509 -key temp.pem -out releasekey.x509.pem \ 92 -days 10000 \ 93 -subj '/C=US/ST=California/L=San Narciso/O=Yoyodyne, Inc./OU=Yoyodyne Mobility/CN=Yoyodyne/emailAddress=yoyodyne@example.com'</b> 94 95# create a PKCS#8-formatted version of the private key 96% <b>openssl pkcs8 -in temp.pem -topk8 -outform DER -out releasekey.pk8 -nocrypt</b> 97 98# securely delete the temp.pem file 99% <b>shred --remove temp.pem</b> 100</pre> 101 102<p>The openssl pkcs8 command given above creates a .pk8 file with <i>no</i> 103password, suitable for use with the build system. To create a .pk8 secured 104with a password (which you should do for all actual release keys), replace the 105<code>-nocrypt</code> argument with <code>-passout stdin</code>; then openssl 106will encrypt the private key with a password read from standard input. No 107prompt is printed, so if stdin is the terminal the program will appear to hang 108when it's really just waiting for you to enter a password. Other values can be 109used for the-passout argument to read the password from other locations; for 110details, see the 111<a href="http://www.openssl.org/docs/apps/openssl.html#PASS_PHRASE_ARGUMENTS"> 112openssl documentation</a>.</p> 113<p>The temp.pem intermediate file contains the private key without any kind of 114password protection, so dispose of it thoughtfully when generating release 115keys. In particular, the GNUshred utility may not be effective on network or 116journaled filesystems. You can use a working directory located in a RAM disk 117(such as a tmpfs partition) when generating keys to ensure the intermediates 118are not inadvertently exposed.</p> 119 120<h2 id="sign-apps-for-release">Signing apps for release</h2> 121<p>The first step in preparing a build for release is to sign all the .apk 122files in it, replacing the test keys used by the build system. This is done 123with the <code>sign_target_files_apks</code> script. It takes a target-files 124.zip as input and produces a new target-files .zip in which all the .apks have 125been signed with new keys.</p> 126<p>When you run this script, you must specify on the command line a 127replacement key for each key used in the build. The <code>-k <i>src_key</i>=<i> 128dest_key</i></code> flag specifies key replacements one at a time. The flag 129<code>-d <i>dir</i></code> lets you specify a directory with four keys to 130replace all those in <code>build/target/product/security</code>; it is 131equivalent to using <code>-k</code> four times to specify the mappings:</p> 132 133<pre> 134build/target/product/security/testkey = dir/releasekey 135build/target/product/security/platform = dir/platform 136build/target/product/security/shared = dir/shared 137build/target/product/security/media = dir/media 138</pre> 139 140<p>For the hypothetical tardis product, you need five password-protected keys: 141four to replace the four in <code>build/target/product/security</code>, and 142one to replace the additional <code>keydevice/yoyodyne/security/special</code> 143required by SpecialApp in the example above. If the keys were in the following 144files:</p> 145 146<pre> 147vendor/yoyodyne/security/tardis/releasekey.x509.pem 148vendor/yoyodyne/security/tardis/releasekey.pk8 149vendor/yoyodyne/security/tardis/platform.x509.pem 150vendor/yoyodyne/security/tardis/platform.pk8 151vendor/yoyodyne/security/tardis/shared.x509.pem 152vendor/yoyodyne/security/tardis/shared.pk8 153vendor/yoyodyne/security/tardis/media.x509.pem 154vendor/yoyodyne/security/tardis/media.pk8 155vendor/yoyodyne/security/special.x509.pem 156vendor/yoyodyne/security/special.pk8 # NOT password protected 157vendor/yoyodyne/security/special-release.x509.pem 158vendor/yoyodyne/security/special-release.pk8 # password protected 159</pre> 160 161<p>Then you would sign all the apps like this:</p> 162 163<pre> 164% <b>./build/tools/releasetools/sign_target_files_apks \ 165 -d vendor/yoyodyne/security/tardis \ 166 -k vendor/yoyodyne/special=vendor/yoyodyne/special-release \ 167 -o \ </b># explained in the next section<b> 168 tardis-target_files.zip signed-tardis-target_files.zip</b> 169Enter password for vendor/yoyodyne/security/special-release key> 170Enter password for vendor/yoyodyne/security/tardis/media key> 171Enter password for vendor/yoyodyne/security/tardis/platform key> 172Enter password for vendor/yoyodyne/security/tardis/releasekey key> 173Enter password for vendor/yoyodyne/security/tardis/shared key> 174 signing: Phone.apk (vendor/yoyodyne/security/tardis/platform) 175 signing: Camera.apk (vendor/yoyodyne/security/tardis/media) 176 signing: Special.apk (vendor/yoyodyne/security/special-release) 177 signing: Email.apk (vendor/yoyodyne/security/tardis/releasekey) 178 [...] 179 signing: ContactsProvider.apk (vendor/yoyodyne/security/tardis/shared) 180 signing: Launcher.apk (vendor/yoyodyne/security/tardis/shared) 181rewriting SYSTEM/build.prop: 182 replace: ro.build.description=tardis-user Eclair ERC91 15449 test-keys 183 with: ro.build.description=tardis-user Eclair ERC91 15449 release-keys 184 replace: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/test-keys 185 with: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/release-keys 186 signing: framework-res.apk (vendor/yoyodyne/security/tardis/platform) 187rewriting RECOVERY/RAMDISK/default.prop: 188 replace: ro.build.description=tardis-user Eclair ERC91 15449 test-keys 189 with: ro.build.description=tardis-user Eclair ERC91 15449 release-keys 190 replace: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/test-keys 191 with: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/release-keys 192using: 193 vendor/yoyodyne/security/tardis/releasekey.x509.pem 194for OTA package verification 195done. 196</pre> 197 198<p>After prompting the user for passwords for all password-protected keys, the 199script re-signs all the .apk files in the input target .zip with the release 200keys. Before running the command, you can also set the ANDROID_PW_FILE 201environment variable to a temporary filename; the script then invokes your 202editor to allow you to enter passwords for all keys (this may be a more 203convenient way to enter passwords).<p> 204<p><code>sign_target_files_apks</code> also rewrites the build description and 205fingerprint in the build properties files to reflect the fact that this is a 206signed build. The <code>-t</code> flag can control what edits are made to the 207fingerprint. Run the script with <code>-h</code> to see documentation on all 208flags.</p> 209 210<h2 id="sign-ota-packages">Signing OTA packages</h2> 211<p>You need the following components to sign OTA packages:</p> 212<ol> 213<li>Certificates of the keys you want this build to accept.</li> 214<li>Sign the newly-created package with the private key (must correspond to 215the certificate embedded in the current build of any device to which you want 216to send this package).</li> 217</ol> 218<p>To achieve these components:</p> 219<ul> 220<li>The target-files .zip produced by the build sets the OTA certificate to 221the certificate of the test key. Passing the <code>-o</code> flag to <code> 222sign_target_files_apks</code> replaces this key with the release key from your 223build.</li> 224<li>To sign the OTA update package, use the <code>-k</code> option when 225generating it to specify the key. You should give <code>ota_from_target_files 226</code> the <i>signed</i> version of the target-files .zip as well: 227<pre> 228% <b>./build/tools/releasetools/ota_from_target_files \ 229 -k vendor/yoyodyne/security/tardis/releasekey \ 230 signed-tardis-target_files.zip \ 231 signed-ota_update.zip</b> 232unzipping target target-files... 233(using device-specific extensions from target_files) 234Enter password for vendor/yoyodyne/security/tardis/releasekey key> 235done.</pre></li></ul> 236 237<h3 id="signatures-sideloading">Signatures and sideloading</h3> 238<p>Sideloading does not bypass recovery's normal package signature 239verification mechanism—before installing a package, recovery will verify that 240it is signed with one of the private keys matching the public keys stored in 241the recovery partition, just as it would for a package delivered over-the-air. 242</p> 243<p>Update packages received from the main system are typically verified twice: 244once by the main system, using the <code><a href="http://developer.android.com/ 245reference/android/os/RecoverySystem.html#verifyPackage">RecoverySystem. 246verifyPackage()</a></code> method in the android API, and then again by 247recovery. The RecoverySystem API checks the signature against public keys 248stored in the main system, in the file <code>/system/etc/security/otacerts.zip 249</code> (by default). Recovery checks the signature against public keys stored 250in the recovery partition RAM disk, in the file <code>/res/keys</code>.</p> 251<p>Normally these two locations store the same set of keys. By adding a key to 252<i>just</i> the recovery set of keys, it's possible to sign packages that can 253be installed only via sideloading (assuming the main system's update download 254mechanism is correctly doing verification against otacerts.zip). You can 255specify extra keys to be included only in recovery by setting the 256PRODUCT_EXTRA_RECOVERY_KEYS variable in your product definition:</p> 257 258<p><code>vendor/yoyodyne/tardis/products/tardis.mk</code></p> 259<pre> 260 [...] 261 262PRODUCT_EXTRA_RECOVERY_KEYS := vendor/yoyodyne/security/tardis/sideload 263</pre> 264 265<p>This includes the public key <code>vendor/yoyodyne/security/tardis/sideload. 266x509.pem</code> in the recovery keys file so it can install packages signed 267with it. The extra key is <i>not</i> included in otacerts.zip though, so 268systems that correctly verify downloaded packages do not invoke recovery for 269packages signed with this key.</p>