Make apksig compatible with Java 7 am: caf0df53f7
Change-Id: Idd1414e404ffca0962eb745bf154eb9306155b54
diff --git a/src/apksigner/java/com/android/apksigner/ApkSignerTool.java b/src/apksigner/java/com/android/apksigner/ApkSignerTool.java
index fe29987..f864595 100644
--- a/src/apksigner/java/com/android/apksigner/ApkSignerTool.java
+++ b/src/apksigner/java/com/android/apksigner/ApkSignerTool.java
@@ -713,7 +713,6 @@
File outputKeyLineage = null;
String optionName;
OptionsParser optionsParser = new OptionsParser(params);
- SigningCertificateLineage lineage = null;
List<SignerParams> signers = new ArrayList<>(1);
while ((optionName = optionsParser.nextOption()) != null) {
if (("help".equals(optionName)) || ("h".equals(optionName))) {
@@ -739,7 +738,7 @@
if (inputKeyLineage == null) {
throw new ParameterException("Input lineage file parameter not present");
}
- lineage = getLineageFromInputFile(inputKeyLineage);
+ SigningCertificateLineage lineage = getLineageFromInputFile(inputKeyLineage);
try (PasswordRetriever passwordRetriever = new PasswordRetriever()) {
for (int i = 0; i < signers.size(); i++) {
diff --git a/src/main/java/com/android/apksig/ApkSigner.java b/src/main/java/com/android/apksig/ApkSigner.java
index 559c0e3..3b63744 100644
--- a/src/main/java/com/android/apksig/ApkSigner.java
+++ b/src/main/java/com/android/apksig/ApkSigner.java
@@ -576,7 +576,7 @@
}
}
- private long outputDataToOutputApk(
+ private static long outputDataToOutputApk(
String entryName,
byte[] uncompressedData,
long localFileHeaderOffset,
@@ -672,7 +672,7 @@
outputOffset + inputRecord.getExtraFieldStartOffsetInsideRecord(),
dataAlignmentMultiple);
long dataOffset =
- inputRecord.getDataStartOffsetInRecord()
+ (long) inputRecord.getDataStartOffsetInRecord()
+ aligningExtra.remaining()
- inputRecord.getExtra().remaining();
return new OutputSizeAndDataOffset(
diff --git a/src/main/java/com/android/apksig/ApkVerifier.java b/src/main/java/com/android/apksig/ApkVerifier.java
index 3d98a38..76a8d74 100644
--- a/src/main/java/com/android/apksig/ApkVerifier.java
+++ b/src/main/java/com/android/apksig/ApkVerifier.java
@@ -215,7 +215,7 @@
SUPPORTED_APK_SIG_SCHEME_NAMES.get(
ApkSigningBlockUtils.VERSION_APK_SIGNATURE_SCHEME_V2));
} else {
- supportedSchemeNames = Collections.EMPTY_MAP;
+ supportedSchemeNames = Collections.emptyMap();
}
// Android N and newer attempts to verify APKs using the APK Signing Block, which can
// include v2 and/or v3 signatures. If none is found, it falls back to JAR signature
@@ -292,14 +292,14 @@
try {
List<CentralDirectoryRecord> cdRecords =
V1SchemeVerifier.parseZipCentralDirectory(apk, zipSections);
- CentralDirectoryRecord sourceStampCdRecord =
- cdRecords.stream()
- .filter(
- cdRecord ->
- SOURCE_STAMP_CERTIFICATE_HASH_ZIP_ENTRY_NAME
- .equals(cdRecord.getName()))
- .findAny()
- .orElse(null);
+ CentralDirectoryRecord sourceStampCdRecord = null;
+ for (CentralDirectoryRecord cdRecord : cdRecords) {
+ if (SOURCE_STAMP_CERTIFICATE_HASH_ZIP_ENTRY_NAME.equals(
+ cdRecord.getName())) {
+ sourceStampCdRecord = cdRecord;
+ break;
+ }
+ }
// If SourceStamp file is found inside the APK, there must be a SourceStamp
// block in the APK signing block as well.
if (sourceStampCdRecord != null) {
@@ -378,7 +378,7 @@
try {
v1SignerCerts.add(new ByteArray(signer.getCertificate().getEncoded()));
} catch (CertificateEncodingException e) {
- throw new RuntimeException(
+ throw new IllegalStateException(
"Failed to encode JAR signer " + signer.getName() + " certs", e);
}
}
@@ -386,7 +386,7 @@
try {
v2SignerCerts.add(new ByteArray(signer.getCertificate().getEncoded()));
} catch (CertificateEncodingException e) {
- throw new RuntimeException(
+ throw new IllegalStateException(
"Failed to encode APK Signature Scheme v2 signer (index: "
+ signer.getIndex() + ") certs",
e);
@@ -498,9 +498,18 @@
v3Signers.get(0).getContentDigests();
List<ApkSigningBlockUtils.Result.SignerInfo.ContentDigest> v3DigestsFromV4 =
v4Signers.get(0).getContentDigests();
- if (v3DigestsFromV4.size() != 1
- || v3DigestsFromV3.stream().noneMatch(
- d -> Arrays.equals(d.getValue(), v3DigestsFromV4.get(0).getValue()))) {
+ if (v3DigestsFromV4.size() != 1) {
+ result.addError(Issue.V4_SIG_V3_DIGESTS_MISMATCH);
+ }
+ boolean foundV3DigestMatch = false;
+ for (ApkSigningBlockUtils.Result.SignerInfo.ContentDigest v3DigestFromV3 :
+ v3DigestsFromV3) {
+ if (Arrays.equals(v3DigestFromV3.getValue(), v3DigestsFromV4.get(0).getValue())) {
+ foundV3DigestMatch = true;
+ break;
+ }
+ }
+ if (!foundV3DigestMatch) {
result.addError(Issue.V4_SIG_V3_DIGESTS_MISMATCH);
}
}
@@ -1181,10 +1190,6 @@
return mCertificates.isEmpty() ? null : mCertificates.get(0);
}
- private void addError(Issue msg, Object... parameters) {
- mErrors.add(new IssueWithParams(msg, parameters));
- }
-
public boolean containsErrors() {
return !mErrors.isEmpty();
}
@@ -2352,10 +2357,7 @@
if (this == obj) {
return true;
}
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
+ if (!(obj instanceof ByteArray)) {
return false;
}
ByteArray other = (ByteArray) obj;
diff --git a/src/main/java/com/android/apksig/DefaultApkSignerEngine.java b/src/main/java/com/android/apksig/DefaultApkSignerEngine.java
index bbd6933..0e0b554 100644
--- a/src/main/java/com/android/apksig/DefaultApkSignerEngine.java
+++ b/src/main/java/com/android/apksig/DefaultApkSignerEngine.java
@@ -54,6 +54,7 @@
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -485,18 +486,19 @@
if (V1SchemeSigner.isJarEntryDigestNeededInManifest(entry.getKey())
&& isDebuggable(entryName)) {
- Optional<V1SchemeVerifier.NamedDigest> extractedDigest =
+ V1SchemeVerifier.NamedDigest extractedDigest = null;
+ Collection<V1SchemeVerifier.NamedDigest> digestsToVerify =
V1SchemeVerifier.getDigestsToVerify(
- entry.getValue(),
- "-Digest",
- mMinSdkVersion,
- Integer.MAX_VALUE)
- .stream()
- .filter(d -> d.jcaDigestAlgorithm == alg)
- .findFirst();
-
- extractedDigest.ifPresent(
- namedDigest -> mOutputJarEntryDigests.put(entryName, namedDigest.digest));
+ entry.getValue(), "-Digest", mMinSdkVersion, Integer.MAX_VALUE);
+ for (V1SchemeVerifier.NamedDigest digestToVerify : digestsToVerify) {
+ if (digestToVerify.jcaDigestAlgorithm.equals(alg)) {
+ extractedDigest = digestToVerify;
+ break;
+ }
+ }
+ if (extractedDigest != null) {
+ mOutputJarEntryDigests.put(entryName, extractedDigest.digest);
+ }
}
}
return mOutputJarEntryDigests.keySet();
diff --git a/src/main/java/com/android/apksig/internal/apk/ApkSigningBlockUtils.java b/src/main/java/com/android/apksig/internal/apk/ApkSigningBlockUtils.java
index 143ee3f..944b9b8 100644
--- a/src/main/java/com/android/apksig/internal/apk/ApkSigningBlockUtils.java
+++ b/src/main/java/com/android/apksig/internal/apk/ApkSigningBlockUtils.java
@@ -431,10 +431,13 @@
DataSource centralDir,
DataSource eocd) throws IOException, NoSuchAlgorithmException, DigestException {
Map<ContentDigestAlgorithm, byte[]> contentDigests = new HashMap<>();
- Set<ContentDigestAlgorithm> oneMbChunkBasedAlgorithm = digestAlgorithms.stream()
- .filter(a -> a == ContentDigestAlgorithm.CHUNKED_SHA256 ||
- a == ContentDigestAlgorithm.CHUNKED_SHA512)
- .collect(Collectors.toSet());
+ Set<ContentDigestAlgorithm> oneMbChunkBasedAlgorithm = new HashSet<>();
+ for (ContentDigestAlgorithm digestAlgorithm : digestAlgorithms) {
+ if (digestAlgorithm == ContentDigestAlgorithm.CHUNKED_SHA256
+ || digestAlgorithm == ContentDigestAlgorithm.CHUNKED_SHA512) {
+ oneMbChunkBasedAlgorithm.add(digestAlgorithm);
+ }
+ }
computeOneMbChunkContentDigests(
executor,
oneMbChunkBasedAlgorithm,
@@ -698,7 +701,7 @@
i));
}
chunkCounts[i] = (int)chunkCount;
- totalChunkCount += chunkCount;
+ totalChunkCount = (int) (totalChunkCount + chunkCount);
}
this.totalChunkCount = totalChunkCount;
nextIndex = new AtomicInteger(0);
@@ -1182,10 +1185,12 @@
if (bestSigAlgorithmOnSdkVersion.isEmpty()) {
throw new NoSupportedSignaturesException("No supported signature");
}
- return bestSigAlgorithmOnSdkVersion.values().stream()
- .sorted((sig1, sig2) -> Integer.compare(
- sig1.algorithm.getId(), sig2.algorithm.getId()))
- .collect(Collectors.toList());
+ List<SupportedSignature> signaturesToVerify =
+ new ArrayList<>(bestSigAlgorithmOnSdkVersion.values());
+ Collections.sort(
+ signaturesToVerify,
+ (sig1, sig2) -> Integer.compare(sig1.algorithm.getId(), sig2.algorithm.getId()));
+ return signaturesToVerify;
}
public static class NoSupportedSignaturesException extends Exception {
@@ -1279,7 +1284,7 @@
* // signatureAlgorithm
* // signature
*
- * @throws Asn1EncodingException
+ * @throws Asn1EncodingException if the ASN.1 structure could not be encoded
*/
public static byte[] generatePkcs7DerEncodedMessage(
byte[] signatureBytes, ByteBuffer data, List<X509Certificate> signerCerts,
@@ -1345,7 +1350,7 @@
/** Whether the APK's APK Signature Scheme signature verifies. */
public boolean verified;
- public final List<SignerInfo> signers = new ArrayList<>();
+ public final List<Result.SignerInfo> signers = new ArrayList<>();
public SigningCertificateLineage signingCertificateLineage = null;
private final List<ApkVerifier.IssueWithParams> mWarnings = new ArrayList<>();
private final List<ApkVerifier.IssueWithParams> mErrors = new ArrayList<>();
@@ -1359,7 +1364,7 @@
return true;
}
if (!signers.isEmpty()) {
- for (SignerInfo signer : signers) {
+ for (Result.SignerInfo signer : signers) {
if (signer.containsErrors()) {
return true;
}
@@ -1373,7 +1378,7 @@
return true;
}
if (!signers.isEmpty()) {
- for (SignerInfo signer : signers) {
+ for (Result.SignerInfo signer : signers) {
if (signer.containsWarnings()) {
return true;
}
diff --git a/src/main/java/com/android/apksig/internal/apk/stamp/SourceStampSigner.java b/src/main/java/com/android/apksig/internal/apk/stamp/SourceStampSigner.java
index 0749ef8..d7e10e7 100644
--- a/src/main/java/com/android/apksig/internal/apk/stamp/SourceStampSigner.java
+++ b/src/main/java/com/android/apksig/internal/apk/stamp/SourceStampSigner.java
@@ -29,6 +29,8 @@
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.cert.CertificateEncodingException;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
@@ -58,11 +60,11 @@
throw new SignatureException("No certificates configured for signer");
}
- List<Pair<Integer, byte[]>> digests =
- digestInfo.entrySet().stream()
- .sorted(Comparator.comparing(e -> e.getKey().getId()))
- .map(e -> Pair.of(e.getKey().getId(), e.getValue()))
- .collect(Collectors.toList());
+ List<Pair<Integer, byte[]>> digests = new ArrayList<>();
+ for (Map.Entry<ContentDigestAlgorithm, byte[]> digest : digestInfo.entrySet()) {
+ digests.add(Pair.of(digest.getKey().getId(), digest.getValue()));
+ }
+ Collections.sort(digests, Comparator.comparing(Pair::getFirst));
SourceStampBlock sourceStampBlock = new SourceStampBlock();
diff --git a/src/main/java/com/android/apksig/internal/apk/stamp/SourceStampVerifier.java b/src/main/java/com/android/apksig/internal/apk/stamp/SourceStampVerifier.java
index 68d225c..3590c71 100644
--- a/src/main/java/com/android/apksig/internal/apk/stamp/SourceStampVerifier.java
+++ b/src/main/java/com/android/apksig/internal/apk/stamp/SourceStampVerifier.java
@@ -36,7 +36,6 @@
import java.nio.ByteBuffer;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
-import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
@@ -46,9 +45,10 @@
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
@@ -136,7 +136,7 @@
maxSdkVersion);
result.verified = !result.containsErrors() && !result.containsWarnings();
} catch (CertificateException e) {
- throw new RuntimeException("Failed to obtain X.509 CertificateFactory", e);
+ throw new IllegalStateException("Failed to obtain X.509 CertificateFactory", e);
} catch (ApkFormatException | BufferUnderflowException e) {
signerInfo.addWarning(ApkVerifier.Issue.SOURCE_STAMP_MALFORMED_SIGNATURE);
}
@@ -160,11 +160,12 @@
int minSdkVersion,
int maxSdkVersion)
throws ApkFormatException, NoSuchAlgorithmException {
- List<Pair<Integer, byte[]>> digests =
- apkContentDigests.entrySet().stream()
- .sorted(Comparator.comparing(e -> e.getKey().getId()))
- .map(e -> Pair.of(e.getKey().getId(), e.getValue()))
- .collect(Collectors.toList());
+ List<Pair<Integer, byte[]>> digests = new ArrayList<>();
+ for (Map.Entry<ContentDigestAlgorithm, byte[]> apkContentDigest :
+ apkContentDigests.entrySet()) {
+ digests.add(Pair.of(apkContentDigest.getKey().getId(), apkContentDigest.getValue()));
+ }
+ Collections.sort(digests, Comparator.comparing(Pair::getFirst));
byte[] digestBytes =
encodeAsSequenceOfLengthPrefixedPairsOfIntAndLengthPrefixedBytes(digests);
diff --git a/src/main/java/com/android/apksig/internal/apk/v1/V1SchemeSigner.java b/src/main/java/com/android/apksig/internal/apk/v1/V1SchemeSigner.java
index a757f62..89f16d5 100644
--- a/src/main/java/com/android/apksig/internal/apk/v1/V1SchemeSigner.java
+++ b/src/main/java/com/android/apksig/internal/apk/v1/V1SchemeSigner.java
@@ -16,37 +16,20 @@
package com.android.apksig.internal.apk.v1;
-import static com.android.apksig.internal.asn1.Asn1DerEncoder.ASN1_DER_NULL;
-import static com.android.apksig.internal.oid.OidConstants.OID_DIGEST_SHA1;
-import static com.android.apksig.internal.oid.OidConstants.OID_DIGEST_SHA256;
-import static com.android.apksig.internal.oid.OidConstants.OID_SIG_DSA;
-import static com.android.apksig.internal.oid.OidConstants.OID_SIG_EC_PUBLIC_KEY;
-import static com.android.apksig.internal.oid.OidConstants.OID_SIG_RSA;
-import static com.android.apksig.internal.oid.OidConstants.OID_SIG_SHA256_WITH_DSA;
import static com.android.apksig.internal.pkcs7.AlgorithmIdentifier.getSignerInfoDigestAlgorithmOid;
import static com.android.apksig.internal.pkcs7.AlgorithmIdentifier.getSignerInfoSignatureAlgorithm;
import com.android.apksig.apk.ApkFormatException;
import com.android.apksig.internal.apk.ApkSigningBlockUtils;
-import com.android.apksig.internal.asn1.Asn1DerEncoder;
import com.android.apksig.internal.asn1.Asn1EncodingException;
-import com.android.apksig.internal.asn1.Asn1OpaqueObject;
-import com.android.apksig.internal.asn1.ber.BerEncoding;
import com.android.apksig.internal.jar.ManifestWriter;
import com.android.apksig.internal.jar.SignatureFileWriter;
import com.android.apksig.internal.pkcs7.AlgorithmIdentifier;
-import com.android.apksig.internal.pkcs7.ContentInfo;
-import com.android.apksig.internal.pkcs7.EncapsulatedContentInfo;
-import com.android.apksig.internal.pkcs7.IssuerAndSerialNumber;
-import com.android.apksig.internal.pkcs7.Pkcs7Constants;
-import com.android.apksig.internal.pkcs7.SignedData;
-import com.android.apksig.internal.pkcs7.SignerIdentifier;
-import com.android.apksig.internal.pkcs7.SignerInfo;
import com.android.apksig.internal.util.Pair;
+
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.nio.ByteBuffer;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -69,7 +52,6 @@
import java.util.TreeMap;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
-import javax.security.auth.x500.X500Principal;
/**
* APK signer which uses JAR signing (aka v1 signing scheme).
diff --git a/src/main/java/com/android/apksig/internal/apk/v1/V1SchemeVerifier.java b/src/main/java/com/android/apksig/internal/apk/v1/V1SchemeVerifier.java
index 1570752..111ac71 100644
--- a/src/main/java/com/android/apksig/internal/apk/v1/V1SchemeVerifier.java
+++ b/src/main/java/com/android/apksig/internal/apk/v1/V1SchemeVerifier.java
@@ -16,11 +16,6 @@
package com.android.apksig.internal.apk.v1;
-import static com.android.apksig.internal.oid.OidConstants.OID_SIG_DSA;
-import static com.android.apksig.internal.oid.OidConstants.OID_SIG_EC_PUBLIC_KEY;
-import static com.android.apksig.internal.oid.OidConstants.OID_SIG_RSA;
-import static com.android.apksig.internal.oid.OidConstants.OID_TO_JCA_DIGEST_ALG;
-import static com.android.apksig.internal.oid.OidConstants.OID_TO_JCA_SIGNATURE_ALG;
import static com.android.apksig.internal.oid.OidConstants.getSigAlgSupportedApiLevels;
import static com.android.apksig.internal.pkcs7.AlgorithmIdentifier.getJcaDigestAlgorithm;
import static com.android.apksig.internal.pkcs7.AlgorithmIdentifier.getJcaSignatureAlgorithm;
@@ -41,18 +36,14 @@
import com.android.apksig.internal.oid.OidConstants;
import com.android.apksig.internal.pkcs7.Attribute;
import com.android.apksig.internal.pkcs7.ContentInfo;
-import com.android.apksig.internal.pkcs7.IssuerAndSerialNumber;
import com.android.apksig.internal.pkcs7.Pkcs7Constants;
import com.android.apksig.internal.pkcs7.Pkcs7DecodingException;
import com.android.apksig.internal.pkcs7.SignedData;
-import com.android.apksig.internal.pkcs7.SignerIdentifier;
import com.android.apksig.internal.pkcs7.SignerInfo;
import com.android.apksig.internal.util.AndroidSdkVersion;
import com.android.apksig.internal.util.ByteBufferUtils;
-import com.android.apksig.internal.util.GuaranteedEncodedFormX509Certificate;
import com.android.apksig.internal.util.InclusiveIntRange;
import com.android.apksig.internal.util.Pair;
-import com.android.apksig.internal.util.X509CertificateUtils;
import com.android.apksig.internal.zip.CentralDirectoryRecord;
import com.android.apksig.internal.zip.LocalFileRecord;
import com.android.apksig.util.DataSinks;
@@ -60,7 +51,6 @@
import com.android.apksig.zip.ZipFormatException;
import java.io.IOException;
-import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.InvalidKeyException;
@@ -86,8 +76,6 @@
import java.util.StringTokenizer;
import java.util.jar.Attributes;
-import javax.security.auth.x500.X500Principal;
-
/**
* APK verifier which uses JAR signing (aka v1 signing scheme).
*
@@ -1317,13 +1305,10 @@
Collections.sort(
cdRecordsSortedByLocalFileHeaderOffset,
CentralDirectoryRecord.BY_LOCAL_FILE_HEADER_OFFSET_COMPARATOR);
- Set<String> manifestEntryNamesMissingFromApk =
- new HashSet<>(entryNameToManifestSection.keySet());
List<Signer> firstSignedEntrySigners = null;
String firstSignedEntryName = null;
for (CentralDirectoryRecord cdRecord : cdRecordsSortedByLocalFileHeaderOffset) {
String entryName = cdRecord.getName();
- manifestEntryNamesMissingFromApk.remove(entryName);
if (!isJarEntryDigestNeededInManifest(entryName)) {
continue;
}
diff --git a/src/main/java/com/android/apksig/internal/apk/v4/V4SchemeVerifier.java b/src/main/java/com/android/apksig/internal/apk/v4/V4SchemeVerifier.java
index 9c93c10..96294da 100644
--- a/src/main/java/com/android/apksig/internal/apk/v4/V4SchemeVerifier.java
+++ b/src/main/java/com/android/apksig/internal/apk/v4/V4SchemeVerifier.java
@@ -17,9 +17,6 @@
package com.android.apksig.internal.apk.v4;
import static com.android.apksig.internal.apk.ApkSigningBlockUtils.toHex;
-import static com.android.apksig.internal.apk.SignatureAlgorithm.VERITY_DSA_WITH_SHA256;
-import static com.android.apksig.internal.apk.SignatureAlgorithm.VERITY_ECDSA_WITH_SHA256;
-import static com.android.apksig.internal.apk.SignatureAlgorithm.VERITY_RSA_PKCS1_V1_5_WITH_SHA256;
import static com.android.apksig.internal.pkcs7.AlgorithmIdentifier.getJcaSignatureAlgorithm;
import static com.android.apksig.internal.x509.Certificate.findCertificate;
import static com.android.apksig.internal.x509.Certificate.parseCertificates;
@@ -150,7 +147,6 @@
}
signedData = Asn1BerParser.parse(contentInfo.content.getEncoded(), SignedData.class);
} catch (Asn1DecodingException e) {
- e.printStackTrace();
result.addError(Issue.V4_SIG_MALFORMED_PKCS7, e);
return result;
}
@@ -219,11 +215,9 @@
}
final boolean[] keyUsageExtension = signingCertificate.getKeyUsage();
if (keyUsageExtension != null) {
- boolean digitalSignature =
- (keyUsageExtension.length >= 1) && (keyUsageExtension[0]);
- boolean nonRepudiation =
- (keyUsageExtension.length >= 2) && (keyUsageExtension[1]);
- if ((!digitalSignature) && (!nonRepudiation)) {
+ boolean digitalSignature = (keyUsageExtension.length >= 1) && keyUsageExtension[0];
+ boolean nonRepudiation = (keyUsageExtension.length >= 2) && keyUsageExtension[1];
+ if (!digitalSignature && !nonRepudiation) {
result.addError(Issue.V4_SIG_MALFORMED_CERTIFICATE,
"Signing certificate not authorized for use in digital signatures"
+ ": keyUsage extension missing digitalSignature and"
@@ -232,15 +226,12 @@
}
}
- Signature s = null;
+ Signature s;
try {
final String jcaSignatureAlgorithm = getJcaSignatureAlgorithm(
digestAlgorithmOid, signatureAlgorithmOid);
s = Signature.getInstance(jcaSignatureAlgorithm);
} catch (SignatureException | NoSuchAlgorithmException e) {
- e.printStackTrace();
- }
- if (s == null) {
result.addError(Issue.V4_SIG_UNKNOWN_SIG_ALGORITHM);
return;
}
@@ -266,7 +257,7 @@
new HashMap<>();
ApkSigningBlockUtils.computeChunkVerityTreeAndDigest(apkContent, actualContentDigests);
if (result.signers.size() != 1) {
- throw new RuntimeException("There should only be one signer for V4");
+ throw new IllegalStateException("There should only be one signer for V4");
}
final ApkSigningBlockUtils.Result.SignerInfo signerInfo = result.signers.get(0);
for (ApkSigningBlockUtils.Result.SignerInfo.ContentDigest expected
diff --git a/src/main/java/com/android/apksig/internal/oid/OidConstants.java b/src/main/java/com/android/apksig/internal/oid/OidConstants.java
index 4504517..d80cbaa 100644
--- a/src/main/java/com/android/apksig/internal/oid/OidConstants.java
+++ b/src/main/java/com/android/apksig/internal/oid/OidConstants.java
@@ -458,4 +458,6 @@
OID_TO_JCA_SIGNATURE_ALG.put(OID_SIG_SHA384_WITH_ECDSA, "SHA384withECDSA");
OID_TO_JCA_SIGNATURE_ALG.put(OID_SIG_SHA512_WITH_ECDSA, "SHA512withECDSA");
}
+
+ private OidConstants() {}
}
diff --git a/src/main/java/com/android/apksig/internal/pkcs7/AlgorithmIdentifier.java b/src/main/java/com/android/apksig/internal/pkcs7/AlgorithmIdentifier.java
index 35a9f4b..c27c487 100644
--- a/src/main/java/com/android/apksig/internal/pkcs7/AlgorithmIdentifier.java
+++ b/src/main/java/com/android/apksig/internal/pkcs7/AlgorithmIdentifier.java
@@ -68,9 +68,8 @@
return new AlgorithmIdentifier(OID_DIGEST_SHA1, ASN1_DER_NULL);
case SHA256:
return new AlgorithmIdentifier(OID_DIGEST_SHA256, ASN1_DER_NULL);
- default:
- throw new RuntimeException("Unsupported digest algorithm: " + digestAlgorithm);
}
+ throw new IllegalArgumentException("Unsupported digest algorithm: " + digestAlgorithm);
}
/**
diff --git a/src/test/java/com/android/apksig/ApkSignerTest.java b/src/test/java/com/android/apksig/ApkSignerTest.java
index e4a22ee..f945234 100644
--- a/src/test/java/com/android/apksig/ApkSignerTest.java
+++ b/src/test/java/com/android/apksig/ApkSignerTest.java
@@ -16,6 +16,7 @@
package com.android.apksig;
+import static com.android.apksig.apk.ApkUtils.SOURCE_STAMP_CERTIFICATE_HASH_ZIP_ENTRY_NAME;
import static com.android.apksig.apk.ApkUtils.findZipSections;
import static org.junit.Assert.assertArrayEquals;
@@ -765,7 +766,7 @@
new ApkSigner.Builder(signers).setDebuggableApkPermitted(false)));
}
- @Test(expected = IllegalStateException.class)
+ @Test
public void testV3SigningWithSignersNotInLineageFails() throws Exception {
// APKs signed with the v3 scheme after a key rotation must specify the lineage containing
// the proof of rotation. This test verifies that the signing will fail if the provided
@@ -776,7 +777,13 @@
getDefaultSignerConfigFromResources(SECOND_RSA_2048_SIGNER_RESOURCE_NAME));
SigningCertificateLineage lineage =
Resources.toSigningCertificateLineage(getClass(), "rsa-1024-lineage-2-signers");
- sign("original.apk", new ApkSigner.Builder(signers).setSigningCertificateLineage(lineage));
+ assertThrows(
+ IllegalStateException.class,
+ () ->
+ sign(
+ "original.apk",
+ new ApkSigner.Builder(signers)
+ .setSigningCertificateLineage(lineage)));
}
@Test
@@ -863,7 +870,7 @@
.setSigningCertificateLineage(lineage));
}
- @Test(expected = IllegalStateException.class)
+ @Test
public void testV3SigningWithMultipleSignersAndNoLineageFails() throws Exception {
// The v3 signing scheme does not support multiple signers; if multiple signers are provided
// it is assumed these signers are part of the lineage. This test verifies v3 signing
@@ -873,12 +880,15 @@
ApkSigner.SignerConfig secondSigner =
getDefaultSignerConfigFromResources(SECOND_RSA_2048_SIGNER_RESOURCE_NAME);
List<ApkSigner.SignerConfig> signers = Arrays.asList(firstSigner, secondSigner);
- sign(
- "original.apk",
- new ApkSigner.Builder(signers)
- .setV1SigningEnabled(true)
- .setV2SigningEnabled(true)
- .setV3SigningEnabled(true));
+ assertThrows(
+ IllegalStateException.class,
+ () ->
+ sign(
+ "original.apk",
+ new ApkSigner.Builder(signers)
+ .setV1SigningEnabled(true)
+ .setV2SigningEnabled(true)
+ .setV3SigningEnabled(true)));
}
@Test
@@ -986,14 +996,13 @@
ApkUtils.ZipSections zipSections = findZipSections(signedApk);
List<CentralDirectoryRecord> cdRecords =
V1SchemeVerifier.parseZipCentralDirectory(signedApk, zipSections);
- CentralDirectoryRecord stampCdRecord =
- cdRecords.stream()
- .filter(
- cdRecord ->
- ApkUtils.SOURCE_STAMP_CERTIFICATE_HASH_ZIP_ENTRY_NAME.equals(
- cdRecord.getName()))
- .findAny()
- .orElse(null);
+ CentralDirectoryRecord stampCdRecord = null;
+ for (CentralDirectoryRecord cdRecord : cdRecords) {
+ if (SOURCE_STAMP_CERTIFICATE_HASH_ZIP_ENTRY_NAME.equals(cdRecord.getName())) {
+ stampCdRecord = cdRecord;
+ break;
+ }
+ }
assertNotNull(stampCdRecord);
byte[] actualStampCertificateDigest =
LocalFileRecord.getUncompressedData(
@@ -1150,7 +1159,7 @@
return Asn1BerParser.parse(subjectPublicKeyBuffer, RSAPublicKey.class);
}
- private SignatureInfo getSignatureInfoFromApk(
+ private static SignatureInfo getSignatureInfoFromApk(
DataSource apk, int signatureVersionId, int signatureVersionBlockId)
throws IOException, ZipFormatException,
ApkSigningBlockUtils.SignatureNotFoundException {
diff --git a/src/test/java/com/android/apksig/internal/util/FileChannelDataSourceTest.java b/src/test/java/com/android/apksig/internal/util/FileChannelDataSourceTest.java
index 9578926..12f08f1 100644
--- a/src/test/java/com/android/apksig/internal/util/FileChannelDataSourceTest.java
+++ b/src/test/java/com/android/apksig/internal/util/FileChannelDataSourceTest.java
@@ -90,14 +90,14 @@
assertArrayEquals(expectedBytes, resultBytes);
}
- private byte[] getDataSinkBytes(ByteArrayDataSink dataSink) {
+ private static byte[] getDataSinkBytes(ByteArrayDataSink dataSink) {
ByteBuffer result = dataSink.getByteBuffer(0, (int)dataSink.size());
byte[] resultBytes = new byte[result.limit()];
result.get(resultBytes);
return resultBytes;
}
- private byte[] createFileContent(int fileSize) {
+ private static byte[] createFileContent(int fileSize) {
byte[] fullFileContent = new byte[fileSize];
for (int i = 0; i < fileSize; ++i) {
fullFileContent[i] = (byte) (i % 255);