/*
 * Copyright (C) 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.
 */

package com.android.apksig.internal.apk.v1;

import com.android.apksig.ApkVerifier.Issue;
import com.android.apksig.ApkVerifier.IssueWithParams;
import com.android.apksig.apk.ApkFormatException;
import com.android.apksig.apk.ApkUtils;
import com.android.apksig.internal.jar.ManifestParser;
import com.android.apksig.internal.util.AndroidSdkVersion;
import com.android.apksig.internal.util.InclusiveIntRange;
import com.android.apksig.internal.util.MessageDigestSink;
import com.android.apksig.internal.zip.CentralDirectoryRecord;
import com.android.apksig.internal.zip.LocalFileRecord;
import com.android.apksig.util.DataSource;
import com.android.apksig.zip.ZipFormatException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Base64.Decoder;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.jar.Attributes;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;

/**
 * APK verifier which uses JAR signing (aka v1 signing scheme).
 *
 * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#Signed_JAR_File">Signed JAR File</a>
 */
public abstract class V1SchemeVerifier {

    private static final String MANIFEST_ENTRY_NAME = V1SchemeSigner.MANIFEST_ENTRY_NAME;

    private V1SchemeVerifier() {}

    /**
     * Verifies the provided APK's JAR signatures and returns the result of verification. APK is
     * considered verified only if {@link Result#verified} is {@code true}. If verification fails,
     * the result will contain errors -- see {@link Result#getErrors()}.
     *
     * @throws ApkFormatException if the APK is malformed
     * @throws IOException if an I/O error occurs when reading the APK
     * @throws NoSuchAlgorithmException if the APK's JAR signatures cannot be verified because a
     *         required cryptographic algorithm implementation is missing
     */
    public static Result verify(
            DataSource apk,
            ApkUtils.ZipSections apkSections,
            Map<Integer, String> supportedApkSigSchemeNames,
            Set<Integer> foundApkSigSchemeIds,
            int minSdkVersion,
            int maxSdkVersion) throws IOException, ApkFormatException, NoSuchAlgorithmException {
        if (minSdkVersion > maxSdkVersion) {
            throw new IllegalArgumentException(
                    "minSdkVersion (" + minSdkVersion + ") > maxSdkVersion (" + maxSdkVersion
                            + ")");
        }

        Result result = new Result();

        // Parse the ZIP Central Directory and check that there are no entries with duplicate names.
        List<CentralDirectoryRecord> cdRecords = parseZipCentralDirectory(apk, apkSections);
        Set<String> cdEntryNames = checkForDuplicateEntries(cdRecords, result);
        if (result.containsErrors()) {
            return result;
        }

        // Verify JAR signature(s).
        Signers.verify(
                apk,
                apkSections.getZipCentralDirectoryOffset(),
                cdRecords,
                cdEntryNames,
                supportedApkSigSchemeNames,
                foundApkSigSchemeIds,
                minSdkVersion,
                maxSdkVersion,
                result);

        return result;
    }

    /**
     * Returns the set of entry names and reports any duplicate entry names in the {@code result}
     * as errors.
     */
    private static Set<String> checkForDuplicateEntries(
            List<CentralDirectoryRecord> cdRecords, Result result) {
        Set<String> cdEntryNames = new HashSet<>(cdRecords.size());
        Set<String> duplicateCdEntryNames = null;
        for (CentralDirectoryRecord cdRecord : cdRecords) {
            String entryName = cdRecord.getName();
            if (!cdEntryNames.add(entryName)) {
                // This is an error. Report this once per duplicate name.
                if (duplicateCdEntryNames == null) {
                    duplicateCdEntryNames = new HashSet<>();
                }
                if (duplicateCdEntryNames.add(entryName)) {
                    result.addError(Issue.JAR_SIG_DUPLICATE_ZIP_ENTRY, entryName);
                }
            }
        }
        return cdEntryNames;
    }

    /**
     * All JAR signers of an APK.
     */
    private static class Signers {

        /**
         * Verifies JAR signatures of the provided APK and populates the provided result container
         * with errors, warnings, and information about signers. The APK is considered verified if
         * the {@link Result#verified} is {@code true}.
         */
        private static void verify(
                DataSource apk,
                long cdStartOffset,
                List<CentralDirectoryRecord> cdRecords,
                Set<String> cdEntryNames,
                Map<Integer, String> supportedApkSigSchemeNames,
                Set<Integer> foundApkSigSchemeIds,
                int minSdkVersion,
                int maxSdkVersion,
                Result result) throws ApkFormatException, IOException, NoSuchAlgorithmException {

            // Find JAR manifest and signature block files.
            CentralDirectoryRecord manifestEntry = null;
            Map<String, CentralDirectoryRecord> sigFileEntries = new HashMap<>(1);
            List<CentralDirectoryRecord> sigBlockEntries = new ArrayList<>(1);
            for (CentralDirectoryRecord cdRecord : cdRecords) {
                String entryName = cdRecord.getName();
                if (!entryName.startsWith("META-INF/")) {
                    continue;
                }
                if ((manifestEntry == null) && (MANIFEST_ENTRY_NAME.equals(entryName))) {
                    manifestEntry = cdRecord;
                    continue;
                }
                if (entryName.endsWith(".SF")) {
                    sigFileEntries.put(entryName, cdRecord);
                    continue;
                }
                if ((entryName.endsWith(".RSA"))
                        || (entryName.endsWith(".DSA"))
                        || (entryName.endsWith(".EC"))) {
                    sigBlockEntries.add(cdRecord);
                    continue;
                }
            }
            if (manifestEntry == null) {
                result.addError(Issue.JAR_SIG_NO_MANIFEST);
                return;
            }

            // Parse the JAR manifest and check that all JAR entries it references exist in the APK.
            byte[] manifestBytes;
            try {
                manifestBytes =
                        LocalFileRecord.getUncompressedData(apk, manifestEntry, cdStartOffset);
            } catch (ZipFormatException e) {
                throw new ApkFormatException("Malformed ZIP entry: " + manifestEntry.getName(), e);
            }
            Map<String, ManifestParser.Section> entryNameToManifestSection = null;
            ManifestParser manifest = new ManifestParser(manifestBytes);
            ManifestParser.Section manifestMainSection = manifest.readSection();
            List<ManifestParser.Section> manifestIndividualSections = manifest.readAllSections();
            entryNameToManifestSection = new HashMap<>(manifestIndividualSections.size());
            int manifestSectionNumber = 0;
            for (ManifestParser.Section manifestSection : manifestIndividualSections) {
                manifestSectionNumber++;
                String entryName = manifestSection.getName();
                if (entryName == null) {
                    result.addError(Issue.JAR_SIG_UNNNAMED_MANIFEST_SECTION, manifestSectionNumber);
                    continue;
                }
                if (entryNameToManifestSection.put(entryName, manifestSection) != null) {
                    result.addError(Issue.JAR_SIG_DUPLICATE_MANIFEST_SECTION, entryName);
                    continue;
                }
                if (!cdEntryNames.contains(entryName)) {
                    result.addError(
                            Issue.JAR_SIG_MISSING_ZIP_ENTRY_REFERENCED_IN_MANIFEST, entryName);
                    continue;
                }
            }
            if (result.containsErrors()) {
                return;
            }
            // STATE OF AFFAIRS:
            // * All JAR entries listed in JAR manifest are present in the APK.

            // Identify signers
            List<Signer> signers = new ArrayList<>(sigBlockEntries.size());
            for (CentralDirectoryRecord sigBlockEntry : sigBlockEntries) {
                String sigBlockEntryName = sigBlockEntry.getName();
                int extensionDelimiterIndex = sigBlockEntryName.lastIndexOf('.');
                if (extensionDelimiterIndex == -1) {
                    throw new RuntimeException(
                            "Signature block file name does not contain extension: "
                                    + sigBlockEntryName);
                }
                String sigFileEntryName =
                        sigBlockEntryName.substring(0, extensionDelimiterIndex) + ".SF";
                CentralDirectoryRecord sigFileEntry = sigFileEntries.get(sigFileEntryName);
                if (sigFileEntry == null) {
                    result.addWarning(
                            Issue.JAR_SIG_MISSING_FILE, sigBlockEntryName, sigFileEntryName);
                    continue;
                }
                String signerName = sigBlockEntryName.substring("META-INF/".length());
                Result.SignerInfo signerInfo =
                        new Result.SignerInfo(
                                signerName, sigBlockEntryName, sigFileEntry.getName());
                Signer signer = new Signer(signerName, sigBlockEntry, sigFileEntry, signerInfo);
                signers.add(signer);
            }
            if (signers.isEmpty()) {
                result.addError(Issue.JAR_SIG_NO_SIGNATURES);
                return;
            }

            // Verify each signer's signature block file .(RSA|DSA|EC) against the corresponding
            // signature file .SF. Any error encountered for any signer terminates verification, to
            // mimic Android's behavior.
            for (Signer signer : signers) {
                signer.verifySigBlockAgainstSigFile(
                        apk, cdStartOffset, minSdkVersion, maxSdkVersion);
                if (signer.getResult().containsErrors()) {
                    result.signers.add(signer.getResult());
                }
            }
            if (result.containsErrors()) {
                return;
            }
            // STATE OF AFFAIRS:
            // * All JAR entries listed in JAR manifest are present in the APK.
            // * All signature files (.SF) verify against corresponding block files (.RSA|.DSA|.EC).

            // Verify each signer's signature file (.SF) against the JAR manifest.
            List<Signer> remainingSigners = new ArrayList<>(signers.size());
            for (Signer signer : signers) {
                signer.verifySigFileAgainstManifest(
                        manifestBytes,
                        manifestMainSection,
                        entryNameToManifestSection,
                        supportedApkSigSchemeNames,
                        foundApkSigSchemeIds,
                        minSdkVersion,
                        maxSdkVersion);
                if (signer.isIgnored()) {
                    result.ignoredSigners.add(signer.getResult());
                } else {
                    if (signer.getResult().containsErrors()) {
                        result.signers.add(signer.getResult());
                    } else {
                        remainingSigners.add(signer);
                    }
                }
            }
            if (result.containsErrors()) {
                return;
            }
            signers = remainingSigners;
            if (signers.isEmpty()) {
                result.addError(Issue.JAR_SIG_NO_SIGNATURES);
                return;
            }
            // STATE OF AFFAIRS:
            // * All signature files (.SF) verify against corresponding block files (.RSA|.DSA|.EC).
            // * Contents of all JAR manifest sections listed in .SF files verify against .SF files.
            // * All JAR entries listed in JAR manifest are present in the APK.

            // Verify data of JAR entries against JAR manifest and .SF files. On Android, an APK's
            // JAR entry is considered signed by signers associated with an .SF file iff the entry
            // is mentioned in the .SF file and the entry's digest(s) mentioned in the JAR manifest
            // match theentry's uncompressed data. Android requires that all such JAR entries are
            // signed by the same set of signers. This set may be smaller than the set of signers
            // we've identified so far.
            Set<Signer> apkSigners =
                    verifyJarEntriesAgainstManifestAndSigners(
                            apk,
                            cdStartOffset,
                            cdRecords,
                            entryNameToManifestSection,
                            signers,
                            minSdkVersion,
                            maxSdkVersion,
                            result);
            if (result.containsErrors()) {
                return;
            }
            // STATE OF AFFAIRS:
            // * All signature files (.SF) verify against corresponding block files (.RSA|.DSA|.EC).
            // * Contents of all JAR manifest sections listed in .SF files verify against .SF files.
            // * All JAR entries listed in JAR manifest are present in the APK.
            // * All JAR entries present in the APK and supposed to be covered by JAR signature
            //   (i.e., reside outside of META-INF/) are covered by signatures from the same set
            //   of signers.

            // Report any JAR entries which aren't covered by signature.
            Set<String> signatureEntryNames = new HashSet<>(1 + result.signers.size() * 2);
            signatureEntryNames.add(manifestEntry.getName());
            for (Signer signer : apkSigners) {
                signatureEntryNames.add(signer.getSignatureBlockEntryName());
                signatureEntryNames.add(signer.getSignatureFileEntryName());
            }
            for (CentralDirectoryRecord cdRecord : cdRecords) {
                String entryName = cdRecord.getName();
                if ((entryName.startsWith("META-INF/"))
                        && (!entryName.endsWith("/"))
                        && (!signatureEntryNames.contains(entryName))) {
                    result.addWarning(Issue.JAR_SIG_UNPROTECTED_ZIP_ENTRY, entryName);
                }
            }

            // Reflect the sets of used signers and ignored signers in the result.
            for (Signer signer : signers) {
                if (apkSigners.contains(signer)) {
                    result.signers.add(signer.getResult());
                } else {
                    result.ignoredSigners.add(signer.getResult());
                }
            }

            result.verified = true;
        }
    }

    static class Signer {
        private final String mName;
        private final Result.SignerInfo mResult;
        private final CentralDirectoryRecord mSignatureFileEntry;
        private final CentralDirectoryRecord mSignatureBlockEntry;
        private boolean mIgnored;

        private byte[] mSigFileBytes;
        private Set<String> mSigFileEntryNames;

        private Signer(
                String name,
                CentralDirectoryRecord sigBlockEntry,
                CentralDirectoryRecord sigFileEntry,
                Result.SignerInfo result) {
            mName = name;
            mResult = result;
            mSignatureBlockEntry = sigBlockEntry;
            mSignatureFileEntry = sigFileEntry;
        }

        public String getName() {
            return mName;
        }

        public String getSignatureFileEntryName() {
            return mSignatureFileEntry.getName();
        }

        public String getSignatureBlockEntryName() {
            return mSignatureBlockEntry.getName();
        }

        void setIgnored() {
            mIgnored = true;
        }

        public boolean isIgnored() {
            return mIgnored;
        }

        public Set<String> getSigFileEntryNames() {
            return mSigFileEntryNames;
        }

        public Result.SignerInfo getResult() {
            return mResult;
        }

        @SuppressWarnings("restriction")
        public void verifySigBlockAgainstSigFile(
                DataSource apk, long cdStartOffset, int minSdkVersion, int maxSdkVersion)
                        throws IOException, ApkFormatException, NoSuchAlgorithmException {
            byte[] sigBlockBytes;
            try {
                sigBlockBytes =
                        LocalFileRecord.getUncompressedData(
                                apk, mSignatureBlockEntry, cdStartOffset);
            } catch (ZipFormatException e) {
                throw new ApkFormatException(
                        "Malformed ZIP entry: " + mSignatureBlockEntry.getName(), e);
            }
            try {
                mSigFileBytes =
                        LocalFileRecord.getUncompressedData(
                                apk, mSignatureFileEntry, cdStartOffset);
            } catch (ZipFormatException e) {
                throw new ApkFormatException(
                        "Malformed ZIP entry: " + mSignatureFileEntry.getName(), e);
            }
            PKCS7 sigBlock;
            try {
                sigBlock = new PKCS7(sigBlockBytes);
            } catch (IOException e) {
                if (e.getCause() instanceof CertificateException) {
                    mResult.addError(
                            Issue.JAR_SIG_MALFORMED_CERTIFICATE, mSignatureBlockEntry.getName(), e);
                } else {
                    mResult.addError(
                            Issue.JAR_SIG_PARSE_EXCEPTION, mSignatureBlockEntry.getName(), e);
                }
                return;
            }
            SignerInfo[] unverifiedSignerInfos = sigBlock.getSignerInfos();
            if ((unverifiedSignerInfos == null) || (unverifiedSignerInfos.length == 0)) {
                mResult.addError(Issue.JAR_SIG_NO_SIGNERS, mSignatureBlockEntry.getName());
                return;
            }

            SignerInfo verifiedSignerInfo = null;
            if ((unverifiedSignerInfos != null) && (unverifiedSignerInfos.length > 0)) {
                for (int i = 0; i < unverifiedSignerInfos.length; i++) {
                    SignerInfo unverifiedSignerInfo = unverifiedSignerInfos[i];
                    String digestAlgorithmOid =
                            unverifiedSignerInfo.getDigestAlgorithmId().getOID().toString();
                    String signatureAlgorithmOid =
                            unverifiedSignerInfo
                                    .getDigestEncryptionAlgorithmId().getOID().toString();
                    InclusiveIntRange desiredApiLevels =
                            InclusiveIntRange.fromTo(minSdkVersion, maxSdkVersion);
                    List<InclusiveIntRange> apiLevelsWhereDigestAndSigAlgorithmSupported =
                            getSigAlgSupportedApiLevels(digestAlgorithmOid, signatureAlgorithmOid);
                    List<InclusiveIntRange> apiLevelsWhereDigestAlgorithmNotSupported =
                            desiredApiLevels.getValuesNotIn(apiLevelsWhereDigestAndSigAlgorithmSupported);
                    if (!apiLevelsWhereDigestAlgorithmNotSupported.isEmpty()) {
                        mResult.addError(
                                Issue.JAR_SIG_UNSUPPORTED_SIG_ALG,
                                mSignatureBlockEntry.getName(),
                                digestAlgorithmOid,
                                signatureAlgorithmOid,
                                String.valueOf(apiLevelsWhereDigestAlgorithmNotSupported));
                        return;
                    }
                    try {
                        verifiedSignerInfo = sigBlock.verify(unverifiedSignerInfo, mSigFileBytes);
                    } catch (SignatureException e) {
                        mResult.addError(
                                Issue.JAR_SIG_VERIFY_EXCEPTION,
                                mSignatureBlockEntry.getName(),
                                mSignatureFileEntry.getName(),
                                e);
                        return;
                    }
                    if (verifiedSignerInfo != null) {
                        // Verified
                        break;
                    }

                    // Did not verify
                    if (minSdkVersion < AndroidSdkVersion.N) {
                        // Prior to N, Android attempted to verify only the first SignerInfo.
                        mResult.addError(
                                Issue.JAR_SIG_DID_NOT_VERIFY,
                                mSignatureBlockEntry.getName(),
                                mSignatureFileEntry.getName());
                        return;
                    }
                }
            }
            if (verifiedSignerInfo == null) {
                mResult.addError(Issue.JAR_SIG_NO_SIGNERS, mSignatureBlockEntry.getName());
                return;
            }

            // TODO: PKCS7 class doesn't guarantee that returned certificates' getEncoded returns
            // the original encoded form of certificates rather than the DER re-encoded form. We
            // need to replace the PKCS7 parser/verifier.
            List<X509Certificate> certChain;
            try {
                certChain = verifiedSignerInfo.getCertificateChain(sigBlock);
            } catch (IOException e) {
                throw new RuntimeException(
                        "Failed to obtain cert chain from " + mSignatureBlockEntry.getName(), e);
            }
            if ((certChain == null) || (certChain.isEmpty())) {
                throw new RuntimeException("Verified SignerInfo does not have a certificate chain");
            }
            mResult.certChain.clear();
            mResult.certChain.addAll(certChain);
        }

        private static final String OID_DIGEST_MD5 = "1.2.840.113549.2.5";
        static final String OID_DIGEST_SHA1 = "1.3.14.3.2.26";
        private static final String OID_DIGEST_SHA224 = "2.16.840.1.101.3.4.2.4";
        static final String OID_DIGEST_SHA256 = "2.16.840.1.101.3.4.2.1";
        private static final String OID_DIGEST_SHA384 = "2.16.840.1.101.3.4.2.2";
        private static final String OID_DIGEST_SHA512 = "2.16.840.1.101.3.4.2.3";

        static final String OID_SIG_RSA = "1.2.840.113549.1.1.1";
        private static final String OID_SIG_MD5_WITH_RSA = "1.2.840.113549.1.1.4";
        private static final String OID_SIG_SHA1_WITH_RSA = "1.2.840.113549.1.1.5";
        private static final String OID_SIG_SHA224_WITH_RSA = "1.2.840.113549.1.1.14";
        private static final String OID_SIG_SHA256_WITH_RSA = "1.2.840.113549.1.1.11";
        private static final String OID_SIG_SHA384_WITH_RSA = "1.2.840.113549.1.1.12";
        private static final String OID_SIG_SHA512_WITH_RSA = "1.2.840.113549.1.1.13";

        static final String OID_SIG_DSA = "1.2.840.10040.4.1";
        private static final String OID_SIG_SHA1_WITH_DSA = "1.2.840.10040.4.3";
        private static final String OID_SIG_SHA224_WITH_DSA = "2.16.840.1.101.3.4.3.1";
        static final String OID_SIG_SHA256_WITH_DSA = "2.16.840.1.101.3.4.3.2";

        static final String OID_SIG_EC_PUBLIC_KEY = "1.2.840.10045.2.1";
        private static final String OID_SIG_SHA1_WITH_ECDSA = "1.2.840.10045.4.1";
        private static final String OID_SIG_SHA224_WITH_ECDSA = "1.2.840.10045.4.3.1";
        private static final String OID_SIG_SHA256_WITH_ECDSA = "1.2.840.10045.4.3.2";
        private static final String OID_SIG_SHA384_WITH_ECDSA = "1.2.840.10045.4.3.3";
        private static final String OID_SIG_SHA512_WITH_ECDSA = "1.2.840.10045.4.3.4";

        private static final Map<String, List<InclusiveIntRange>> SUPPORTED_SIG_ALG_OIDS =
                new HashMap<>();
        {
            addSupportedSigAlg(
                    OID_DIGEST_MD5, OID_SIG_RSA,
                    InclusiveIntRange.from(0));
            addSupportedSigAlg(
                    OID_DIGEST_MD5, OID_SIG_MD5_WITH_RSA,
                    InclusiveIntRange.fromTo(0, 8), InclusiveIntRange.from(21));
            addSupportedSigAlg(
                    OID_DIGEST_MD5, OID_SIG_SHA1_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_MD5, OID_SIG_SHA224_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_MD5, OID_SIG_SHA256_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_MD5, OID_SIG_SHA384_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_MD5, OID_SIG_SHA512_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));

            addSupportedSigAlg(
                    OID_DIGEST_SHA1, OID_SIG_RSA,
                    InclusiveIntRange.from(0));
            addSupportedSigAlg(
                    OID_DIGEST_SHA1, OID_SIG_MD5_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA1, OID_SIG_SHA1_WITH_RSA,
                    InclusiveIntRange.from(0));
            addSupportedSigAlg(
                    OID_DIGEST_SHA1, OID_SIG_SHA224_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA1, OID_SIG_SHA256_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA1, OID_SIG_SHA384_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA1, OID_SIG_SHA512_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));

            addSupportedSigAlg(
                    OID_DIGEST_SHA224, OID_SIG_RSA,
                    InclusiveIntRange.fromTo(0, 8), InclusiveIntRange.from(21));
            addSupportedSigAlg(
                    OID_DIGEST_SHA224, OID_SIG_MD5_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA224, OID_SIG_SHA1_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA224, OID_SIG_SHA224_WITH_RSA,
                    InclusiveIntRange.fromTo(0, 8), InclusiveIntRange.from(21));
            addSupportedSigAlg(
                    OID_DIGEST_SHA224, OID_SIG_SHA256_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 21));
            addSupportedSigAlg(
                    OID_DIGEST_SHA224, OID_SIG_SHA384_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA224, OID_SIG_SHA512_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));

            addSupportedSigAlg(
                    OID_DIGEST_SHA256, OID_SIG_RSA,
                    InclusiveIntRange.fromTo(0, 8), InclusiveIntRange.from(18));
            addSupportedSigAlg(
                    OID_DIGEST_SHA256, OID_SIG_MD5_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA256, OID_SIG_SHA1_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 21));
            addSupportedSigAlg(
                    OID_DIGEST_SHA256, OID_SIG_SHA224_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA256, OID_SIG_SHA256_WITH_RSA,
                    InclusiveIntRange.fromTo(0, 8), InclusiveIntRange.from(18));
            addSupportedSigAlg(
                    OID_DIGEST_SHA256, OID_SIG_SHA384_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA256, OID_SIG_SHA512_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));

            addSupportedSigAlg(
                    OID_DIGEST_SHA384, OID_SIG_RSA,
                    InclusiveIntRange.from(18));
            addSupportedSigAlg(
                    OID_DIGEST_SHA384, OID_SIG_MD5_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA384, OID_SIG_SHA1_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA384, OID_SIG_SHA224_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA384, OID_SIG_SHA256_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA384, OID_SIG_SHA384_WITH_RSA,
                    InclusiveIntRange.from(21));
            addSupportedSigAlg(
                    OID_DIGEST_SHA384, OID_SIG_SHA512_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));

            addSupportedSigAlg(
                    OID_DIGEST_SHA512, OID_SIG_RSA,
                    InclusiveIntRange.from(18));
            addSupportedSigAlg(
                    OID_DIGEST_SHA512, OID_SIG_MD5_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA512, OID_SIG_SHA1_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA512, OID_SIG_SHA224_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA512, OID_SIG_SHA256_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA512, OID_SIG_SHA384_WITH_RSA,
                    InclusiveIntRange.fromTo(21, 21));
            addSupportedSigAlg(
                    OID_DIGEST_SHA512, OID_SIG_SHA512_WITH_RSA,
                    InclusiveIntRange.from(21));

            addSupportedSigAlg(
                    OID_DIGEST_MD5, OID_SIG_SHA1_WITH_DSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_MD5, OID_SIG_SHA224_WITH_DSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_MD5, OID_SIG_SHA256_WITH_DSA,
                    InclusiveIntRange.fromTo(21, 23));

            addSupportedSigAlg(
                    OID_DIGEST_SHA1, OID_SIG_DSA,
                    InclusiveIntRange.from(0));
            addSupportedSigAlg(
                    OID_DIGEST_SHA1, OID_SIG_SHA1_WITH_DSA,
                    InclusiveIntRange.from(9));
            addSupportedSigAlg(
                    OID_DIGEST_SHA1, OID_SIG_SHA224_WITH_DSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA1, OID_SIG_SHA256_WITH_DSA,
                    InclusiveIntRange.fromTo(21, 23));

            addSupportedSigAlg(
                    OID_DIGEST_SHA224, OID_SIG_DSA,
                    InclusiveIntRange.from(22));
            addSupportedSigAlg(
                    OID_DIGEST_SHA224, OID_SIG_SHA1_WITH_DSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA224, OID_SIG_SHA224_WITH_DSA,
                    InclusiveIntRange.from(21));
            addSupportedSigAlg(
                    OID_DIGEST_SHA224, OID_SIG_SHA256_WITH_DSA,
                    InclusiveIntRange.fromTo(21, 23));

            addSupportedSigAlg(
                    OID_DIGEST_SHA256, OID_SIG_DSA,
                    InclusiveIntRange.from(22));
            addSupportedSigAlg(
                    OID_DIGEST_SHA256, OID_SIG_SHA1_WITH_DSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA256, OID_SIG_SHA224_WITH_DSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA256, OID_SIG_SHA256_WITH_DSA,
                    InclusiveIntRange.from(21));

            addSupportedSigAlg(
                    OID_DIGEST_SHA384, OID_SIG_SHA1_WITH_DSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA384, OID_SIG_SHA224_WITH_DSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA384, OID_SIG_SHA256_WITH_DSA,
                    InclusiveIntRange.fromTo(21, 23));

            addSupportedSigAlg(
                    OID_DIGEST_SHA512, OID_SIG_SHA1_WITH_DSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA512, OID_SIG_SHA224_WITH_DSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA512, OID_SIG_SHA256_WITH_DSA,
                    InclusiveIntRange.fromTo(21, 23));

            addSupportedSigAlg(
                    OID_DIGEST_SHA1, OID_SIG_EC_PUBLIC_KEY,
                    InclusiveIntRange.from(18));
            addSupportedSigAlg(
                    OID_DIGEST_SHA224, OID_SIG_EC_PUBLIC_KEY,
                    InclusiveIntRange.from(21));
            addSupportedSigAlg(
                    OID_DIGEST_SHA256, OID_SIG_EC_PUBLIC_KEY,
                    InclusiveIntRange.from(18));
            addSupportedSigAlg(
                    OID_DIGEST_SHA384, OID_SIG_EC_PUBLIC_KEY,
                    InclusiveIntRange.from(18));
            addSupportedSigAlg(
                    OID_DIGEST_SHA512, OID_SIG_EC_PUBLIC_KEY,
                    InclusiveIntRange.from(18));

            addSupportedSigAlg(
                    OID_DIGEST_MD5, OID_SIG_SHA1_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_MD5, OID_SIG_SHA224_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_MD5, OID_SIG_SHA256_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_MD5, OID_SIG_SHA384_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_MD5, OID_SIG_SHA512_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));

            addSupportedSigAlg(
                    OID_DIGEST_SHA1, OID_SIG_SHA1_WITH_ECDSA,
                    InclusiveIntRange.from(18));
            addSupportedSigAlg(
                    OID_DIGEST_SHA1, OID_SIG_SHA224_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA1, OID_SIG_SHA256_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA1, OID_SIG_SHA384_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA1, OID_SIG_SHA512_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));

            addSupportedSigAlg(
                    OID_DIGEST_SHA224, OID_SIG_SHA1_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA224, OID_SIG_SHA224_WITH_ECDSA,
                    InclusiveIntRange.from(21));
            addSupportedSigAlg(
                    OID_DIGEST_SHA224, OID_SIG_SHA256_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA224, OID_SIG_SHA384_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA224, OID_SIG_SHA512_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));

            addSupportedSigAlg(
                    OID_DIGEST_SHA256, OID_SIG_SHA1_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA256, OID_SIG_SHA224_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA256, OID_SIG_SHA256_WITH_ECDSA,
                    InclusiveIntRange.from(21));
            addSupportedSigAlg(
                    OID_DIGEST_SHA256, OID_SIG_SHA384_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA256, OID_SIG_SHA512_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));

            addSupportedSigAlg(
                    OID_DIGEST_SHA384, OID_SIG_SHA1_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA384, OID_SIG_SHA224_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA384, OID_SIG_SHA256_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA384, OID_SIG_SHA384_WITH_ECDSA,
                    InclusiveIntRange.from(21));
            addSupportedSigAlg(
                    OID_DIGEST_SHA384, OID_SIG_SHA512_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));

            addSupportedSigAlg(
                    OID_DIGEST_SHA512, OID_SIG_SHA1_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA512, OID_SIG_SHA224_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA512, OID_SIG_SHA256_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA512, OID_SIG_SHA384_WITH_ECDSA,
                    InclusiveIntRange.fromTo(21, 23));
            addSupportedSigAlg(
                    OID_DIGEST_SHA512, OID_SIG_SHA512_WITH_ECDSA,
                    InclusiveIntRange.from(21));
        }

        private static void addSupportedSigAlg(
                String digestAlgorithmOid,
                String signatureAlgorithmOid,
                InclusiveIntRange... supportedApiLevels) {
            SUPPORTED_SIG_ALG_OIDS.put(
                    digestAlgorithmOid + "with" + signatureAlgorithmOid,
                    Arrays.asList(supportedApiLevels));
        }

        private List<InclusiveIntRange> getSigAlgSupportedApiLevels(
                String digestAlgorithmOid,
                String signatureAlgorithmOid) {
            List<InclusiveIntRange> result =
                    SUPPORTED_SIG_ALG_OIDS.get(digestAlgorithmOid + "with" + signatureAlgorithmOid);
            return (result != null) ? result : Collections.emptyList();
        }

        public void verifySigFileAgainstManifest(
                byte[] manifestBytes,
                ManifestParser.Section manifestMainSection,
                Map<String, ManifestParser.Section> entryNameToManifestSection,
                Map<Integer, String> supportedApkSigSchemeNames,
                Set<Integer> foundApkSigSchemeIds,
                int minSdkVersion,
                int maxSdkVersion) throws NoSuchAlgorithmException {
            // Inspect the main section of the .SF file.
            ManifestParser sf = new ManifestParser(mSigFileBytes);
            ManifestParser.Section sfMainSection = sf.readSection();
            if (sfMainSection.getAttributeValue(Attributes.Name.SIGNATURE_VERSION) == null) {
                mResult.addError(
                        Issue.JAR_SIG_MISSING_VERSION_ATTR_IN_SIG_FILE,
                        mSignatureFileEntry.getName());
                setIgnored();
                return;
            }

            if (maxSdkVersion >= AndroidSdkVersion.N) {
                // Android N and newer rejects APKs whose .SF file says they were supposed to be
                // signed with APK Signature Scheme v2 (or newer) and yet no such signature was
                // found.
                checkForStrippedApkSignatures(
                        sfMainSection, supportedApkSigSchemeNames, foundApkSigSchemeIds);
                if (mResult.containsErrors()) {
                    return;
                }
            }

            boolean createdBySigntool = false;
            String createdBy = sfMainSection.getAttributeValue("Created-By");
            if (createdBy != null) {
                createdBySigntool = createdBy.indexOf("signtool") != -1;
            }
            boolean manifestDigestVerified =
                    verifyManifestDigest(
                            sfMainSection,
                            createdBySigntool,
                            manifestBytes,
                            minSdkVersion,
                            maxSdkVersion);
            if (!createdBySigntool) {
                verifyManifestMainSectionDigest(
                        sfMainSection,
                        manifestMainSection,
                        manifestBytes,
                        minSdkVersion,
                        maxSdkVersion);
            }
            if (mResult.containsErrors()) {
                return;
            }

            // Inspect per-entry sections of .SF file. Technically, if the digest of JAR manifest
            // verifies, per-entry sections should be ignored. However, most Android platform
            // implementations require that such sections exist.
            List<ManifestParser.Section> sfSections = sf.readAllSections();
            Set<String> sfEntryNames = new HashSet<>(sfSections.size());
            int sfSectionNumber = 0;
            for (ManifestParser.Section sfSection : sfSections) {
                sfSectionNumber++;
                String entryName = sfSection.getName();
                if (entryName == null) {
                    mResult.addError(
                            Issue.JAR_SIG_UNNNAMED_SIG_FILE_SECTION,
                            mSignatureFileEntry.getName(),
                            sfSectionNumber);
                    setIgnored();
                    return;
                }
                if (!sfEntryNames.add(entryName)) {
                    mResult.addError(
                            Issue.JAR_SIG_DUPLICATE_SIG_FILE_SECTION,
                            mSignatureFileEntry.getName(),
                            entryName);
                    setIgnored();
                    return;
                }
                if (manifestDigestVerified) {
                    // No need to verify this entry's corresponding JAR manifest entry because the
                    // JAR manifest verifies in full.
                    continue;
                }
                // Whole-file digest of JAR manifest hasn't been verified. Thus, we need to verify
                // the digest of the JAR manifest section corresponding to this .SF section.
                ManifestParser.Section manifestSection = entryNameToManifestSection.get(entryName);
                if (manifestSection == null) {
                    mResult.addError(
                            Issue.JAR_SIG_NO_ZIP_ENTRY_DIGEST_IN_SIG_FILE,
                            entryName,
                            mSignatureFileEntry.getName());
                    setIgnored();
                    continue;
                }
                verifyManifestIndividualSectionDigest(
                        sfSection,
                        createdBySigntool,
                        manifestSection,
                        manifestBytes,
                        minSdkVersion,
                        maxSdkVersion);
            }
            mSigFileEntryNames = sfEntryNames;
        }


        /**
         * Returns {@code true} if the whole-file digest of the manifest against the main section of
         * the .SF file.
         */
        private boolean verifyManifestDigest(
                ManifestParser.Section sfMainSection,
                boolean createdBySigntool,
                byte[] manifestBytes,
                int minSdkVersion,
                int maxSdkVersion) throws NoSuchAlgorithmException {
            Collection<NamedDigest> expectedDigests =
                    getDigestsToVerify(
                            sfMainSection,
                            ((createdBySigntool) ? "-Digest" : "-Digest-Manifest"),
                            minSdkVersion,
                            maxSdkVersion);
            boolean digestFound = !expectedDigests.isEmpty();
            if (!digestFound) {
                mResult.addWarning(
                        Issue.JAR_SIG_NO_MANIFEST_DIGEST_IN_SIG_FILE,
                        mSignatureFileEntry.getName());
                return false;
            }

            boolean verified = true;
            for (NamedDigest expectedDigest : expectedDigests) {
                String jcaDigestAlgorithm = expectedDigest.jcaDigestAlgorithm;
                byte[] actual = digest(jcaDigestAlgorithm, manifestBytes);
                byte[] expected = expectedDigest.digest;
                if (!Arrays.equals(expected, actual)) {
                    mResult.addWarning(
                            Issue.JAR_SIG_ZIP_ENTRY_DIGEST_DID_NOT_VERIFY,
                            V1SchemeSigner.MANIFEST_ENTRY_NAME,
                            jcaDigestAlgorithm,
                            mSignatureFileEntry.getName(),
                            Base64.getEncoder().encodeToString(actual),
                            Base64.getEncoder().encodeToString(expected));
                    verified = false;
                }
            }
            return verified;
        }

        /**
         * Verifies the digest of the manifest's main section against the main section of the .SF
         * file.
         */
        private void verifyManifestMainSectionDigest(
                ManifestParser.Section sfMainSection,
                ManifestParser.Section manifestMainSection,
                byte[] manifestBytes,
                int minSdkVersion,
                int maxSdkVersion) throws NoSuchAlgorithmException {
            Collection<NamedDigest> expectedDigests =
                    getDigestsToVerify(
                            sfMainSection,
                            "-Digest-Manifest-Main-Attributes",
                            minSdkVersion,
                            maxSdkVersion);
            if (expectedDigests.isEmpty()) {
                return;
            }

            for (NamedDigest expectedDigest : expectedDigests) {
                String jcaDigestAlgorithm = expectedDigest.jcaDigestAlgorithm;
                byte[] actual =
                        digest(
                                jcaDigestAlgorithm,
                                manifestBytes,
                                manifestMainSection.getStartOffset(),
                                manifestMainSection.getSizeBytes());
                byte[] expected = expectedDigest.digest;
                if (!Arrays.equals(expected, actual)) {
                    mResult.addError(
                            Issue.JAR_SIG_MANIFEST_MAIN_SECTION_DIGEST_DID_NOT_VERIFY,
                            jcaDigestAlgorithm,
                            mSignatureFileEntry.getName(),
                            Base64.getEncoder().encodeToString(actual),
                            Base64.getEncoder().encodeToString(expected));
                }
            }
        }

        /**
         * Verifies the digest of the manifest's individual section against the corresponding
         * individual section of the .SF file.
         */
        private void verifyManifestIndividualSectionDigest(
                ManifestParser.Section sfIndividualSection,
                boolean createdBySigntool,
                ManifestParser.Section manifestIndividualSection,
                byte[] manifestBytes,
                int minSdkVersion,
                int maxSdkVersion) throws NoSuchAlgorithmException {
            String entryName = sfIndividualSection.getName();
            Collection<NamedDigest> expectedDigests =
                    getDigestsToVerify(
                            sfIndividualSection, "-Digest", minSdkVersion, maxSdkVersion);
            if (expectedDigests.isEmpty()) {
                mResult.addError(
                        Issue.JAR_SIG_NO_ZIP_ENTRY_DIGEST_IN_SIG_FILE,
                        entryName,
                        mSignatureFileEntry.getName());
                return;
            }

            int sectionStartIndex = manifestIndividualSection.getStartOffset();
            int sectionSizeBytes = manifestIndividualSection.getSizeBytes();
            if (createdBySigntool) {
                int sectionEndIndex = sectionStartIndex + sectionSizeBytes;
                if ((manifestBytes[sectionEndIndex - 1] == '\n')
                        && (manifestBytes[sectionEndIndex - 2] == '\n')) {
                    sectionSizeBytes--;
                }
            }
            for (NamedDigest expectedDigest : expectedDigests) {
                String jcaDigestAlgorithm = expectedDigest.jcaDigestAlgorithm;
                byte[] actual =
                        digest(
                                jcaDigestAlgorithm,
                                manifestBytes,
                                sectionStartIndex,
                                sectionSizeBytes);
                byte[] expected = expectedDigest.digest;
                if (!Arrays.equals(expected, actual)) {
                    mResult.addError(
                            Issue.JAR_SIG_MANIFEST_SECTION_DIGEST_DID_NOT_VERIFY,
                            entryName,
                            jcaDigestAlgorithm,
                            mSignatureFileEntry.getName(),
                            Base64.getEncoder().encodeToString(actual),
                            Base64.getEncoder().encodeToString(expected));
                }
            }
        }

        private void checkForStrippedApkSignatures(
                ManifestParser.Section sfMainSection,
                Map<Integer, String> supportedApkSigSchemeNames,
                Set<Integer> foundApkSigSchemeIds) {
            String signedWithApkSchemes =
                    sfMainSection.getAttributeValue(
                            V1SchemeSigner.SF_ATTRIBUTE_NAME_ANDROID_APK_SIGNED_NAME_STR);
            // This field contains a comma-separated list of APK signature scheme IDs which were
            // used to sign this APK. Android rejects APKs where an ID is known to the platform but
            // the APK didn't verify using that scheme.

            if (signedWithApkSchemes == null) {
                // APK signature (e.g., v2 scheme) stripping protections not enabled.
                if (!foundApkSigSchemeIds.isEmpty()) {
                    // APK is signed with an APK signature scheme such as v2 scheme.
                    mResult.addWarning(
                            Issue.JAR_SIG_NO_APK_SIG_STRIP_PROTECTION,
                            mSignatureFileEntry.getName());
                }
                return;
            }

            if (supportedApkSigSchemeNames.isEmpty()) {
                return;
            }

            Set<Integer> supportedApkSigSchemeIds = supportedApkSigSchemeNames.keySet();
            Set<Integer> supportedExpectedApkSigSchemeIds = new HashSet<>(1);
            StringTokenizer tokenizer = new StringTokenizer(signedWithApkSchemes, ",");
            while (tokenizer.hasMoreTokens()) {
                String idText = tokenizer.nextToken().trim();
                if (idText.isEmpty()) {
                    continue;
                }
                int id;
                try {
                    id = Integer.parseInt(idText);
                } catch (Exception ignored) {
                    continue;
                }
                // This APK was supposed to be signed with the APK signature scheme having
                // this ID.
                if (supportedApkSigSchemeIds.contains(id)) {
                    supportedExpectedApkSigSchemeIds.add(id);
                } else {
                    mResult.addWarning(
                            Issue.JAR_SIG_UNKNOWN_APK_SIG_SCHEME_ID,
                            mSignatureFileEntry.getName(),
                            id);
                }
            }

            for (int id : supportedExpectedApkSigSchemeIds) {
                if (!foundApkSigSchemeIds.contains(id)) {
                    String apkSigSchemeName = supportedApkSigSchemeNames.get(id);
                    mResult.addError(
                            Issue.JAR_SIG_MISSING_APK_SIG_REFERENCED,
                            mSignatureFileEntry.getName(),
                            id,
                            apkSigSchemeName);
                }
            }
        }
    }

    private static Collection<NamedDigest> getDigestsToVerify(
            ManifestParser.Section section,
            String digestAttrSuffix,
            int minSdkVersion,
            int maxSdkVersion) {
        Decoder base64Decoder = Base64.getDecoder();
        List<NamedDigest> result = new ArrayList<>(1);
        if (minSdkVersion < AndroidSdkVersion.JELLY_BEAN_MR2) {
            // Prior to JB MR2, Android platform's logic for picking a digest algorithm to verify is
            // to rely on the ancient Digest-Algorithms attribute which contains
            // whitespace-separated list of digest algorithms (defaulting to SHA-1) to try. The
            // first digest attribute (with supported digest algorithm) found using the list is
            // used.
            String algs = section.getAttributeValue("Digest-Algorithms");
            if (algs == null) {
                algs = "SHA SHA1";
            }
            StringTokenizer tokens = new StringTokenizer(algs);
            while (tokens.hasMoreTokens()) {
                String alg = tokens.nextToken();
                String attrName = alg + digestAttrSuffix;
                String digestBase64 = section.getAttributeValue(attrName);
                if (digestBase64 == null) {
                    // Attribute not found
                    continue;
                }
                alg = getCanonicalJcaMessageDigestAlgorithm(alg);
                if ((alg == null)
                        || (getMinSdkVersionFromWhichSupportedInManifestOrSignatureFile(alg)
                                > minSdkVersion)) {
                    // Unsupported digest algorithm
                    continue;
                }
                // Supported digest algorithm
                result.add(new NamedDigest(alg, base64Decoder.decode(digestBase64)));
                break;
            }
            // No supported digests found -- this will fail to verify on pre-JB MR2 Androids.
            if (result.isEmpty()) {
                return result;
            }
        }

        if (maxSdkVersion >= AndroidSdkVersion.JELLY_BEAN_MR2) {
            // On JB MR2 and newer, Android platform picks the strongest algorithm out of:
            // SHA-512, SHA-384, SHA-256, SHA-1.
            for (String alg : JB_MR2_AND_NEWER_DIGEST_ALGS) {
                String attrName = getJarDigestAttributeName(alg, digestAttrSuffix);
                String digestBase64 = section.getAttributeValue(attrName);
                if (digestBase64 == null) {
                    // Attribute not found
                    continue;
                }
                byte[] digest = base64Decoder.decode(digestBase64);
                byte[] digestInResult = getDigest(result, alg);
                if ((digestInResult == null) || (!Arrays.equals(digestInResult, digest))) {
                    result.add(new NamedDigest(alg, digest));
                }
                break;
            }
        }

        return result;
    }

    private static final String[] JB_MR2_AND_NEWER_DIGEST_ALGS = {
            "SHA-512",
            "SHA-384",
            "SHA-256",
            "SHA-1",
    };

    private static String getCanonicalJcaMessageDigestAlgorithm(String algorithm) {
        return UPPER_CASE_JCA_DIGEST_ALG_TO_CANONICAL.get(algorithm.toUpperCase(Locale.US));
    }

    public static int getMinSdkVersionFromWhichSupportedInManifestOrSignatureFile(
            String jcaAlgorithmName) {
        Integer result =
                MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST.get(
                        jcaAlgorithmName.toUpperCase(Locale.US));
        return (result != null) ? result : Integer.MAX_VALUE;
    }

    private static String getJarDigestAttributeName(
            String jcaDigestAlgorithm, String attrNameSuffix) {
        if ("SHA-1".equalsIgnoreCase(jcaDigestAlgorithm)) {
            return "SHA1" + attrNameSuffix;
        } else {
            return jcaDigestAlgorithm + attrNameSuffix;
        }
    }

    private static final Map<String, String> UPPER_CASE_JCA_DIGEST_ALG_TO_CANONICAL;
    static {
        UPPER_CASE_JCA_DIGEST_ALG_TO_CANONICAL = new HashMap<>(8);
        UPPER_CASE_JCA_DIGEST_ALG_TO_CANONICAL.put("MD5", "MD5");
        UPPER_CASE_JCA_DIGEST_ALG_TO_CANONICAL.put("SHA", "SHA-1");
        UPPER_CASE_JCA_DIGEST_ALG_TO_CANONICAL.put("SHA1", "SHA-1");
        UPPER_CASE_JCA_DIGEST_ALG_TO_CANONICAL.put("SHA-1", "SHA-1");
        UPPER_CASE_JCA_DIGEST_ALG_TO_CANONICAL.put("SHA-256", "SHA-256");
        UPPER_CASE_JCA_DIGEST_ALG_TO_CANONICAL.put("SHA-384", "SHA-384");
        UPPER_CASE_JCA_DIGEST_ALG_TO_CANONICAL.put("SHA-512", "SHA-512");
    }

    private static final Map<String, Integer>
            MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST;
    static {
        MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST = new HashMap<>(5);
        MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST.put("MD5", 0);
        MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST.put("SHA-1", 0);
        MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST.put("SHA-256", 0);
        MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST.put(
                "SHA-384", AndroidSdkVersion.GINGERBREAD);
        MIN_SDK_VESION_FROM_WHICH_DIGEST_SUPPORTED_IN_MANIFEST.put(
                "SHA-512", AndroidSdkVersion.GINGERBREAD);
    }

    private static byte[] getDigest(Collection<NamedDigest> digests, String jcaDigestAlgorithm) {
        for (NamedDigest digest : digests) {
            if (digest.jcaDigestAlgorithm.equalsIgnoreCase(jcaDigestAlgorithm)) {
                return digest.digest;
            }
        }
        return null;
    }

    public static List<CentralDirectoryRecord> parseZipCentralDirectory(
            DataSource apk,
            ApkUtils.ZipSections apkSections)
                    throws IOException, ApkFormatException {
        // Read the ZIP Central Directory
        long cdSizeBytes = apkSections.getZipCentralDirectorySizeBytes();
        if (cdSizeBytes > Integer.MAX_VALUE) {
            throw new ApkFormatException("ZIP Central Directory too large: " + cdSizeBytes);
        }
        long cdOffset = apkSections.getZipCentralDirectoryOffset();
        ByteBuffer cd = apk.getByteBuffer(cdOffset, (int) cdSizeBytes);
        cd.order(ByteOrder.LITTLE_ENDIAN);

        // Parse the ZIP Central Directory
        int expectedCdRecordCount = apkSections.getZipCentralDirectoryRecordCount();
        List<CentralDirectoryRecord> cdRecords = new ArrayList<>(expectedCdRecordCount);
        for (int i = 0; i < expectedCdRecordCount; i++) {
            CentralDirectoryRecord cdRecord;
            int offsetInsideCd = cd.position();
            try {
                cdRecord = CentralDirectoryRecord.getRecord(cd);
            } catch (ZipFormatException e) {
                throw new ApkFormatException(
                        "Malformed ZIP Central Directory record #" + (i + 1)
                                + " at file offset " + (cdOffset + offsetInsideCd),
                        e);
            }
            String entryName = cdRecord.getName();
            if (entryName.endsWith("/")) {
                // Ignore directory entries
                continue;
            }
            cdRecords.add(cdRecord);
        }
        // There may be more data in Central Directory, but we don't warn or throw because Android
        // ignores unused CD data.

        return cdRecords;
    }

    /**
     * Returns {@code true} if the provided JAR entry must be mentioned in signed JAR archive's
     * manifest for the APK to verify on Android.
     */
    private static boolean isJarEntryDigestNeededInManifest(String entryName) {
        // NOTE: This logic is different from what's required by the JAR signing scheme. This is
        // because Android's APK verification logic differs from that spec. In particular, JAR
        // signing spec includes into JAR manifest all files in subdirectories of META-INF and
        // any files inside META-INF not related to signatures.
        if (entryName.startsWith("META-INF/")) {
            return false;
        }
        return !entryName.endsWith("/");
    }

    private static Set<Signer> verifyJarEntriesAgainstManifestAndSigners(
            DataSource apk,
            long cdOffsetInApk,
            Collection<CentralDirectoryRecord> cdRecords,
            Map<String, ManifestParser.Section> entryNameToManifestSection,
            List<Signer> signers,
            int minSdkVersion,
            int maxSdkVersion,
            Result result) throws ApkFormatException, IOException, NoSuchAlgorithmException {
        // Iterate over APK contents as sequentially as possible to improve performance.
        List<CentralDirectoryRecord> cdRecordsSortedByLocalFileHeaderOffset =
                new ArrayList<>(cdRecords);
        Collections.sort(
                cdRecordsSortedByLocalFileHeaderOffset,
                CentralDirectoryRecord.BY_LOCAL_FILE_HEADER_OFFSET_COMPARATOR);
        Set<String> manifestEntryNamesMissingFromApk =
                new HashSet<>(entryNameToManifestSection.keySet());
        List<Signer> firstSignedEntrySigners = null;
        String firstSignedEntryName = null;
        for (CentralDirectoryRecord cdRecord : cdRecordsSortedByLocalFileHeaderOffset) {
            String entryName = cdRecord.getName();
            manifestEntryNamesMissingFromApk.remove(entryName);
            if (!isJarEntryDigestNeededInManifest(entryName)) {
                continue;
            }

            ManifestParser.Section manifestSection = entryNameToManifestSection.get(entryName);
            if (manifestSection == null) {
                result.addError(Issue.JAR_SIG_NO_ZIP_ENTRY_DIGEST_IN_MANIFEST, entryName);
                continue;
            }

            List<Signer> entrySigners = new ArrayList<>(signers.size());
            for (Signer signer : signers) {
                if (signer.getSigFileEntryNames().contains(entryName)) {
                    entrySigners.add(signer);
                }
            }
            if (entrySigners.isEmpty()) {
                result.addError(Issue.JAR_SIG_ZIP_ENTRY_NOT_SIGNED, entryName);
                continue;
            }
            if (firstSignedEntrySigners == null) {
                firstSignedEntrySigners = entrySigners;
                firstSignedEntryName = entryName;
            } else if (!entrySigners.equals(firstSignedEntrySigners)) {
                result.addError(
                        Issue.JAR_SIG_ZIP_ENTRY_SIGNERS_MISMATCH,
                        firstSignedEntryName,
                        getSignerNames(firstSignedEntrySigners),
                        entryName,
                        getSignerNames(entrySigners));
                continue;
            }

            List<NamedDigest> expectedDigests =
                    new ArrayList<>(
                            getDigestsToVerify(
                                    manifestSection, "-Digest", minSdkVersion, maxSdkVersion));
            if (expectedDigests.isEmpty()) {
                result.addError(Issue.JAR_SIG_NO_ZIP_ENTRY_DIGEST_IN_MANIFEST, entryName);
                continue;
            }

            MessageDigest[] mds = new MessageDigest[expectedDigests.size()];
            for (int i = 0; i < expectedDigests.size(); i++) {
                mds[i] = getMessageDigest(expectedDigests.get(i).jcaDigestAlgorithm);
            }

            try {
                LocalFileRecord.outputUncompressedData(
                        apk,
                        cdRecord,
                        cdOffsetInApk,
                        new MessageDigestSink(mds));
            } catch (ZipFormatException e) {
                throw new ApkFormatException("Malformed ZIP entry: " + entryName, e);
            } catch (IOException e) {
                throw new IOException("Failed to read entry: " + entryName, e);
            }

            for (int i = 0; i < expectedDigests.size(); i++) {
                NamedDigest expectedDigest = expectedDigests.get(i);
                byte[] actualDigest = mds[i].digest();
                if (!Arrays.equals(expectedDigest.digest, actualDigest)) {
                    result.addError(
                            Issue.JAR_SIG_ZIP_ENTRY_DIGEST_DID_NOT_VERIFY,
                            entryName,
                            expectedDigest.jcaDigestAlgorithm,
                            V1SchemeSigner.MANIFEST_ENTRY_NAME,
                            Base64.getEncoder().encodeToString(actualDigest),
                            Base64.getEncoder().encodeToString(expectedDigest.digest));
                }
            }
        }

        if (firstSignedEntrySigners == null) {
            result.addError(Issue.JAR_SIG_NO_SIGNED_ZIP_ENTRIES);
            return Collections.emptySet();
        } else {
            return new HashSet<>(firstSignedEntrySigners);
        }
    }

    private static List<String> getSignerNames(List<Signer> signers) {
        if (signers.isEmpty()) {
            return Collections.emptyList();
        }
        List<String> result = new ArrayList<>(signers.size());
        for (Signer signer : signers) {
            result.add(signer.getName());
        }
        return result;
    }

    private static MessageDigest getMessageDigest(String algorithm)
            throws NoSuchAlgorithmException {
        return MessageDigest.getInstance(algorithm);
    }

    private static byte[] digest(String algorithm, byte[] data, int offset, int length)
            throws NoSuchAlgorithmException {
        MessageDigest md = getMessageDigest(algorithm);
        md.update(data, offset, length);
        return md.digest();
    }

    private static byte[] digest(String algorithm, byte[] data) throws NoSuchAlgorithmException {
        return getMessageDigest(algorithm).digest(data);
    }

    private static class NamedDigest {
        private final String jcaDigestAlgorithm;
        private final byte[] digest;

        private NamedDigest(String jcaDigestAlgorithm, byte[] digest) {
            this.jcaDigestAlgorithm = jcaDigestAlgorithm;
            this.digest = digest;
        }
    }

    public static class Result {

        /** Whether the APK's JAR signature verifies. */
        public boolean verified;

        /** List of APK's signers. These signers are used by Android. */
        public final List<SignerInfo> signers = new ArrayList<>();

        /**
         * Signers encountered in the APK but not included in the set of the APK's signers. These
         * signers are ignored by Android.
         */
        public final List<SignerInfo> ignoredSigners = new ArrayList<>();

        private final List<IssueWithParams> mWarnings = new ArrayList<>();
        private final List<IssueWithParams> mErrors = new ArrayList<>();

        private boolean containsErrors() {
            if (!mErrors.isEmpty()) {
                return true;
            }
            for (SignerInfo signer : signers) {
                if (signer.containsErrors()) {
                    return true;
                }
            }
            return false;
        }

        private void addError(Issue msg, Object... parameters) {
            mErrors.add(new IssueWithParams(msg, parameters));
        }

        private void addWarning(Issue msg, Object... parameters) {
            mWarnings.add(new IssueWithParams(msg, parameters));
        }

        public List<IssueWithParams> getErrors() {
            return mErrors;
        }

        public List<IssueWithParams> getWarnings() {
            return mWarnings;
        }

        public static class SignerInfo {
            public final String name;
            public final String signatureFileName;
            public final String signatureBlockFileName;
            public final List<X509Certificate> certChain = new ArrayList<>();

            private final List<IssueWithParams> mWarnings = new ArrayList<>();
            private final List<IssueWithParams> mErrors = new ArrayList<>();

            private SignerInfo(
                    String name, String signatureBlockFileName, String signatureFileName) {
                this.name = name;
                this.signatureBlockFileName = signatureBlockFileName;
                this.signatureFileName = signatureFileName;
            }

            private boolean containsErrors() {
                return !mErrors.isEmpty();
            }

            private void addError(Issue msg, Object... parameters) {
                mErrors.add(new IssueWithParams(msg, parameters));
            }

            private void addWarning(Issue msg, Object... parameters) {
                mWarnings.add(new IssueWithParams(msg, parameters));
            }

            public List<IssueWithParams> getErrors() {
                return mErrors;
            }

            public List<IssueWithParams> getWarnings() {
                return mWarnings;
            }
        }
    }
}
