Search in sources :

Example 36 with ApkFormatException

use of com.android.apksig.apk.ApkFormatException in project apksig by venshine.

the class V1SchemeVerifier method verifyJarEntriesAgainstManifestAndSigners.

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);
    List<Signer> firstSignedEntrySigners = null;
    String firstSignedEntryName = null;
    for (CentralDirectoryRecord cdRecord : cdRecordsSortedByLocalFileHeaderOffset) {
        String entryName = cdRecord.getName();
        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, DataSinks.asDataSink(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, V1SchemeConstants.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);
    }
}
Also used : CentralDirectoryRecord(com.android.apksig.internal.zip.CentralDirectoryRecord) ManifestParser(com.android.apksig.internal.jar.ManifestParser) ArrayList(java.util.ArrayList) ZipFormatException(com.android.apksig.zip.ZipFormatException) IOException(java.io.IOException) ApkFormatException(com.android.apksig.apk.ApkFormatException) MessageDigest(java.security.MessageDigest) HashSet(java.util.HashSet)

Aggregations

ApkFormatException (com.android.apksig.apk.ApkFormatException)36 IOException (java.io.IOException)18 ByteBuffer (java.nio.ByteBuffer)17 ArrayList (java.util.ArrayList)15 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)13 BufferUnderflowException (java.nio.BufferUnderflowException)12 ZipFormatException (com.android.apksig.zip.ZipFormatException)11 CertificateException (java.security.cert.CertificateException)11 ApkSigningBlockUtils (com.android.apksig.internal.apk.ApkSigningBlockUtils)9 CentralDirectoryRecord (com.android.apksig.internal.zip.CentralDirectoryRecord)9 X509Certificate (java.security.cert.X509Certificate)9 InvalidKeyException (java.security.InvalidKeyException)7 SignatureException (java.security.SignatureException)7 CertificateFactory (java.security.cert.CertificateFactory)7 SignatureAlgorithm (com.android.apksig.internal.apk.SignatureAlgorithm)6 GuaranteedEncodedFormX509Certificate (com.android.apksig.internal.util.GuaranteedEncodedFormX509Certificate)6 HashSet (java.util.HashSet)6 ApkSigResult (com.android.apksig.internal.apk.ApkSigResult)5 DataSource (com.android.apksig.util.DataSource)5 InvalidAlgorithmParameterException (java.security.InvalidAlgorithmParameterException)5