Search in sources :

Example 11 with DataSource

use of com.android.apksig.util.DataSource in project LSPatch by LSPosed.

the class SigningBlockUtils method extractAllSigners.

/**
 * Extracts all signing block entries except padding block.
 *
 * @param signingBlock APK v2 signing block containing: length prefix, signers (can include
 *     padding block), length postfix and APK sig v2 block magic.
 * @return list of block entry value and block entry id pairs.
 */
private static ImmutableList<Pair<byte[], Integer>> extractAllSigners(DataSource signingBlock) throws IOException {
    long wholeBlockSize = signingBlock.size();
    // Take the segment of the existing signing block without the length prefix (8 bytes)
    // at the beginning and the length and magic (24 bytes) at the end, so it is just the sequence
    // of length prefix id value pairs.
    DataSource lengthPrefixedIdValuePairsSource = signingBlock.slice(SIZE_OF_BLOCK_NUM_BYTES, wholeBlockSize - 2 * SIZE_OF_BLOCK_NUM_BYTES - MAGIC_NUM_BYTES);
    final int lengthAndIdByteCount = BLOCK_LENGTH_NUM_BYTES + BLOCK_ID_NUM_BYTES;
    ByteBuffer lengthAndId = ByteBuffer.allocate(lengthAndIdByteCount).order(LITTLE_ENDIAN);
    ImmutableList.Builder<Pair<byte[], Integer>> idValuePairs = ImmutableList.builder();
    for (int index = 0; index <= lengthPrefixedIdValuePairsSource.size() - lengthAndIdByteCount; ) {
        lengthPrefixedIdValuePairsSource.copyTo(index, lengthAndIdByteCount, lengthAndId);
        lengthAndId.flip();
        int blockLength = Ints.checkedCast(lengthAndId.getLong());
        int id = lengthAndId.getInt();
        lengthAndId.clear();
        if (id != VERITY_PADDING_BLOCK_ID) {
            int blockValueSize = blockLength - BLOCK_ID_NUM_BYTES;
            ByteBuffer blockValue = ByteBuffer.allocate(blockValueSize);
            lengthPrefixedIdValuePairsSource.copyTo(index + BLOCK_LENGTH_NUM_BYTES + BLOCK_ID_NUM_BYTES, blockValueSize, blockValue);
            idValuePairs.add(Pair.of(blockValue.array(), id));
        }
        index += blockLength + BLOCK_LENGTH_NUM_BYTES;
    }
    return idValuePairs.build();
}
Also used : ImmutableList(com.google.common.collect.ImmutableList) ByteBuffer(java.nio.ByteBuffer) DataSource(com.android.apksig.util.DataSource) Pair(com.android.apksig.internal.util.Pair)

Example 12 with DataSource

use of com.android.apksig.util.DataSource in project bundletool by google.

the class BuildApksCommand method getLineageFromInputFile.

/**
 * Extracts the Signing Certificate Lineage from the provided lineage or APK file.
 */
private static SigningCertificateLineage getLineageFromInputFile(File inputLineageFile) {
    try (RandomAccessFile f = new RandomAccessFile(inputLineageFile, "r")) {
        if (f.length() < 4) {
            throw CommandExecutionException.builder().withInternalMessage("The input file is not a valid lineage file.").build();
        }
        DataSource apk = DataSources.asDataSource(f);
        int magicValue = apk.getByteBuffer(0, 4).order(ByteOrder.LITTLE_ENDIAN).getInt();
        if (magicValue == SigningCertificateLineage.MAGIC) {
            return SigningCertificateLineage.readFromFile(inputLineageFile);
        } else if (magicValue == ZIP_MAGIC) {
            return SigningCertificateLineage.readFromApkFile(inputLineageFile);
        } else {
            throw CommandExecutionException.builder().withInternalMessage("The input file is not a valid lineage file.").build();
        }
    } catch (IOException | ApkFormatException | IllegalArgumentException e) {
        throw CommandExecutionException.builder().withCause(e).build();
    }
}
Also used : RandomAccessFile(java.io.RandomAccessFile) ApkFormatException(com.android.apksig.apk.ApkFormatException) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) DataSource(com.android.apksig.util.DataSource)

Example 13 with DataSource

use of com.android.apksig.util.DataSource in project apksig by venshine.

the class ApkSigner method sign.

private void sign(DataSource inputApk, DataSink outputApkOut, DataSource outputApkIn) throws IOException, ApkFormatException, NoSuchAlgorithmException, InvalidKeyException, SignatureException {
    // Step 1. Find input APK's main ZIP sections
    ApkUtils.ZipSections inputZipSections;
    try {
        inputZipSections = ApkUtils.findZipSections(inputApk);
    } catch (ZipFormatException e) {
        throw new ApkFormatException("Malformed APK: not a ZIP archive", e);
    }
    long inputApkSigningBlockOffset = -1;
    DataSource inputApkSigningBlock = null;
    try {
        ApkUtils.ApkSigningBlock apkSigningBlockInfo = ApkUtils.findApkSigningBlock(inputApk, inputZipSections);
        inputApkSigningBlockOffset = apkSigningBlockInfo.getStartOffset();
        inputApkSigningBlock = apkSigningBlockInfo.getContents();
    } catch (ApkSigningBlockNotFoundException e) {
    // Input APK does not contain an APK Signing Block. That's OK. APKs are not required to
    // contain this block. It's only needed if the APK is signed using APK Signature Scheme
    // v2 and/or v3.
    }
    DataSource inputApkLfhSection = inputApk.slice(0, (inputApkSigningBlockOffset != -1) ? inputApkSigningBlockOffset : inputZipSections.getZipCentralDirectoryOffset());
    // Step 2. Parse the input APK's ZIP Central Directory
    ByteBuffer inputCd = getZipCentralDirectory(inputApk, inputZipSections);
    List<CentralDirectoryRecord> inputCdRecords = parseZipCentralDirectory(inputCd, inputZipSections);
    List<Hints.PatternWithRange> pinPatterns = extractPinPatterns(inputCdRecords, inputApkLfhSection);
    List<Hints.ByteRange> pinByteRanges = pinPatterns == null ? null : new ArrayList<>();
    // Step 3. Obtain a signer engine instance
    ApkSignerEngine signerEngine;
    if (mSignerEngine != null) {
        // Use the provided signer engine
        signerEngine = mSignerEngine;
    } else {
        // Construct a signer engine from the provided parameters
        int minSdkVersion;
        if (mMinSdkVersion != null) {
            // No need to extract minSdkVersion from the APK's AndroidManifest.xml
            minSdkVersion = mMinSdkVersion;
        } else {
            // Need to extract minSdkVersion from the APK's AndroidManifest.xml
            minSdkVersion = getMinSdkVersionFromApk(inputCdRecords, inputApkLfhSection);
        }
        List<DefaultApkSignerEngine.SignerConfig> engineSignerConfigs = new ArrayList<>(mSignerConfigs.size());
        for (SignerConfig signerConfig : mSignerConfigs) {
            engineSignerConfigs.add(new DefaultApkSignerEngine.SignerConfig.Builder(signerConfig.getName(), signerConfig.getPrivateKey(), signerConfig.getCertificates(), signerConfig.getDeterministicDsaSigning()).build());
        }
        DefaultApkSignerEngine.Builder signerEngineBuilder = new DefaultApkSignerEngine.Builder(engineSignerConfigs, minSdkVersion).setV1SigningEnabled(mV1SigningEnabled).setV2SigningEnabled(mV2SigningEnabled).setV3SigningEnabled(mV3SigningEnabled).setVerityEnabled(mVerityEnabled).setDebuggableApkPermitted(mDebuggableApkPermitted).setOtherSignersSignaturesPreserved(mOtherSignersSignaturesPreserved).setSigningCertificateLineage(mSigningCertificateLineage);
        if (mCreatedBy != null) {
            signerEngineBuilder.setCreatedBy(mCreatedBy);
        }
        if (mSourceStampSignerConfig != null) {
            signerEngineBuilder.setStampSignerConfig(new DefaultApkSignerEngine.SignerConfig.Builder(mSourceStampSignerConfig.getName(), mSourceStampSignerConfig.getPrivateKey(), mSourceStampSignerConfig.getCertificates(), mSourceStampSignerConfig.getDeterministicDsaSigning()).build());
        }
        if (mSourceStampSigningCertificateLineage != null) {
            signerEngineBuilder.setSourceStampSigningCertificateLineage(mSourceStampSigningCertificateLineage);
        }
        signerEngine = signerEngineBuilder.build();
    }
    // Step 4. Provide the signer engine with the input APK's APK Signing Block (if any)
    if (inputApkSigningBlock != null) {
        signerEngine.inputApkSigningBlock(inputApkSigningBlock);
    }
    // Step 5. Iterate over input APK's entries and output the Local File Header + data of those
    // entries which need to be output. Entries are iterated in the order in which their Local
    // File Header records are stored in the file. This is to achieve better data locality in
    // case Central Directory entries are in the wrong order.
    List<CentralDirectoryRecord> inputCdRecordsSortedByLfhOffset = new ArrayList<>(inputCdRecords);
    Collections.sort(inputCdRecordsSortedByLfhOffset, CentralDirectoryRecord.BY_LOCAL_FILE_HEADER_OFFSET_COMPARATOR);
    int lastModifiedDateForNewEntries = -1;
    int lastModifiedTimeForNewEntries = -1;
    long inputOffset = 0;
    long outputOffset = 0;
    byte[] sourceStampCertificateDigest = null;
    Map<String, CentralDirectoryRecord> outputCdRecordsByName = new HashMap<>(inputCdRecords.size());
    for (final CentralDirectoryRecord inputCdRecord : inputCdRecordsSortedByLfhOffset) {
        String entryName = inputCdRecord.getName();
        if (Hints.PIN_BYTE_RANGE_ZIP_ENTRY_NAME.equals(entryName)) {
            // We'll re-add below if needed.
            continue;
        }
        if (SOURCE_STAMP_CERTIFICATE_HASH_ZIP_ENTRY_NAME.equals(entryName)) {
            try {
                sourceStampCertificateDigest = LocalFileRecord.getUncompressedData(inputApkLfhSection, inputCdRecord, inputApkLfhSection.size());
            } catch (ZipFormatException ex) {
                throw new ApkFormatException("Bad source stamp entry");
            }
            // Existing source stamp is handled below as needed.
            continue;
        }
        ApkSignerEngine.InputJarEntryInstructions entryInstructions = signerEngine.inputJarEntry(entryName);
        boolean shouldOutput;
        switch(entryInstructions.getOutputPolicy()) {
            case OUTPUT:
                shouldOutput = true;
                break;
            case OUTPUT_BY_ENGINE:
            case SKIP:
                shouldOutput = false;
                break;
            default:
                throw new RuntimeException("Unknown output policy: " + entryInstructions.getOutputPolicy());
        }
        long inputLocalFileHeaderStartOffset = inputCdRecord.getLocalFileHeaderOffset();
        if (inputLocalFileHeaderStartOffset > inputOffset) {
            // Unprocessed data in input starting at inputOffset and ending and the start of
            // this record's LFH. We output this data verbatim because this signer is supposed
            // to preserve as much of input as possible.
            long chunkSize = inputLocalFileHeaderStartOffset - inputOffset;
            inputApkLfhSection.feed(inputOffset, chunkSize, outputApkOut);
            outputOffset += chunkSize;
            inputOffset = inputLocalFileHeaderStartOffset;
        }
        LocalFileRecord inputLocalFileRecord;
        try {
            inputLocalFileRecord = LocalFileRecord.getRecord(inputApkLfhSection, inputCdRecord, inputApkLfhSection.size());
        } catch (ZipFormatException e) {
            throw new ApkFormatException("Malformed ZIP entry: " + inputCdRecord.getName(), e);
        }
        inputOffset += inputLocalFileRecord.getSize();
        ApkSignerEngine.InspectJarEntryRequest inspectEntryRequest = entryInstructions.getInspectJarEntryRequest();
        if (inspectEntryRequest != null) {
            fulfillInspectInputJarEntryRequest(inputApkLfhSection, inputLocalFileRecord, inspectEntryRequest);
        }
        if (shouldOutput) {
            // Find the max value of last modified, to be used for new entries added by the
            // signer.
            int lastModifiedDate = inputCdRecord.getLastModificationDate();
            int lastModifiedTime = inputCdRecord.getLastModificationTime();
            if ((lastModifiedDateForNewEntries == -1) || (lastModifiedDate > lastModifiedDateForNewEntries) || ((lastModifiedDate == lastModifiedDateForNewEntries) && (lastModifiedTime > lastModifiedTimeForNewEntries))) {
                lastModifiedDateForNewEntries = lastModifiedDate;
                lastModifiedTimeForNewEntries = lastModifiedTime;
            }
            inspectEntryRequest = signerEngine.outputJarEntry(entryName);
            if (inspectEntryRequest != null) {
                fulfillInspectInputJarEntryRequest(inputApkLfhSection, inputLocalFileRecord, inspectEntryRequest);
            }
            // Output entry's Local File Header + data
            long outputLocalFileHeaderOffset = outputOffset;
            OutputSizeAndDataOffset outputLfrResult = outputInputJarEntryLfhRecordPreservingDataAlignment(inputApkLfhSection, inputLocalFileRecord, outputApkOut, outputLocalFileHeaderOffset);
            outputOffset += outputLfrResult.outputBytes;
            long outputDataOffset = outputLocalFileHeaderOffset + outputLfrResult.dataOffsetBytes;
            if (pinPatterns != null) {
                boolean pinFileHeader = false;
                for (Hints.PatternWithRange pinPattern : pinPatterns) {
                    if (pinPattern.matcher(inputCdRecord.getName()).matches()) {
                        Hints.ByteRange dataRange = new Hints.ByteRange(outputDataOffset, outputOffset);
                        Hints.ByteRange pinRange = pinPattern.ClampToAbsoluteByteRange(dataRange);
                        if (pinRange != null) {
                            pinFileHeader = true;
                            pinByteRanges.add(pinRange);
                        }
                    }
                }
                if (pinFileHeader) {
                    pinByteRanges.add(new Hints.ByteRange(outputLocalFileHeaderOffset, outputDataOffset));
                }
            }
            // Enqueue entry's Central Directory record for output
            CentralDirectoryRecord outputCdRecord;
            if (outputLocalFileHeaderOffset == inputLocalFileRecord.getStartOffsetInArchive()) {
                outputCdRecord = inputCdRecord;
            } else {
                outputCdRecord = inputCdRecord.createWithModifiedLocalFileHeaderOffset(outputLocalFileHeaderOffset);
            }
            outputCdRecordsByName.put(entryName, outputCdRecord);
        }
    }
    long inputLfhSectionSize = inputApkLfhSection.size();
    if (inputOffset < inputLfhSectionSize) {
        // Unprocessed data in input starting at inputOffset and ending and the end of the input
        // APK's LFH section. We output this data verbatim because this signer is supposed
        // to preserve as much of input as possible.
        long chunkSize = inputLfhSectionSize - inputOffset;
        inputApkLfhSection.feed(inputOffset, chunkSize, outputApkOut);
        outputOffset += chunkSize;
        inputOffset = inputLfhSectionSize;
    }
    // Step 6. Sort output APK's Central Directory records in the order in which they should
    // appear in the output
    List<CentralDirectoryRecord> outputCdRecords = new ArrayList<>(inputCdRecords.size() + 10);
    for (CentralDirectoryRecord inputCdRecord : inputCdRecords) {
        String entryName = inputCdRecord.getName();
        CentralDirectoryRecord outputCdRecord = outputCdRecordsByName.get(entryName);
        if (outputCdRecord != null) {
            outputCdRecords.add(outputCdRecord);
        }
    }
    if (lastModifiedDateForNewEntries == -1) {
        // Jan 1 2009 (DOS)
        lastModifiedDateForNewEntries = 0x3a21;
        lastModifiedTimeForNewEntries = 0;
    }
    // records.
    if (signerEngine.isEligibleForSourceStamp()) {
        byte[] uncompressedData = signerEngine.generateSourceStampCertificateDigest();
        if (mForceSourceStampOverwrite || sourceStampCertificateDigest == null || Arrays.equals(uncompressedData, sourceStampCertificateDigest)) {
            outputOffset += outputDataToOutputApk(SOURCE_STAMP_CERTIFICATE_HASH_ZIP_ENTRY_NAME, uncompressedData, outputOffset, outputCdRecords, lastModifiedTimeForNewEntries, lastModifiedDateForNewEntries, outputApkOut);
        } else {
            throw new ApkFormatException(String.format("Cannot generate SourceStamp. APK contains an existing entry with" + " the name: %s, and it is different than the provided source" + " stamp certificate", SOURCE_STAMP_CERTIFICATE_HASH_ZIP_ENTRY_NAME));
        }
    }
    // This has to be before the step 8 so that the file is signed.
    if (pinByteRanges != null) {
        // Covers JAR signature and zip central dir entry.
        // The signature files don't have to be pinned, but pinning them isn't that wasteful
        // since the total size is small.
        pinByteRanges.add(new Hints.ByteRange(outputOffset, Long.MAX_VALUE));
        String entryName = Hints.PIN_BYTE_RANGE_ZIP_ENTRY_NAME;
        byte[] uncompressedData = Hints.encodeByteRangeList(pinByteRanges);
        requestOutputEntryInspection(signerEngine, entryName, uncompressedData);
        outputOffset += outputDataToOutputApk(entryName, uncompressedData, outputOffset, outputCdRecords, lastModifiedTimeForNewEntries, lastModifiedDateForNewEntries, outputApkOut);
    }
    // Step 8. Generate and output JAR signatures, if necessary. This may output more Local File
    // Header + data entries and add to the list of output Central Directory records.
    ApkSignerEngine.OutputJarSignatureRequest outputJarSignatureRequest = signerEngine.outputJarEntries();
    if (outputJarSignatureRequest != null) {
        for (ApkSignerEngine.OutputJarSignatureRequest.JarEntry entry : outputJarSignatureRequest.getAdditionalJarEntries()) {
            String entryName = entry.getName();
            byte[] uncompressedData = entry.getData();
            requestOutputEntryInspection(signerEngine, entryName, uncompressedData);
            outputOffset += outputDataToOutputApk(entryName, uncompressedData, outputOffset, outputCdRecords, lastModifiedTimeForNewEntries, lastModifiedDateForNewEntries, outputApkOut);
        }
        outputJarSignatureRequest.done();
    }
    // Step 9. Construct output ZIP Central Directory in an in-memory buffer
    long outputCentralDirSizeBytes = 0;
    for (CentralDirectoryRecord record : outputCdRecords) {
        outputCentralDirSizeBytes += record.getSize();
    }
    if (outputCentralDirSizeBytes > Integer.MAX_VALUE) {
        throw new IOException("Output ZIP Central Directory too large: " + outputCentralDirSizeBytes + " bytes");
    }
    ByteBuffer outputCentralDir = ByteBuffer.allocate((int) outputCentralDirSizeBytes);
    for (CentralDirectoryRecord record : outputCdRecords) {
        record.copyTo(outputCentralDir);
    }
    outputCentralDir.flip();
    DataSource outputCentralDirDataSource = new ByteBufferDataSource(outputCentralDir);
    long outputCentralDirStartOffset = outputOffset;
    int outputCentralDirRecordCount = outputCdRecords.size();
    // Step 10. Construct output ZIP End of Central Directory record in an in-memory buffer
    ByteBuffer outputEocd = EocdRecord.createWithModifiedCentralDirectoryInfo(inputZipSections.getZipEndOfCentralDirectory(), outputCentralDirRecordCount, outputCentralDirDataSource.size(), outputCentralDirStartOffset);
    // Step 11. Generate and output APK Signature Scheme v2 and/or v3 signatures and/or
    // SourceStamp signatures, if necessary.
    // This may insert an APK Signing Block just before the output's ZIP Central Directory
    ApkSignerEngine.OutputApkSigningBlockRequest2 outputApkSigningBlockRequest = signerEngine.outputZipSections2(outputApkIn, outputCentralDirDataSource, DataSources.asDataSource(outputEocd));
    if (outputApkSigningBlockRequest != null) {
        int padding = outputApkSigningBlockRequest.getPaddingSizeBeforeApkSigningBlock();
        outputApkOut.consume(ByteBuffer.allocate(padding));
        byte[] outputApkSigningBlock = outputApkSigningBlockRequest.getApkSigningBlock();
        outputApkOut.consume(outputApkSigningBlock, 0, outputApkSigningBlock.length);
        ZipUtils.setZipEocdCentralDirectoryOffset(outputEocd, outputCentralDirStartOffset + padding + outputApkSigningBlock.length);
        outputApkSigningBlockRequest.done();
    }
    // Step 12. Output ZIP Central Directory and ZIP End of Central Directory
    outputCentralDirDataSource.feed(0, outputCentralDirDataSource.size(), outputApkOut);
    outputApkOut.consume(outputEocd);
    signerEngine.outputDone();
    // Step 13. Generate and output APK Signature Scheme v4 signatures, if necessary.
    if (mV4SigningEnabled) {
        signerEngine.signV4(outputApkIn, mOutputV4File, !mV4ErrorReportingEnabled);
    }
}
Also used : CentralDirectoryRecord(com.android.apksig.internal.zip.CentralDirectoryRecord) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) ZipFormatException(com.android.apksig.zip.ZipFormatException) ApkFormatException(com.android.apksig.apk.ApkFormatException) ByteBufferDataSource(com.android.apksig.internal.util.ByteBufferDataSource) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer) DataSource(com.android.apksig.util.DataSource) ByteBufferDataSource(com.android.apksig.internal.util.ByteBufferDataSource) LocalFileRecord(com.android.apksig.internal.zip.LocalFileRecord) ApkUtils(com.android.apksig.apk.ApkUtils) ApkSigningBlockNotFoundException(com.android.apksig.apk.ApkSigningBlockNotFoundException)

Example 14 with DataSource

use of com.android.apksig.util.DataSource in project apksig by venshine.

the class ApkSigner method sign.

/**
 * Signs the input APK and outputs the resulting signed APK. The input APK is not modified.
 *
 * @throws IOException if an I/O error is encountered while reading or writing the APKs
 * @throws ApkFormatException if the input APK is malformed
 * @throws NoSuchAlgorithmException if the APK signatures cannot be produced or verified because
 *     a required cryptographic algorithm implementation is missing
 * @throws InvalidKeyException if a signature could not be generated because a signing key is
 *     not suitable for generating the signature
 * @throws SignatureException if an error occurred while generating or verifying a signature
 * @throws IllegalStateException if this signer's configuration is missing required information
 *     or if the signing engine is in an invalid state.
 */
public void sign() throws IOException, ApkFormatException, NoSuchAlgorithmException, InvalidKeyException, SignatureException, IllegalStateException {
    Closeable in = null;
    DataSource inputApk;
    try {
        if (mInputApkDataSource != null) {
            inputApk = mInputApkDataSource;
        } else if (mInputApkFile != null) {
            RandomAccessFile inputFile = new RandomAccessFile(mInputApkFile, "r");
            in = inputFile;
            inputApk = DataSources.asDataSource(inputFile);
        } else {
            throw new IllegalStateException("Input APK not specified");
        }
        Closeable out = null;
        try {
            DataSink outputApkOut;
            DataSource outputApkIn;
            if (mOutputApkDataSink != null) {
                outputApkOut = mOutputApkDataSink;
                outputApkIn = mOutputApkDataSource;
            } else if (mOutputApkFile != null) {
                RandomAccessFile outputFile = new RandomAccessFile(mOutputApkFile, "rw");
                out = outputFile;
                outputFile.setLength(0);
                outputApkOut = DataSinks.asDataSink(outputFile);
                outputApkIn = DataSources.asDataSource(outputFile);
            } else {
                throw new IllegalStateException("Output APK not specified");
            }
            sign(inputApk, outputApkOut, outputApkIn);
        } finally {
            if (out != null) {
                out.close();
            }
        }
    } finally {
        if (in != null) {
            in.close();
        }
    }
}
Also used : ReadableDataSink(com.android.apksig.util.ReadableDataSink) DataSink(com.android.apksig.util.DataSink) RandomAccessFile(java.io.RandomAccessFile) Closeable(java.io.Closeable) DataSource(com.android.apksig.util.DataSource) ByteBufferDataSource(com.android.apksig.internal.util.ByteBufferDataSource)

Example 15 with DataSource

use of com.android.apksig.util.DataSource in project apksig by venshine.

the class ApkSignerTool method getLineageFromInputFile.

/**
 * Extracts the Signing Certificate Lineage from the provided lineage or APK file.
 */
private static SigningCertificateLineage getLineageFromInputFile(File inputLineageFile) throws ParameterException {
    try (RandomAccessFile f = new RandomAccessFile(inputLineageFile, "r")) {
        if (f.length() < 4) {
            throw new ParameterException("The input file is not a valid lineage file.");
        }
        DataSource apk = DataSources.asDataSource(f);
        int magicValue = apk.getByteBuffer(0, 4).order(ByteOrder.LITTLE_ENDIAN).getInt();
        if (magicValue == SigningCertificateLineage.MAGIC) {
            return SigningCertificateLineage.readFromFile(inputLineageFile);
        } else if (magicValue == ZIP_MAGIC) {
            return SigningCertificateLineage.readFromApkFile(inputLineageFile);
        } else {
            throw new ParameterException("The input file is not a valid lineage file.");
        }
    } catch (IOException | ApkFormatException | IllegalArgumentException e) {
        throw new ParameterException(e.getMessage());
    }
}
Also used : RandomAccessFile(java.io.RandomAccessFile) ApkFormatException(com.android.apksig.apk.ApkFormatException) IOException(java.io.IOException) DataSource(com.android.apksig.util.DataSource)

Aggregations

DataSource (com.android.apksig.util.DataSource)29 RandomAccessFile (java.io.RandomAccessFile)11 Test (org.junit.Test)10 ByteBuffer (java.nio.ByteBuffer)7 ArrayList (java.util.ArrayList)6 ApkFormatException (com.android.apksig.apk.ApkFormatException)5 ApkSigningBlockUtils (com.android.apksig.internal.apk.ApkSigningBlockUtils)5 IOException (java.io.IOException)5 ApkUtils (com.android.apksig.apk.ApkUtils)4 ByteBufferDataSource (com.android.apksig.internal.util.ByteBufferDataSource)4 SignerConfig (com.android.apksig.SigningCertificateLineage.SignerConfig)3 CentralDirectoryRecord (com.android.apksig.internal.zip.CentralDirectoryRecord)3 DataSink (com.android.apksig.util.DataSink)3 File (java.io.File)3 MessageDigest (java.security.MessageDigest)3 ApkSigningBlockNotFoundException (com.android.apksig.apk.ApkSigningBlockNotFoundException)2 SignatureInfo (com.android.apksig.internal.apk.SignatureInfo)2 ChainedDataSource (com.android.apksig.internal.util.ChainedDataSource)2 Pair (com.android.apksig.internal.util.Pair)2 ZipFormatException (com.android.apksig.zip.ZipFormatException)2