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);
}
}
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);
}
Aggregations