Search in sources :

Example 16 with ZipFormatException

use of com.android.apksig.zip.ZipFormatException 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)

Example 17 with ZipFormatException

use of com.android.apksig.zip.ZipFormatException in project apksig by venshine.

the class ApkUtilsLite method findZipSections.

/**
 * Finds the main ZIP sections of the provided APK.
 *
 * @throws IOException if an I/O error occurred while reading the APK
 * @throws ZipFormatException if the APK is malformed
 */
public static ZipSections findZipSections(DataSource apk) throws IOException, ZipFormatException {
    Pair<ByteBuffer, Long> eocdAndOffsetInFile = ZipUtils.findZipEndOfCentralDirectoryRecord(apk);
    if (eocdAndOffsetInFile == null) {
        throw new ZipFormatException("ZIP End of Central Directory record not found");
    }
    ByteBuffer eocdBuf = eocdAndOffsetInFile.getFirst();
    long eocdOffset = eocdAndOffsetInFile.getSecond();
    eocdBuf.order(ByteOrder.LITTLE_ENDIAN);
    long cdStartOffset = ZipUtils.getZipEocdCentralDirectoryOffset(eocdBuf);
    if (cdStartOffset > eocdOffset) {
        throw new ZipFormatException("ZIP Central Directory start offset out of range: " + cdStartOffset + ". ZIP End of Central Directory offset: " + eocdOffset);
    }
    long cdSizeBytes = ZipUtils.getZipEocdCentralDirectorySizeBytes(eocdBuf);
    long cdEndOffset = cdStartOffset + cdSizeBytes;
    if (cdEndOffset > eocdOffset) {
        throw new ZipFormatException("ZIP Central Directory overlaps with End of Central Directory" + ". CD end: " + cdEndOffset + ", EoCD start: " + eocdOffset);
    }
    int cdRecordCount = ZipUtils.getZipEocdCentralDirectoryTotalRecordCount(eocdBuf);
    return new ZipSections(cdStartOffset, cdSizeBytes, cdRecordCount, eocdOffset, eocdBuf);
}
Also used : ZipFormatException(com.android.apksig.zip.ZipFormatException) ByteBuffer(java.nio.ByteBuffer) ZipSections(com.android.apksig.zip.ZipSections)

Aggregations

ZipFormatException (com.android.apksig.zip.ZipFormatException)17 ApkFormatException (com.android.apksig.apk.ApkFormatException)11 CentralDirectoryRecord (com.android.apksig.internal.zip.CentralDirectoryRecord)10 IOException (java.io.IOException)7 ByteBuffer (java.nio.ByteBuffer)7 ArrayList (java.util.ArrayList)7 ApkUtils (com.android.apksig.apk.ApkUtils)5 EnumMap (java.util.EnumMap)5 ApkSigResult (com.android.apksig.internal.apk.ApkSigResult)4 HashMap (java.util.HashMap)4 HashSet (java.util.HashSet)4 ApkSigningBlockUtils (com.android.apksig.internal.apk.ApkSigningBlockUtils)3 ContentDigestAlgorithm (com.android.apksig.internal.apk.ContentDigestAlgorithm)3 SignatureNotFoundException (com.android.apksig.internal.apk.SignatureNotFoundException)3 Map (java.util.Map)3 SignatureInfo (com.android.apksig.internal.apk.SignatureInfo)2 DataSource (com.android.apksig.util.DataSource)2 ZipSections (com.android.apksig.zip.ZipSections)2 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)2 X509Certificate (java.security.cert.X509Certificate)2