1 page.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 31 signature in two ways:<ul> 32 <li>When an application is replaced, it must be signed by the same key as the 33 old 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 35 data, 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 37 system 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 41 extension .x509.pem, and the <i>private key</i>, which has the extension .pk8. 42 The private key should be kept secret and is needed to sign a package. The key 43 may itself be protected by a passworda reasonable strategy is to store your 44 keys in source control along with the codebut keep them protected by a 45 password known only to the people who make final releases. The certificate, in 46 contrast, contains only the public half of the key, so it can be distributed 47 widely. It is used to verify a package has been signed by the corresponding 48 private key.</p> 49 <p>The standard Android build uses four keys, all of which reside in <code> 50 build/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 63 in their Android.mk file. (testkey is used if this variable is not set.) You 64 can 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 70 LOCAL_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 75 are <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 79 certificate/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> 85 Generating RSA private key, 2048 bit long modulus 86 ....+++ 87 .....................+++ 88 e 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 (a] 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> 103 password, suitable for use with the build system. To create a .pk8 secured 104 with 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 106 will encrypt the private key with a password read from standard input. No 107 prompt is printed, so if stdin is the terminal the program will appear to hang 108 when it's really just waiting for you to enter a password. Other values can be 109 used for the-passout argument to read the password from other locations; for 110 details, see the 111 <a href="http://www.openssl.org/docs/apps/openssl.html#PASS_PHRASE_ARGUMENTS"> 112 openssl documentation</a>.</p> 113 <p>The temp.pem intermediate file contains the private key without any kind of 114 password protection, so dispose of it thoughtfully when generating release 115 keys. In particular, the GNUshred utility may not be effective on network or 116 journaled 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 118 are 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 122 files in it, replacing the test keys used by the build system. This is done 123 with 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 125 been signed with new keys.</p> 126 <p>When you run this script, you must specify on the command line a 127 replacement key for each key used in the build. The <code>-k <i>src_key</i>=<i> 128 dest_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 130 replace all those in <code>build/target/product/security</code>; it is 131 equivalent to using <code>-k</code> four times to specify the mappings:</p> 132 133 <pre> 134 build/target/product/security/testkey = dir/releasekey 135 build/target/product/security/platform = dir/platform 136 build/target/product/security/shared = dir/shared 137 build/target/product/security/media = dir/media 138 </pre> 139 140 <p>For the hypothetical tardis product, you need five password-protected keys: 141 four to replace the four in <code>build/target/product/security</code>, and 142 one to replace the additional <code>keydevice/yoyodyne/security/special</code> 143 required by SpecialApp in the example above. If the keys were in the following 144 files:</p> 145 146 <pre> 147 vendor/yoyodyne/security/tardis/releasekey.x509.pem 148 vendor/yoyodyne/security/tardis/releasekey.pk8 149 vendor/yoyodyne/security/tardis/platform.x509.pem 150 vendor/yoyodyne/security/tardis/platform.pk8 151 vendor/yoyodyne/security/tardis/shared.x509.pem 152 vendor/yoyodyne/security/tardis/shared.pk8 153 vendor/yoyodyne/security/tardis/media.x509.pem 154 vendor/yoyodyne/security/tardis/media.pk8 155 vendor/yoyodyne/security/special.x509.pem 156 vendor/yoyodyne/security/special.pk8 # NOT password protected 157 vendor/yoyodyne/security/special-release.x509.pem 158 vendor/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> 169 Enter password for vendor/yoyodyne/security/special-release key> 170 Enter password for vendor/yoyodyne/security/tardis/media key> 171 Enter password for vendor/yoyodyne/security/tardis/platform key> 172 Enter password for vendor/yoyodyne/security/tardis/releasekey key> 173 Enter 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) 181 rewriting 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) 187 rewriting 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 192 using: 193 vendor/yoyodyne/security/tardis/releasekey.x509.pem 194 for OTA package verification 195 done. 196 </pre> 197 198 <p>After prompting the user for passwords for all password-protected keys, the 199 script re-signs all the .apk files in the input target .zip with the release 200 keys. Before running the command, you can also set the ANDROID_PW_FILE 201 environment variable to a temporary filename; the script then invokes your 202 editor to allow you to enter passwords for all keys (this may be a more 203 convenient way to enter passwords).<p> 204 <p><code>sign_target_files_apks</code> also rewrites the build description and 205 fingerprint in the build properties files to reflect the fact that this is a 206 signed build. The <code>-t</code> flag can control what edits are made to the 207 fingerprint. Run the script with <code>-h</code> to see documentation on all 208 flags.</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 215 the certificate embedded in the current build of any device to which you want 216 to 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 221 the certificate of the test key. Passing the <code>-o</code> flag to <code> 222 sign_target_files_apks</code> replaces this key with the release key from your 223 build.</li> 224 <li>To sign the OTA update package, use the <code>-k</code> option when 225 generating 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> 232 unzipping target target-files... 233 (using device-specific extensions from target_files) 234 Enter password for vendor/yoyodyne/security/tardis/releasekey key> 235 done.</pre></li></ul> 236 237 <h3 id="signatures-sideloading">Signatures and sideloading</h3> 238 <p>Sideloading does not bypass recovery's normal package signature 239 verification mechanismbefore installing a package, recovery will verify that 240 it is signed with one of the private keys matching the public keys stored in 241 the 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: 244 once by the main system, using the <code><a href="http://developer.android.com/ 245 reference/android/os/RecoverySystem.html#verifyPackage">RecoverySystem. 246 verifyPackage()</a></code> method in the android API, and then again by 247 recovery. The RecoverySystem API checks the signature against public keys 248 stored 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 250 in 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 253 be installed only via sideloading (assuming the main system's update download 254 mechanism is correctly doing verification against otacerts.zip). You can 255 specify extra keys to be included only in recovery by setting the 256 PRODUCT_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 262 PRODUCT_EXTRA_RECOVERY_KEYS := vendor/yoyodyne/security/tardis/sideload 263 </pre> 264 265 <p>This includes the public key <code>vendor/yoyodyne/security/tardis/sideload. 266 x509.pem</code> in the recovery keys file so it can install packages signed 267 with it. The extra key is <i>not</i> included in otacerts.zip though, so 268 systems that correctly verify downloaded packages do not invoke recovery for 269 packages signed with this key.</p>