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&gt;
170Enter password for vendor/yoyodyne/security/tardis/media key&gt;
171Enter password for vendor/yoyodyne/security/tardis/platform key&gt;
172Enter password for vendor/yoyodyne/security/tardis/releasekey key&gt;
173Enter password for vendor/yoyodyne/security/tardis/shared key&gt;
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&gt;
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>