use of com.android.apksig.util.DataSource in project LSPatch by LSPosed.
the class SigningBlockUtils method extractBlock.
/**
* Extract a block with the given id from the APK. If there is more than one block with the same
* ID, the first block will be returned. If there are no block with the give id, {@code null} will
* be returned.
*
* @param apk APK file
* @param blockId id of the block to be extracted.
*/
@Nullable
public static ByteBuffer extractBlock(File apk, int blockId) throws IOException, ZipFormatException, ApkSigningBlockNotFoundException {
try (RandomAccessFile file = new RandomAccessFile(apk, "r")) {
DataSource apkDataSource = DataSources.asDataSource(file);
ApkSigningBlock signingBlockInfo = ApkUtils.findApkSigningBlock(apkDataSource, ApkUtils.findZipSections(apkDataSource));
DataSource wholeV2Block = signingBlockInfo.getContents();
final int lengthAndIdByteCount = BLOCK_LENGTH_NUM_BYTES + BLOCK_ID_NUM_BYTES;
DataSource signingBlock = wholeV2Block.slice(SIZE_OF_BLOCK_NUM_BYTES, wholeV2Block.size() - SIZE_OF_BLOCK_NUM_BYTES - MAGIC_NUM_BYTES);
ByteBuffer lengthAndId = ByteBuffer.allocate(lengthAndIdByteCount).order(ByteOrder.LITTLE_ENDIAN);
for (int index = 0; index <= signingBlock.size() - lengthAndIdByteCount; ) {
signingBlock.copyTo(index, lengthAndIdByteCount, lengthAndId);
lengthAndId.flip();
int blockLength = (int) lengthAndId.getLong();
int id = lengthAndId.getInt();
lengthAndId.flip();
if (id == blockId) {
ByteBuffer block = ByteBuffer.allocate(blockLength - BLOCK_ID_NUM_BYTES);
signingBlock.copyTo(index + lengthAndIdByteCount, blockLength - BLOCK_ID_NUM_BYTES, block);
block.flip();
return block;
}
index += blockLength + BLOCK_LENGTH_NUM_BYTES;
}
return null;
}
}
use of com.android.apksig.util.DataSource in project apksig by venshine.
the class ApkSigningBlockUtils method computeOneMbChunkContentDigests.
static void computeOneMbChunkContentDigests(RunnablesExecutor executor, Set<ContentDigestAlgorithm> digestAlgorithms, DataSource[] contents, Map<ContentDigestAlgorithm, byte[]> outputContentDigests) throws NoSuchAlgorithmException, DigestException {
long chunkCountLong = 0;
for (DataSource input : contents) {
chunkCountLong += getChunkCount(input.size(), CONTENT_DIGESTED_CHUNK_MAX_SIZE_BYTES);
}
if (chunkCountLong > Integer.MAX_VALUE) {
throw new DigestException("Input too long: " + chunkCountLong + " chunks");
}
int chunkCount = (int) chunkCountLong;
List<ChunkDigests> chunkDigestsList = new ArrayList<>(digestAlgorithms.size());
for (ContentDigestAlgorithm algorithms : digestAlgorithms) {
chunkDigestsList.add(new ChunkDigests(algorithms, chunkCount));
}
ChunkSupplier chunkSupplier = new ChunkSupplier(contents);
executor.execute(() -> new ChunkDigester(chunkSupplier, chunkDigestsList));
// Compute and write out final digest for each algorithm.
for (ChunkDigests chunkDigests : chunkDigestsList) {
MessageDigest messageDigest = chunkDigests.createMessageDigest();
outputContentDigests.put(chunkDigests.algorithm, messageDigest.digest(chunkDigests.concatOfDigestsOfChunks));
}
}
use of com.android.apksig.util.DataSource in project apksig by venshine.
the class ApkUtils method getAndroidManifest.
/**
* Returns the contents of the APK's {@code AndroidManifest.xml}.
*
* @throws IOException if an I/O error occurs while reading the APK
* @throws ApkFormatException if the APK is malformed
*/
public static ByteBuffer getAndroidManifest(DataSource apk) throws IOException, ApkFormatException {
ZipSections zipSections;
try {
zipSections = findZipSections(apk);
} catch (ZipFormatException e) {
throw new ApkFormatException("Not a valid ZIP archive", e);
}
List<CentralDirectoryRecord> cdRecords = V1SchemeVerifier.parseZipCentralDirectory(apk, zipSections);
CentralDirectoryRecord androidManifestCdRecord = null;
for (CentralDirectoryRecord cdRecord : cdRecords) {
if (ANDROID_MANIFEST_ZIP_ENTRY_NAME.equals(cdRecord.getName())) {
androidManifestCdRecord = cdRecord;
break;
}
}
if (androidManifestCdRecord == null) {
throw new ApkFormatException("Missing " + ANDROID_MANIFEST_ZIP_ENTRY_NAME);
}
DataSource lfhSection = apk.slice(0, zipSections.getZipCentralDirectoryOffset());
try {
return ByteBuffer.wrap(LocalFileRecord.getUncompressedData(lfhSection, androidManifestCdRecord, lfhSection.size()));
} catch (ZipFormatException e) {
throw new ApkFormatException("Failed to read " + ANDROID_MANIFEST_ZIP_ENTRY_NAME, e);
}
}
use of com.android.apksig.util.DataSource in project apksig by venshine.
the class SigningCertificateLineageTest method testLineageFromAPKContainsExpectedSigners.
@Test
public void testLineageFromAPKContainsExpectedSigners() throws Exception {
SignerConfig firstSigner = getSignerConfigFromResources(FIRST_RSA_2048_SIGNER_RESOURCE_NAME);
SignerConfig secondSigner = getSignerConfigFromResources(SECOND_RSA_2048_SIGNER_RESOURCE_NAME);
SignerConfig thirdSigner = getSignerConfigFromResources(THIRD_RSA_2048_SIGNER_RESOURCE_NAME);
List<SignerConfig> expectedSigners = Arrays.asList(firstSigner, secondSigner, thirdSigner);
DataSource apkDataSource = Resources.toDataSource(getClass(), "v1v2v3-with-rsa-2048-lineage-3-signers.apk");
SigningCertificateLineage lineageFromApk = SigningCertificateLineage.readFromApkDataSource(apkDataSource);
assertLineageContainsExpectedSigners(lineageFromApk, expectedSigners);
}
use of com.android.apksig.util.DataSource in project apksig by venshine.
the class SigningCertificateLineageTest method testLineageFromAPKWithInvalidZipCDSizeFails.
@Test(expected = ApkFormatException.class)
public void testLineageFromAPKWithInvalidZipCDSizeFails() throws Exception {
// This test verifies that attempting to read the lineage from an APK where the zip
// sections cannot be parsed fails. This APK is based off the
// v1v2v3-with-rsa-2048-lineage-3-signers.apk with a modified CD size in the EoCD.
DataSource apkDataSource = Resources.toDataSource(getClass(), "v1v2v3-with-rsa-2048-lineage-3-signers-invalid-zip.apk");
SigningCertificateLineage.readFromApkDataSource(apkDataSource);
}
Aggregations