Search in sources :

Example 6 with ContentDigestAlgorithm

use of com.android.apksig.internal.apk.ContentDigestAlgorithm in project apksig by venshine.

the class V4SchemeSigner method generateV4Signature.

/**
 * Generate v4 signature and hash tree for a given APK.
 */
public static Pair<V4Signature, byte[]> generateV4Signature(DataSource apkContent, SignerConfig signerConfig) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
    // Salt has to stay empty for fs-verity compatibility.
    final byte[] salt = null;
    // Not used by apksigner.
    final byte[] additionalData = null;
    final long fileSize = apkContent.size();
    // Obtaining first supported digest from v2/v3 blocks (SHA256 or SHA512).
    final byte[] apkDigest = getApkDigest(apkContent);
    // Obtaining the merkle tree and the root hash in verity format.
    ApkSigningBlockUtils.VerityTreeAndDigest verityContentDigestInfo = ApkSigningBlockUtils.computeChunkVerityTreeAndDigest(apkContent);
    final ContentDigestAlgorithm verityContentDigestAlgorithm = verityContentDigestInfo.contentDigestAlgorithm;
    final byte[] rootHash = verityContentDigestInfo.rootHash;
    final byte[] tree = verityContentDigestInfo.tree;
    final Pair<Integer, Byte> hashingAlgorithmBlockSizePair = convertToV4HashingInfo(verityContentDigestAlgorithm);
    final V4Signature.HashingInfo hashingInfo = new V4Signature.HashingInfo(hashingAlgorithmBlockSizePair.getFirst(), hashingAlgorithmBlockSizePair.getSecond(), salt, rootHash);
    // Generating SigningInfo and combining everything into V4Signature.
    final V4Signature signature;
    try {
        signature = generateSignature(signerConfig, hashingInfo, apkDigest, additionalData, fileSize);
    } catch (InvalidKeyException | SignatureException | CertificateEncodingException e) {
        throw new InvalidKeyException("Signer failed", e);
    }
    return Pair.of(signature, tree);
}
Also used : CertificateEncodingException(java.security.cert.CertificateEncodingException) SignatureException(java.security.SignatureException) ApkSigningBlockUtils(com.android.apksig.internal.apk.ApkSigningBlockUtils) InvalidKeyException(java.security.InvalidKeyException) ContentDigestAlgorithm(com.android.apksig.internal.apk.ContentDigestAlgorithm)

Example 7 with ContentDigestAlgorithm

use of com.android.apksig.internal.apk.ContentDigestAlgorithm in project apksig by venshine.

the class V4SchemeSigner method pickBestDigest.

private static byte[] pickBestDigest(List<ApkSigningBlockUtils.Result.SignerInfo.ContentDigest> contentDigests) throws SignatureException {
    if (contentDigests == null || contentDigests.isEmpty()) {
        throw new SignatureException("Should have at least one digest");
    }
    int bestAlgorithmOrder = -1;
    byte[] bestDigest = null;
    for (ApkSigningBlockUtils.Result.SignerInfo.ContentDigest contentDigest : contentDigests) {
        final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.findById(contentDigest.getSignatureAlgorithmId());
        final ContentDigestAlgorithm contentDigestAlgorithm = signatureAlgorithm.getContentDigestAlgorithm();
        if (!isSupported(contentDigestAlgorithm, true)) {
            continue;
        }
        final int algorithmOrder = digestAlgorithmSortingOrder(contentDigestAlgorithm);
        if (bestAlgorithmOrder < algorithmOrder) {
            bestAlgorithmOrder = algorithmOrder;
            bestDigest = contentDigest.getValue();
        }
    }
    if (bestDigest == null) {
        throw new SignatureException("Failed to find a supported digest in the source APK");
    }
    return bestDigest;
}
Also used : SignatureAlgorithm(com.android.apksig.internal.apk.SignatureAlgorithm) SignatureException(java.security.SignatureException) ContentDigestAlgorithm(com.android.apksig.internal.apk.ContentDigestAlgorithm) ApkSigningBlockUtils(com.android.apksig.internal.apk.ApkSigningBlockUtils)

Example 8 with ContentDigestAlgorithm

use of com.android.apksig.internal.apk.ContentDigestAlgorithm in project apksig by venshine.

the class V4SchemeVerifier method verifyRootHashAndTree.

private static void verifyRootHashAndTree(DataSource apkContent, ApkSigningBlockUtils.Result.SignerInfo signerInfo, byte[] expectedDigest, byte[] expectedTree) throws IOException, NoSuchAlgorithmException {
    ApkSigningBlockUtils.VerityTreeAndDigest actualContentDigestInfo = ApkSigningBlockUtils.computeChunkVerityTreeAndDigest(apkContent);
    ContentDigestAlgorithm algorithm = actualContentDigestInfo.contentDigestAlgorithm;
    final byte[] actualDigest = actualContentDigestInfo.rootHash;
    final byte[] actualTree = actualContentDigestInfo.tree;
    if (!Arrays.equals(expectedDigest, actualDigest)) {
        signerInfo.addError(ApkVerifier.Issue.V4_SIG_APK_ROOT_DID_NOT_VERIFY, algorithm, toHex(expectedDigest), toHex(actualDigest));
        return;
    }
    // Only check verity tree if it is not empty
    if (expectedTree != null && !Arrays.equals(expectedTree, actualTree)) {
        signerInfo.addError(ApkVerifier.Issue.V4_SIG_APK_TREE_DID_NOT_VERIFY, algorithm, toHex(expectedDigest), toHex(actualDigest));
        return;
    }
    signerInfo.verifiedContentDigests.put(algorithm, actualDigest);
}
Also used : ContentDigestAlgorithm(com.android.apksig.internal.apk.ContentDigestAlgorithm) ApkSigningBlockUtils(com.android.apksig.internal.apk.ApkSigningBlockUtils)

Example 9 with ContentDigestAlgorithm

use of com.android.apksig.internal.apk.ContentDigestAlgorithm in project apksig by venshine.

the class DefaultApkSignerEngine method outputZipSectionsInternal.

private OutputApkSigningBlockRequestImpl outputZipSectionsInternal(DataSource zipEntries, DataSource zipCentralDirectory, DataSource zipEocd, boolean apkSigningBlockPaddingSupported) throws IOException, InvalidKeyException, SignatureException, NoSuchAlgorithmException {
    checkNotClosed();
    checkV1SigningDoneIfEnabled();
    if (!mV2SigningEnabled && !mV3SigningEnabled && !isEligibleForSourceStamp()) {
        return null;
    }
    checkOutputApkNotDebuggableIfDebuggableMustBeRejected();
    // adjust to proper padding
    Pair<DataSource, Integer> paddingPair = ApkSigningBlockUtils.generateApkSigningBlockPadding(zipEntries, apkSigningBlockPaddingSupported);
    DataSource beforeCentralDir = paddingPair.getFirst();
    int padSizeBeforeApkSigningBlock = paddingPair.getSecond();
    DataSource eocd = ApkSigningBlockUtils.copyWithModifiedCDOffset(beforeCentralDir, zipEocd);
    List<Pair<byte[], Integer>> signingSchemeBlocks = new ArrayList<>();
    ApkSigningBlockUtils.SigningSchemeBlockAndDigests v2SigningSchemeBlockAndDigests = null;
    ApkSigningBlockUtils.SigningSchemeBlockAndDigests v3SigningSchemeBlockAndDigests = null;
    // new APK signing block.
    if (mOtherSignersSignaturesPreserved && mPreservedSignatureBlocks != null && !mPreservedSignatureBlocks.isEmpty()) {
        signingSchemeBlocks.addAll(mPreservedSignatureBlocks);
    }
    // create APK Signature Scheme V2 Signature if requested
    if (mV2SigningEnabled) {
        invalidateV2Signature();
        List<ApkSigningBlockUtils.SignerConfig> v2SignerConfigs = createV2SignerConfigs(apkSigningBlockPaddingSupported);
        v2SigningSchemeBlockAndDigests = V2SchemeSigner.generateApkSignatureSchemeV2Block(mExecutor, beforeCentralDir, zipCentralDirectory, eocd, v2SignerConfigs, mV3SigningEnabled, mOtherSignersSignaturesPreserved ? mPreservedV2Signers : null);
        signingSchemeBlocks.add(v2SigningSchemeBlockAndDigests.signingSchemeBlock);
    }
    if (mV3SigningEnabled) {
        invalidateV3Signature();
        List<ApkSigningBlockUtils.SignerConfig> v3SignerConfigs = createV3SignerConfigs(apkSigningBlockPaddingSupported);
        v3SigningSchemeBlockAndDigests = V3SchemeSigner.generateApkSignatureSchemeV3Block(mExecutor, beforeCentralDir, zipCentralDirectory, eocd, v3SignerConfigs);
        signingSchemeBlocks.add(v3SigningSchemeBlockAndDigests.signingSchemeBlock);
    }
    if (isEligibleForSourceStamp()) {
        ApkSigningBlockUtils.SignerConfig sourceStampSignerConfig = createSourceStampSignerConfig();
        Map<Integer, Map<ContentDigestAlgorithm, byte[]>> signatureSchemeDigestInfos = new HashMap<>();
        if (mV3SigningEnabled) {
            signatureSchemeDigestInfos.put(VERSION_APK_SIGNATURE_SCHEME_V3, v3SigningSchemeBlockAndDigests.digestInfo);
        }
        if (mV2SigningEnabled) {
            signatureSchemeDigestInfos.put(VERSION_APK_SIGNATURE_SCHEME_V2, v2SigningSchemeBlockAndDigests.digestInfo);
        }
        if (mV1SigningEnabled) {
            Map<ContentDigestAlgorithm, byte[]> v1SigningSchemeDigests = new HashMap<>();
            try {
                // Jar signing related variables must have been already populated at this point
                // if V1 signing is enabled since it is happening before computations on the APK
                // signing block (V2/V3/V4/SourceStamp signing).
                byte[] inputJarManifest = (mInputJarManifestEntryDataRequest != null) ? mInputJarManifestEntryDataRequest.getData() : null;
                byte[] jarManifest = V1SchemeSigner.generateManifestFile(mV1ContentDigestAlgorithm, mOutputJarEntryDigests, inputJarManifest).contents;
                // The digest of the jar manifest does not need to be computed in chunks due to
                // the small size of the manifest.
                v1SigningSchemeDigests.put(ContentDigestAlgorithm.SHA256, computeSha256DigestBytes(jarManifest));
            } catch (ApkFormatException e) {
                throw new RuntimeException("Failed to generate manifest file", e);
            }
            signatureSchemeDigestInfos.put(VERSION_JAR_SIGNATURE_SCHEME, v1SigningSchemeDigests);
        }
        signingSchemeBlocks.add(V2SourceStampSigner.generateSourceStampBlock(sourceStampSignerConfig, signatureSchemeDigestInfos));
    }
    // create APK Signing Block with v2 and/or v3 and/or SourceStamp blocks
    byte[] apkSigningBlock = ApkSigningBlockUtils.generateApkSigningBlock(signingSchemeBlocks);
    mAddSigningBlockRequest = new OutputApkSigningBlockRequestImpl(apkSigningBlock, padSizeBeforeApkSigningBlock);
    return mAddSigningBlockRequest;
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) ApkSigningBlockUtils(com.android.apksig.internal.apk.ApkSigningBlockUtils) DataSource(com.android.apksig.util.DataSource) ApkFormatException(com.android.apksig.apk.ApkFormatException) ContentDigestAlgorithm(com.android.apksig.internal.apk.ContentDigestAlgorithm) Map(java.util.Map) HashMap(java.util.HashMap) Pair(com.android.apksig.internal.util.Pair)

Example 10 with ContentDigestAlgorithm

use of com.android.apksig.internal.apk.ContentDigestAlgorithm in project apksig by venshine.

the class ApkVerifier method getApkContentDigestFromV1SigningScheme.

private static Map<ContentDigestAlgorithm, byte[]> getApkContentDigestFromV1SigningScheme(List<CentralDirectoryRecord> cdRecords, DataSource apk, ApkUtils.ZipSections zipSections) throws IOException, ApkFormatException {
    CentralDirectoryRecord manifestCdRecord = null;
    Map<ContentDigestAlgorithm, byte[]> v1ContentDigest = new EnumMap<>(ContentDigestAlgorithm.class);
    for (CentralDirectoryRecord cdRecord : cdRecords) {
        if (MANIFEST_ENTRY_NAME.equals(cdRecord.getName())) {
            manifestCdRecord = cdRecord;
            break;
        }
    }
    if (manifestCdRecord == null) {
        // thus an empty digest will invalidate that signature.
        return v1ContentDigest;
    }
    try {
        byte[] manifestBytes = LocalFileRecord.getUncompressedData(apk, manifestCdRecord, zipSections.getZipCentralDirectoryOffset());
        v1ContentDigest.put(ContentDigestAlgorithm.SHA256, computeSha256DigestBytes(manifestBytes));
        return v1ContentDigest;
    } catch (ZipFormatException e) {
        throw new ApkFormatException("Failed to read APK", e);
    }
}
Also used : CentralDirectoryRecord(com.android.apksig.internal.zip.CentralDirectoryRecord) ApkFormatException(com.android.apksig.apk.ApkFormatException) ZipFormatException(com.android.apksig.zip.ZipFormatException) ContentDigestAlgorithm(com.android.apksig.internal.apk.ContentDigestAlgorithm) EnumMap(java.util.EnumMap)

Aggregations

ContentDigestAlgorithm (com.android.apksig.internal.apk.ContentDigestAlgorithm)14 ApkSigningBlockUtils (com.android.apksig.internal.apk.ApkSigningBlockUtils)8 SignatureException (java.security.SignatureException)7 CertificateEncodingException (java.security.cert.CertificateEncodingException)6 SignatureAlgorithm (com.android.apksig.internal.apk.SignatureAlgorithm)5 ZipFormatException (com.android.apksig.zip.ZipFormatException)5 ArrayList (java.util.ArrayList)5 ApkFormatException (com.android.apksig.apk.ApkFormatException)4 SignatureInfo (com.android.apksig.internal.apk.SignatureInfo)4 Pair (com.android.apksig.internal.util.Pair)4 EnumMap (java.util.EnumMap)4 ApkSigResult (com.android.apksig.internal.apk.ApkSigResult)3 ApkSignerInfo (com.android.apksig.internal.apk.ApkSignerInfo)3 CentralDirectoryRecord (com.android.apksig.internal.zip.CentralDirectoryRecord)3 IOException (java.io.IOException)3 InvalidKeyException (java.security.InvalidKeyException)3 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)3 HashSet (java.util.HashSet)3 Map (java.util.Map)3 ApkSigningBlockUtils.encodePublicKey (com.android.apksig.internal.apk.ApkSigningBlockUtils.encodePublicKey)2