| page.title=APK Signature Scheme v2 |
| @jd:body |
| |
| <!-- |
| Copyright 2016 The Android Open Source Project |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| <div id="qv-wrapper"> |
| <div id="qv"> |
| <h2>In this document</h2> |
| <ol id="auto-toc"> |
| </ol> |
| </div> |
| </div> |
| |
| <p> |
| APK Signature Scheme v2 is a whole-file signature scheme that increases |
| verification speed and <a |
| href="#integrity-protected-contents">strengthens integrity guarantees</a> by |
| detecting any changes to the protected parts of the APK. |
| </p> |
| |
| <p> |
| Signing using APK Signature Scheme v2 inserts an <a |
| href="#apk-signing-block">APK Signing Block</a> into the APK file immediately |
| before the ZIP Central Directory section. Inside the APK Signing Block, v2 |
| signatures and signer identity information are stored in an <a |
| href="#apk-signature-scheme-v2-block">APK Signature Scheme v2 Block</a>. |
| </p> |
| |
| <p> |
| <img src="../images/apk-before-after-signing.png" alt="APK before and after signing" id="figure1" /> |
| </p> |
| <p class="img-caption"><strong>Figure 1.</strong> APK before and after signing</p> |
| |
| <p> |
| APK Signature Scheme v2 was introduced in Android 7.0 (Nougat). To make |
| a APK installable on Android 6.0 (Marshmallow) and older devices, the |
| APK should be signed using <a href="index.html#v1">JAR signing</a> before being |
| signed with the v2 scheme. |
| </p> |
| |
| |
| <h2 id="apk-signing-block">APK Signing Block</h2> |
| <p> |
| To maintain backward-compatibility with the current APK format, v2 and newer APK |
| signatures are stored inside an APK Signing Block, a new container introduced to |
| support APK Signature Scheme v2. In an APK file, the APK Signing Block is located |
| immediately before the ZIP Central Directory, which is located at the end of the file. |
| </p> |
| |
| <p> |
| The block contains ID-value pairs wrapped in a way that makes it easier to |
| locate the block in the APK. The v2 signature of the APK is stored as an ID-value |
| pair with ID 0x7109871a. |
| </p> |
| |
| <h3 id="apk-signing-block-format">Format</h3> |
| <p> |
| The format of the APK Signing Block is as follows (all numeric fields are |
| little-endian): |
| </p> |
| |
| <ul> |
| <li><code>size of block</code> in bytes (excluding this field) (uint64)</li> |
| <li>Sequence of uint64-length-prefixed ID-value pairs: |
| <ul> |
| <li><code>ID</code> (uint32)</li> |
| <li><code>value</code> (variable-length: length of the pair - 4 bytes)</li> |
| </ul> |
| </li> |
| <li><code>size of block</code> in bytes—same as the very first field (uint64)</li> |
| <li><code>magic</code> “APK Sig Block 42” (16 bytes)</li> |
| </ul> |
| |
| <p> |
| APK is parsed by first finding the start of the ZIP Central Directory (by |
| finding the ZIP End of Central Directory record at the end of the file, then |
| reading the start offset of the Central Directory from the record). The |
| <code>magic</code> value provides a quick way to establish that what precedes |
| Central Directory is likely the APK Signing Block. The <code>size of |
| block</code> value then efficiently points to the start of the block in the |
| file. |
| </p> |
| |
| <p> |
| ID-value pairs with unknown IDs should be ignored when interpreting the |
| block. |
| </p> |
| |
| |
| <h2 id="apk-signature-scheme-v2-block">APK Signature Scheme v2 Block</h2> |
| <p> |
| APK is signed by one or more signers/identities, each represented by a signing |
| key. This information is stored as an APK Signature Scheme v2 Block. For each |
| signer, the following information is stored: |
| </p> |
| |
| <ul> |
| <li>(signature algorithm, digest, signature) tuples. The digest is stored to |
| decouple signature verification from integrity checking of the APK’s contents.</li> |
| <li>X.509 certificate chain representing the signer’s identity.</li> |
| <li>Additional attributes as key-value pairs.</li> |
| </ul> |
| |
| <p> |
| For each signer, the APK is verified using a supported signature from the |
| provided list. Signatures with unknown signature algorithms are ignored. It is |
| up to each implementation to choose which signature to use when multiple |
| supported signatures are encountered. This enables the introduction of stronger |
| signing methods in the future in a backward-compatible way. The suggested |
| approach is to verify the strongest signature. |
| </p> |
| |
| <h3 id="apk-signature-scheme-v2-block-format">Format</h3> |
| <p> |
| APK Signature Scheme v2 Block is stored inside the APK Signing Block under ID |
| <code>0x7109871a</code>. |
| </p> |
| |
| <p> |
| The format of the APK Signature Scheme v2 Block is as follows (all numeric |
| values are little-endian, all length-prefixed fields use uint32 for length): |
| </p> |
| <ul> |
| <li>length-prefixed sequence of length-prefixed <code>signer</code>: |
| <ul> |
| <li>length-prefixed <code>signed data</code>: |
| <ul> |
| <li>length-prefixed sequence of length-prefixed <code>digests</code>: |
| <ul> |
| <li><code>signature algorithm ID</code> (uint32)</li> |
| <li>(length-prefixed) <code>digest</code>—see |
| <a href="#integrity-protected-contents">Integrity-protected Contents</a></li> |
| </ul> |
| </li> |
| <li>length-prefixed sequence of X.509 <code>certificates</code>: |
| <ul> |
| <li>length-prefixed X.509 <code>certificate</code> (ASN.1 DER form)</li> |
| </ul> |
| </li> |
| <li>length-prefixed sequence of length-prefixed <code>additional attributes</code>: |
| <ul> |
| <li><code>ID</code> (uint32)</li> |
| <li><code>value</code> (variable-length: length of the additional |
| attribute - 4 bytes)</li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| <li>length-prefixed sequence of length-prefixed <code>signatures</code>: |
| <ul> |
| <li><code>signature algorithm ID</code> (uint32)</li> |
| <li>length-prefixed <code>signature</code> over <code>signed data</code></li> |
| </ul> |
| </li> |
| <li>length-prefixed <code>public key</code> (SubjectPublicKeyInfo, ASN.1 DER form)</li> |
| </ul> |
| </li> |
| </ul> |
| |
| <h4 id="signature-algorithm-ids">Signature Algorithm IDs</h4> |
| <ul> |
| <li>0x0101—RSASSA-PSS with SHA2-256 digest, SHA2-256 MGF1, 32 bytes of salt, |
| trailer: 0xbc</li> |
| <li>0x0102—RSASSA-PSS with SHA2-512 digest, SHA2-512 MGF1, 64 bytes of salt, |
| trailer: 0xbc</li> |
| <li>0x0103—RSASSA-PKCS1-v1_5 with SHA2-256 digest. This is for build systems |
| which require deterministic signatures.</li> |
| <li>0x0104—RSASSA-PKCS1-v1_5 with SHA2-512 digest. This is for build systems |
| which require deterministic signatures.</li> |
| <li>0x0201—ECDSA with SHA2-256 digest</li> |
| <li>0x0202—ECDSA with SHA2-512 digest</li> |
| <li>0x0301—DSA with SHA2-256 digest</li> |
| </ul> |
| |
| <p> |
| All of the above signature algorithms are supported by the Android platform. |
| Signing tools may support a subset of the algorithms. |
| </p> |
| |
| <p> |
| <strong>Supported keys sizes and EC curves:</strong> |
| </p> |
| |
| <ul> |
| <li>RSA: 1024, 2048, 4096, 8192, 16384</li> |
| <li>EC: NIST P-256, P-384, P-521</li> |
| <li>DSA: 1024, 2048, 3072</li> |
| </ul> |
| |
| <h2 id="integrity-protected-contents">Integrity-protected contents</h2> |
| |
| <p> |
| For the purposes of protecting APK contents, an APK consists of four sections: |
| </p> |
| |
| <ol> |
| <li>Contents of ZIP entries (from offset 0 until the start of APK Signing Block)</li> |
| <li>APK Signing Block</li> |
| <li>ZIP Central Directory</li> |
| <li>ZIP End of Central Directory</li> |
| </ol> |
| |
| <p> |
| <img src="../images/apk-sections.png" alt="APK sections after signing" id="figure2" /> |
| </p> |
| <p class="img-caption"><strong>Figure 2.</strong> APK sections after signing</p> |
| |
| <p> |
| APK Signature Scheme v2 protects the integrity of sections 1, 3, 4, and the |
| <code>signed data</code> blocks of the APK Signature Scheme v2 Block contained |
| inside section 2. |
| </p> |
| |
| <p> |
| The integrity of sections 1, 3, and 4 is protected by one or more digests of |
| their contents stored in <code>signed data</code> blocks which are, in |
| turn, protected by one or more signatures. |
| </p> |
| |
| <p> |
| The digest over sections 1, 3, and 4 is computed as follows, similar to a |
| two-level <a href="https://en.wikipedia.org/wiki/Merkle_tree">Merkle tree</a>. |
| Each section is split into consecutive 1 MB (2<sup>20</sup> bytes) chunks. The last chunk |
| in each section may be shorter. The digest of each chunk is computed over the |
| concatenation of byte <code>0xa5</code>, the chunk’s length in bytes |
| (little-endian uint32), and the chunk’s contents. The top-level digest is |
| computed over the concatenation of byte <code>0x5a</code>, the number of chunks |
| (little-endian uint32), and the concatenation of digests of the chunks in the |
| order the chunks appear in the APK. The digest is computed in chunked fashion to |
| enable to speed up the computation by parallelizing it. |
| </p> |
| |
| <p> |
| <img src="../images/apk-integrity-protection.png" alt="APK digest" id="figure3" /> |
| </p> |
| <p class="img-caption"><strong>Figure 3.</strong> APK digest</p> |
| |
| <p> |
| Protection of section 4 (ZIP End of Central Directory) is complicated by the |
| section containing the offset of ZIP Central Directory. The offset changes when |
| the size of the APK Signing Block changes, for instance, when a new signature is |
| added. Thus, when computing digest over the ZIP End of Central Directory, the |
| field containing the offset of ZIP Central Directory must be treated as |
| containing the offset of the APK Signing Block. |
| </p> |
| |
| <h2 id="rollback-protections">Rollback Protections</h2> |
| <p> |
| An attacker could attempt to have a v2-signed APK verified as a v1-signed APK on |
| Android platforms that support verifying v2-signed APK. To mitigate this attack, |
| v2-signed APKs that are also v1-signed must contain an X-Android-APK-Signed |
| attribute in the main section of their META-INF/*.SF files. The value of the |
| attribute is a comma-separated set of APK signature scheme IDs (the ID of this |
| scheme is 2). When verifying the v1 signature, APK verifier is required to |
| reject APKs which do not have a signature for the APK signature scheme the |
| verifier prefers from this set (e.g., v2 scheme). This protection relies on the |
| fact that contents META-INF/*.SF files are protected by v1 signatures. See the |
| section on |
| <a href="#v1-verification">JAR signed APK verification</a>. |
| </p> |
| |
| <p> |
| An attacker could attempt to strip stronger signatures from the APK Signature |
| Scheme v2 Block. To mitigate this attack, the list of signature algorithm IDs |
| with which the APK was being signed is stored in the <code>signed data</code> |
| block which is protected by each signature. |
| </p> |
| |
| <h2 id="verification">Verification</h2> |
| |
| In Android 7.0, APKs can be verified according to the APK Signature Scheme v2 |
| (v2 scheme) or JAR signing (v1 scheme). Older platforms ignore v2 signatures |
| and only verify v1 signatures. |
| </p> |
| |
| <p> |
| <img src="../images/apk-validation-process.png" alt="APK signature verification process" id="figure4" /> |
| </p> |
| <p class="img-caption"><strong>Figure 4.</strong> APK signature verification |
| process (new steps in red)</p> |
| |
| <h3 id="v2-verification">APK Signature Scheme v2 verification</h3> |
| <ol> |
| <li>Locate the APK Signing Block and verify that: |
| <ol> |
| <li>Two size fields of APK Signing Block contain the same value.</li> |
| <li>ZIP Central Directory is immediately followed by ZIP End of Central |
| Directory record.</li> |
| <li>ZIP End of Central Directory is not followed by more data.</li> |
| </ol> |
| </li> |
| <li>Locate the first APK Signature Scheme v2 Block inside the APK Signing Block. |
| If the v2 Block if present, proceed to step 3. Otherwise, fall back to |
| verifying the APK |
| <a href="#v1-verification">using v1 scheme</a>.</li> |
| <li>For each <code>signer</code> in the APK Signature Scheme v2 Block: |
| <ol> |
| <li>Choose the strongest supported <code>signature algorithm ID</code> from |
| <code>signatures</code>. The strength ordering is up to each |
| implementation/platform version.</li> |
| <li>Verify the corresponding <code>signature</code> from |
| <code>signatures</code> against <code>signed data</code> using <code>public |
| key</code>. (It is now safe to parse <code>signed data</code>.)</li> |
| <li>Verify that the ordered list of signature algorithm IDs in |
| <code>digests</code> and <code>signatures</code> is identical. (This is to |
| prevent signature stripping/addition.)</li> |
| <li><a href="#integrity-protected-contents">Compute the digest of APK |
| contents</a> using the same digest algorithm as the digest algorithm used by the |
| signature algorithm.</li> |
| <li>Verify that the computed digest is identical to the corresponding |
| <code>digest</code> from <code>digests</code>.</li> |
| <li>Verify that SubjectPublicKeyInfo of the first <code>certificate</code> of |
| <code>certificates</code> is identical to <code>public key</code>.</li> |
| </ol> |
| </li> |
| <li>Verification succeeds if at least one <code>signer</code> was found and |
| step 3 succeeded for each found <code>signer</code>.</li> |
| </ol> |
| |
| <p class="note"><strong>Note</strong>: APK must not be verified using |
| the v1 scheme if a failure occurs in step 3 or 4. |
| </p> |
| |
| <h3 id="v1-verification">JAR-signed APK verification (v1 scheme)</h3> |
| <p> |
| The JAR-signed APK is a |
| <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#Signed_JAR_File">standard |
| signed JAR</a>, which must contain exactly the entries listed in |
| META-INF/MANIFEST.MF and where all entries must be signed by the same set of |
| signers. Its integrity is verified as follows: |
| </p> |
| |
| <ol> |
| <li>Each signer is represented by a META-INF/<signer>.SF and |
| META-INF/<signer>.(RSA|DSA|EC) JAR entry.</li> |
| <li><signer>.(RSA|DSA|EC) is a |
| <a href="https://tools.ietf.org/html/rfc5652">PKCS #7 CMS ContentInfo |
| with SignedData structure</a> whose signature is verified over the |
| <signer>.SF file.</li> |
| <li><signer>.SF file contains a whole-file digest of the META-INF/MANIFEST.MF |
| and digests of each section of META-INF/MANIFEST.MF. The whole-file digest of |
| the MANIFEST.MF is verified. If that fails, the digest of each MANIFEST.MF |
| section is verified instead.</li> |
| <li>META-INF/MANIFEST.MF contains, for each integrity-protected JAR entry, a |
| correspondingly named section containing the digest of the entry’s uncompressed |
| contents. All these digests are verified.</li> |
| <li>APK verification fails if the APK contains JAR entries which are not listed |
| in the MANIFEST.MF and are not part of JAR signature.</li> |
| </ol> |
| |
| <p> |
| The protection chain is thus <signer>.(RSA|DSA|EC) -> <signer>.SF -> MANIFEST.MF |
| -> contents of each integrity-protected JAR entry. |
| </p> |
| |