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 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
31uses an .apk signature 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. This
34holds true both for updating user apps by overwriting the .apk, and for
35overriding 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
38data, 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
40system 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
47using <code>make</code> will sign all .apk files using the test-keys.
48Since the test-keys are publicly known, anybody can sign their own .apk files
49with the same keys, which may allow them to replace or hijack system
50apps built into your OS image. For this reason it is critical to sign any
51publicly 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
55the root of your Android tree:</p>
56
57<pre class="no-pretty-print">
58subject='/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
59mkdir ~/.android-certs
60for x in releasekey platform shared media; do \
61    ./development/tools/make_key ~/.android-certs/$x "$subject"; \
62done
63</pre>
64
65<p><code>$subject</code> should be changed to reflect your organization's
66information. You can use any directory, but be careful to pick a
67location that is backed up and secure. Some vendors choose to encrypt
68their private key with a strong passphrase and store the encrypted key
69in source control; others store their release keys somewhere else entirely,
70such as on an air-gapped computer.</p>
71
72<p>To generate a release image, use:</p>
73
74<pre class="no-pretty-print">
75make 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
83as input and produces a new target-files .zip in which all the .apks have
84been 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
89A signed target-files zip can be converted into a signed OTA update zip
90using 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
101verification mechanism—before installing a package, recovery will verify that
102it is signed with one of the private keys matching the public keys stored in
103the 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:
107once by the main system, using the
108<code><a href="http://developer.android.com/reference/android/os/RecoverySystem.html#verifyPackage">RecoverySystem.verifyPackage()</a></code>
109method in the android API, and then again by
110recovery. The RecoverySystem API checks the signature against public keys
111stored 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
113in 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
116certificate to match the test key. On a released image, a
117different certificate must be used so that devices can verify the
118authenticity 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
120the test key certificate with the release key certificate from your certs
121directory.</p>
122
123<p>Normally the system image and recovery image store the same set of OTA
124public keys.  By adding a key to <i>just</i> the recovery set of keys, it is
125possible to sign packages that can be installed only via sideloading
126(assuming the main system's update download mechanism is correctly doing
127verification against otacerts.zip). You can specify extra keys to be
128included only in recovery by setting the PRODUCT_EXTRA_RECOVERY_KEYS
129variable 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
135PRODUCT_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
140keys file so it can install packages signed
141with it. The extra key is <i>not</i> included in otacerts.zip though, so
142systems that correctly verify downloaded packages do not invoke recovery for
143packages 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
147extension .x509.pem, and the <i>private key</i>, which has the extension .pk8.
148The private key should be kept secret and is needed to sign a package. The key
149may itself be protected by a password. The certificate, in
150contrast, contains only the public half of the key, so it can be distributed
151widely. It is used to verify a package has been signed by the corresponding
152private key.</p>
153<p>The standard Android build uses four keys, all of which reside in <code>
154build/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
167in their Android.mk file. (testkey is used if this variable is not set.) You
168can 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
174LOCAL_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
179are <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
183specify on the command line a replacement key for each key used in the build.
184The <code>-k <i>src_key</i>=<i>
185dest_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
187replace all those in <code>build/target/product/security</code>; it is
188equivalent to using <code>-k</code> four times to specify the mappings:</p>
189
190<pre class="no-pretty-print">
191build/target/product/security/testkey  = dir/releasekey
192build/target/product/security/platform = dir/platform
193build/target/product/security/shared   = dir/shared
194build/target/product/security/media    = dir/media
195</pre>
196
197<p>For the hypothetical tardis product, you need five password-protected keys:
198four to replace the four in <code>build/target/product/security</code>, and
199one to replace the additional <code>keydevice/yoyodyne/security/special</code>
200required by SpecialApp in the example above. If the keys were in the following
201files:</p>
202
203<pre class="no-pretty-print">
204vendor/yoyodyne/security/tardis/releasekey.x509.pem
205vendor/yoyodyne/security/tardis/releasekey.pk8
206vendor/yoyodyne/security/tardis/platform.x509.pem
207vendor/yoyodyne/security/tardis/platform.pk8
208vendor/yoyodyne/security/tardis/shared.x509.pem
209vendor/yoyodyne/security/tardis/shared.pk8
210vendor/yoyodyne/security/tardis/media.x509.pem
211vendor/yoyodyne/security/tardis/media.pk8
212vendor/yoyodyne/security/special.x509.pem
213vendor/yoyodyne/security/special.pk8           # NOT password protected
214vendor/yoyodyne/security/special-release.x509.pem
215vendor/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>
226Enter password for vendor/yoyodyne/security/special-release key&gt;
227Enter password for vendor/yoyodyne/security/tardis/media key&gt;
228Enter password for vendor/yoyodyne/security/tardis/platform key&gt;
229Enter password for vendor/yoyodyne/security/tardis/releasekey key&gt;
230Enter password for vendor/yoyodyne/security/tardis/shared key&gt;
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)
238rewriting 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)
244rewriting 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
249using:
250    vendor/yoyodyne/security/tardis/releasekey.x509.pem
251for OTA package verification
252done.
253</pre>
254
255<p>After prompting the user for passwords for all password-protected keys, the
256script re-signs all the .apk files in the input target .zip with the release
257keys. Before running the command, you can also set the ANDROID_PW_FILE
258environment variable to a temporary filename; the script then invokes your
259editor to allow you to enter passwords for all keys (this may be a more
260convenient way to enter passwords).<p>
261<p><code>sign_target_files_apks</code> also rewrites the build description and
262fingerprint in the build properties files to reflect the fact that this is a
263signed build. The <code>-t</code> flag can control what edits are made to the
264fingerprint. Run the script with <code>-h</code> to see documentation on all
265flags.</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
269certificate/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>
275Generating RSA private key, 2048 bit long modulus
276....+++
277.....................+++
278e 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@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>
293password, suitable for use with the build system. To create a .pk8 secured
294with 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
296will encrypt the private key with a password read from standard input. No
297prompt is printed, so if stdin is the terminal the program will appear to hang
298when it's really just waiting for you to enter a password. Other values can be
299used for the-passout argument to read the password from other locations; for
300details, see the
301<a href="http://www.openssl.org/docs/apps/openssl.html#PASS_PHRASE_ARGUMENTS">
302openssl documentation</a>.</p>
303<p>The temp.pem intermediate file contains the private key without any kind of
304password protection, so dispose of it thoughtfully when generating release
305keys. In particular, the GNUshred utility may not be effective on network or
306journaled 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
308are not inadvertently exposed.</p>
309
310<h2 id="creating-image-files">Creating image files</h2>
311
312<p>
313Once you have signed-target-files.zip, you need to
314create the image so you can put it onto a device.
315To create the signed image from the target files, run
316the following command from the root of the Android
317tree:
318</p>
319
320<pre>
321./build/tools/releasetools/img_from_target_files signed-target-files.zip signed-img.zip
322</pre>
323
324The resulting file, <code>signed-img.zip</code>, contains all the .img files.
325
326To load an image onto a device, use fastboot as
327follows:
328
329<pre>
330fastboot update signed-img.zip
331</pre>
332