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 OS images use cryptographic signatures in two places:</p> 29 <ol> 30 <li>Each .apk file inside the image must be signed. Android's Package Manager 31 uses an .apk 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. This 34 holds true both for updating user apps by overwriting the .apk, and for 35 overriding a system app with a newer version installed under 36 <code>/data</code>.</li> 37 <li>If two or more applications want to share a user ID (so they can share 38 data, etc.), they must be signed with the same key.</ul></li> 39 <li>OTA update packages must be signed with one of the keys expected by the 40 system or the installation process will reject them.</ul></li> 41 </ol> 42 43 <h2 id="release-keys">Release keys</h2> 44 45 <p>The Android tree includes <i>test-keys</i> under 46 <code>build/target/product/security</code>. Building an Android OS image 47 using <code>make</code> will sign all .apk files using the test-keys. 48 Since the test-keys are publicly known, anybody can sign their own .apk files 49 with the same keys, which may allow them to replace or hijack system 50 apps built into your OS image. For this reason it is critical to sign any 51 publicly released or deployed Android OS image with a special set of 52 <i>release-keys</i> that only you have access to.</p> 53 54 <p>To generate your own unique set of release-keys, run these commands from 55 the root of your Android tree:</p> 56 57 <pre class="no-pretty-print"> 58 subject='/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android (a] android.com' 59 mkdir ~/.android-certs 60 for x in releasekey platform shared media; do \ 61 ./development/tools/make_key ~/.android-certs/$x "$subject"; \ 62 done 63 </pre> 64 65 <p><code>$subject</code> should be changed to reflect your organization's 66 information. You can use any directory, but be careful to pick a 67 location that is backed up and secure. Some vendors choose to encrypt 68 their private key with a strong passphrase and store the encrypted key 69 in source control; others store their release keys somewhere else entirely, 70 such as on an air-gapped computer.</p> 71 72 <p>To generate a release image, use:</p> 73 74 <pre class="no-pretty-print"> 75 make dist 76 ./build/tools/releasetools/sign_target_files_apks \ 77 -o \ # explained in the next section 78 -d ~/.android-certs out/dist/*-target_files-*.zip \ 79 signed-target_files.zip 80 </pre> 81 82 <p>The <code>sign_target_files_apks</code> script takes a target-files .zip 83 as input and produces a new target-files .zip in which all the .apks have 84 been signed with new keys. The newly signed images can be found under 85 <code>IMAGES/</code> in <code>signed-target_files.zip</code>.</p> 86 87 <h2 id="sign-ota-packages">Signing OTA packages</h2> 88 89 A signed target-files zip can be converted into a signed OTA update zip 90 using the following procedure: 91 92 <pre class="no-pretty-print"> 93 ./build/tools/releasetools/ota_from_target_files \ 94 -k ~/.android-certs/releasekey \ 95 signed-target_files.zip \ 96 signed-ota_update.zip 97 </pre> 98 99 <h3 id="signatures-sideloading">Signatures and sideloading</h3> 100 <p>Sideloading does not bypass recovery's normal package signature 101 verification mechanismbefore installing a package, recovery will verify that 102 it is signed with one of the private keys matching the public keys stored in 103 the recovery partition, just as it would for a package delivered over-the-air. 104 </p> 105 106 <p>Update packages received from the main system are typically verified twice: 107 once by the main system, using the 108 <code><a href="http://developer.android.com/reference/android/os/RecoverySystem.html#verifyPackage">RecoverySystem.verifyPackage()</a></code> 109 method in the android API, and then again by 110 recovery. The RecoverySystem API checks the signature against public keys 111 stored in the main system, in the file <code>/system/etc/security/otacerts.zip 112 </code> (by default). Recovery checks the signature against public keys stored 113 in the recovery partition RAM disk, in the file <code>/res/keys</code>.</p> 114 115 <p>By default, the target-files .zip produced by the build sets the OTA 116 certificate to match the test key. On a released image, a 117 different certificate must be used so that devices can verify the 118 authenticity of the update package. Passing the <code>-o</code> flag to 119 <code>sign_target_files_apks</code>, as shown in the previous section, replaces 120 the test key certificate with the release key certificate from your certs 121 directory.</p> 122 123 <p>Normally the system image and recovery image store the same set of OTA 124 public keys. By adding a key to <i>just</i> the recovery set of keys, it is 125 possible to sign packages that can be installed only via sideloading 126 (assuming the main system's update download mechanism is correctly doing 127 verification against otacerts.zip). You can specify extra keys to be 128 included only in recovery by setting the PRODUCT_EXTRA_RECOVERY_KEYS 129 variable in your product definition:</p> 130 131 <p><code>vendor/yoyodyne/tardis/products/tardis.mk</code></p> 132 <pre class="no-pretty-print"> 133 [...] 134 135 PRODUCT_EXTRA_RECOVERY_KEYS := vendor/yoyodyne/security/tardis/sideload 136 </pre> 137 138 <p>This includes the public key 139 <code>vendor/yoyodyne/security/tardis/sideload.x509.pem</code> in the recovery 140 keys file so it can install packages signed 141 with it. The extra key is <i>not</i> included in otacerts.zip though, so 142 systems that correctly verify downloaded packages do not invoke recovery for 143 packages signed with this key.</p> 144 145 <h2 id="certificates-keys">Certificates and private keys</h2> 146 <p>Each key comes in two files: the <i>certificate</i>, which has the 147 extension .x509.pem, and the <i>private key</i>, which has the extension .pk8. 148 The private key should be kept secret and is needed to sign a package. The key 149 may itself be protected by a password. The certificate, in 150 contrast, contains only the public half of the key, so it can be distributed 151 widely. It is used to verify a package has been signed by the corresponding 152 private key.</p> 153 <p>The standard Android build uses four keys, all of which reside in <code> 154 build/target/product/security</code>:</p> 155 156 <dl> 157 <dt>testkey</dt> 158 <dd>Generic default key for packages that do not otherwise specify a key.</dd> 159 <dt>platform</dt> 160 <dd>Test key for packages that are part of the core platform.</dd> 161 <dt>shared</dt> 162 <dd>Test key for things that are shared in the home/contacts process.</dd> 163 <dt>media</dt> 164 <dd>Test key for packages that are part of the media/download system.</dd></dl> 165 166 <p>Individual packages specify one of these keys by setting LOCAL_CERTIFICATE 167 in their Android.mk file. (testkey is used if this variable is not set.) You 168 can also specify an entirely different key by pathname, e.g.:</p> 169 170 <p><code>device/yoyodyne/apps/SpecialApp/Android.mk</code></p> 171 <pre class="no-pretty-print"> 172 [...] 173 174 LOCAL_CERTIFICATE := device/yoyodyne/security/special 175 </pre> 176 177 <p>Now the build uses the <code>device/yoyodyne/security/special.{x509.pem,pk8} 178 </code> key to sign SpecialApp.apk. The build can use only private keys that 179 are <i>not </i>password protected.</p> 180 181 <h2 id="advanced-signing-options">Advanced signing options</h2> 182 <p>When you run the <code>sign_target_files_apks</code> script, you must 183 specify on the command line a replacement key for each key used in the build. 184 The <code>-k <i>src_key</i>=<i> 185 dest_key</i></code> flag specifies key replacements one at a time. The flag 186 <code>-d <i>dir</i></code> lets you specify a directory with four keys to 187 replace all those in <code>build/target/product/security</code>; it is 188 equivalent to using <code>-k</code> four times to specify the mappings:</p> 189 190 <pre class="no-pretty-print"> 191 build/target/product/security/testkey = dir/releasekey 192 build/target/product/security/platform = dir/platform 193 build/target/product/security/shared = dir/shared 194 build/target/product/security/media = dir/media 195 </pre> 196 197 <p>For the hypothetical tardis product, you need five password-protected keys: 198 four to replace the four in <code>build/target/product/security</code>, and 199 one to replace the additional <code>keydevice/yoyodyne/security/special</code> 200 required by SpecialApp in the example above. If the keys were in the following 201 files:</p> 202 203 <pre class="no-pretty-print"> 204 vendor/yoyodyne/security/tardis/releasekey.x509.pem 205 vendor/yoyodyne/security/tardis/releasekey.pk8 206 vendor/yoyodyne/security/tardis/platform.x509.pem 207 vendor/yoyodyne/security/tardis/platform.pk8 208 vendor/yoyodyne/security/tardis/shared.x509.pem 209 vendor/yoyodyne/security/tardis/shared.pk8 210 vendor/yoyodyne/security/tardis/media.x509.pem 211 vendor/yoyodyne/security/tardis/media.pk8 212 vendor/yoyodyne/security/special.x509.pem 213 vendor/yoyodyne/security/special.pk8 # NOT password protected 214 vendor/yoyodyne/security/special-release.x509.pem 215 vendor/yoyodyne/security/special-release.pk8 # password protected 216 </pre> 217 218 <p>Then you would sign all the apps like this:</p> 219 220 <pre class="no-pretty-print"> 221 % <b>./build/tools/releasetools/sign_target_files_apks \ 222 -d vendor/yoyodyne/security/tardis \ 223 -k vendor/yoyodyne/special=vendor/yoyodyne/special-release \ 224 -o \ 225 tardis-target_files.zip signed-tardis-target_files.zip</b> 226 Enter password for vendor/yoyodyne/security/special-release key> 227 Enter password for vendor/yoyodyne/security/tardis/media key> 228 Enter password for vendor/yoyodyne/security/tardis/platform key> 229 Enter password for vendor/yoyodyne/security/tardis/releasekey key> 230 Enter password for vendor/yoyodyne/security/tardis/shared key> 231 signing: Phone.apk (vendor/yoyodyne/security/tardis/platform) 232 signing: Camera.apk (vendor/yoyodyne/security/tardis/media) 233 signing: Special.apk (vendor/yoyodyne/security/special-release) 234 signing: Email.apk (vendor/yoyodyne/security/tardis/releasekey) 235 [...] 236 signing: ContactsProvider.apk (vendor/yoyodyne/security/tardis/shared) 237 signing: Launcher.apk (vendor/yoyodyne/security/tardis/shared) 238 rewriting SYSTEM/build.prop: 239 replace: ro.build.description=tardis-user Eclair ERC91 15449 test-keys 240 with: ro.build.description=tardis-user Eclair ERC91 15449 release-keys 241 replace: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/test-keys 242 with: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/release-keys 243 signing: framework-res.apk (vendor/yoyodyne/security/tardis/platform) 244 rewriting RECOVERY/RAMDISK/default.prop: 245 replace: ro.build.description=tardis-user Eclair ERC91 15449 test-keys 246 with: ro.build.description=tardis-user Eclair ERC91 15449 release-keys 247 replace: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/test-keys 248 with: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/release-keys 249 using: 250 vendor/yoyodyne/security/tardis/releasekey.x509.pem 251 for OTA package verification 252 done. 253 </pre> 254 255 <p>After prompting the user for passwords for all password-protected keys, the 256 script re-signs all the .apk files in the input target .zip with the release 257 keys. Before running the command, you can also set the ANDROID_PW_FILE 258 environment variable to a temporary filename; the script then invokes your 259 editor to allow you to enter passwords for all keys (this may be a more 260 convenient way to enter passwords).<p> 261 <p><code>sign_target_files_apks</code> also rewrites the build description and 262 fingerprint in the build properties files to reflect the fact that this is a 263 signed build. The <code>-t</code> flag can control what edits are made to the 264 fingerprint. Run the script with <code>-h</code> to see documentation on all 265 flags.</p> 266 267 <h2 id="manually-generating-keys">Manually generating keys</h2> 268 <p>Android uses 2048-bit RSA keys with public exponent 3. You can generate 269 certificate/private key pairs using the openssl tool from 270 <a href="http://www.openssl.org/">openssl.org</a>:</p> 271 272 <pre class="no-pretty-print"> 273 # generate RSA key 274 % <b>openssl genrsa -3 -out temp.pem 2048</b> 275 Generating RSA private key, 2048 bit long modulus 276 ....+++ 277 .....................+++ 278 e is 3 (0x3) 279 280 # create a certificate with the public part of the key 281 % <b>openssl req -new -x509 -key temp.pem -out releasekey.x509.pem \ 282 -days 10000 \ 283 -subj '/C=US/ST=California/L=San Narciso/O=Yoyodyne, Inc./OU=Yoyodyne Mobility/CN=Yoyodyne/emailAddress=yoyodyne (a] example.com'</b> 284 285 # create a PKCS#8-formatted version of the private key 286 % <b>openssl pkcs8 -in temp.pem -topk8 -outform DER -out releasekey.pk8 -nocrypt</b> 287 288 # securely delete the temp.pem file 289 % <b>shred --remove temp.pem</b> 290 </pre> 291 292 <p>The openssl pkcs8 command given above creates a .pk8 file with <i>no</i> 293 password, suitable for use with the build system. To create a .pk8 secured 294 with a password (which you should do for all actual release keys), replace the 295 <code>-nocrypt</code> argument with <code>-passout stdin</code>; then openssl 296 will encrypt the private key with a password read from standard input. No 297 prompt is printed, so if stdin is the terminal the program will appear to hang 298 when it's really just waiting for you to enter a password. Other values can be 299 used for the-passout argument to read the password from other locations; for 300 details, see the 301 <a href="http://www.openssl.org/docs/apps/openssl.html#PASS_PHRASE_ARGUMENTS"> 302 openssl documentation</a>.</p> 303 <p>The temp.pem intermediate file contains the private key without any kind of 304 password protection, so dispose of it thoughtfully when generating release 305 keys. In particular, the GNUshred utility may not be effective on network or 306 journaled filesystems. You can use a working directory located in a RAM disk 307 (such as a tmpfs partition) when generating keys to ensure the intermediates 308 are not inadvertently exposed.</p> 309 310 <h2 id="creating-image-files">Creating image files</h2> 311 312 <p> 313 Once you have signed-target-files.zip, you need to 314 create the image so you can put it onto a device. 315 To create the signed image from the target files, run 316 the following command from the root of the Android 317 tree: 318 </p> 319 320 <pre> 321 ./build/tools/releasetools/img_from_target_files signed-target-files.zip signed-img.zip 322 </pre> 323 324 The resulting file, <code>signed-img.zip</code>, contains all the .img files. 325 326 To load an image onto a device, use fastboot as 327 follows: 328 329 <pre> 330 fastboot update signed-img.zip 331 </pre> 332