aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHajime Morrita <morrita@google.com>2021-02-05 12:54:45 -0800
committerMichael Groover <mpgroover@google.com>2021-04-06 16:27:39 -0700
commit88f873c6c769eed5090e15789ec685fe886e1379 (patch)
tree8d7ce164e8ae0e6ecebf992e6d2c0163193e7a81
parent242e33e676754aa3df01429ecda763b5bcdac0a8 (diff)
downloadapksig-88f873c6c769eed5090e15789ec685fe886e1379.tar.gz
Add support for V1 signing with the pinlinst.meta file
Test: gradlew test Bug: 174697187 Bug: 179297646 Change-Id: I164579043bec804c2cbc2b9166fdacc6a04963f1 Merged-In: I164579043bec804c2cbc2b9166fdacc6a04963f1
-rw-r--r--src/main/java/com/android/apksig/ApkSigner.java61
-rw-r--r--src/test/java/com/android/apksig/ApkSignerTest.java46
-rw-r--r--src/test/resources/com/android/apksig/golden-pinsapp-signed.apkbin0 -> 8732 bytes
-rwxr-xr-xsrc/test/resources/com/android/apksig/pinsapp-unsigned.apkbin0 -> 2205 bytes
4 files changed, 83 insertions, 24 deletions
diff --git a/src/main/java/com/android/apksig/ApkSigner.java b/src/main/java/com/android/apksig/ApkSigner.java
index d4da569..8cca444 100644
--- a/src/main/java/com/android/apksig/ApkSigner.java
+++ b/src/main/java/com/android/apksig/ApkSigner.java
@@ -510,6 +510,28 @@ public class ApkSigner {
}
}
+ // Step 7.5. Generate pinlist.meta file if necessary.
+ // 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 =
@@ -520,15 +542,7 @@ public class ApkSigner {
String entryName = entry.getName();
byte[] uncompressedData = entry.getData();
- ApkSignerEngine.InspectJarEntryRequest inspectEntryRequest =
- signerEngine.outputJarEntry(entryName);
- if (inspectEntryRequest != null) {
- inspectEntryRequest
- .getDataSink()
- .consume(uncompressedData, 0, uncompressedData.length);
- inspectEntryRequest.done();
- }
-
+ requestOutputEntryInspection(signerEngine, entryName, uncompressedData);
outputOffset +=
outputDataToOutputApk(
entryName,
@@ -542,21 +556,6 @@ public class ApkSigner {
outputJarSignatureRequest.done();
}
- if (pinByteRanges != null) {
- pinByteRanges.add(new Hints.ByteRange(outputOffset, Long.MAX_VALUE)); // central dir
- String entryName = Hints.PIN_BYTE_RANGE_ZIP_ENTRY_NAME;
- byte[] uncompressedData = Hints.encodeByteRangeList(pinByteRanges);
- outputOffset +=
- outputDataToOutputApk(
- entryName,
- uncompressedData,
- outputOffset,
- outputCdRecords,
- lastModifiedTimeForNewEntries,
- lastModifiedDateForNewEntries,
- outputApkOut);
- }
-
// Step 9. Construct output ZIP Central Directory in an in-memory buffer
long outputCentralDirSizeBytes = 0;
for (CentralDirectoryRecord record : outputCdRecords) {
@@ -616,6 +615,20 @@ public class ApkSigner {
}
}
+ private static void requestOutputEntryInspection(
+ ApkSignerEngine signerEngine,
+ String entryName,
+ byte[] uncompressedData)
+ throws IOException {
+ ApkSignerEngine.InspectJarEntryRequest inspectEntryRequest =
+ signerEngine.outputJarEntry(entryName);
+ if (inspectEntryRequest != null) {
+ inspectEntryRequest.getDataSink().consume(
+ uncompressedData, 0, uncompressedData.length);
+ inspectEntryRequest.done();
+ }
+ }
+
private static long outputDataToOutputApk(
String entryName,
byte[] uncompressedData,
diff --git a/src/test/java/com/android/apksig/ApkSignerTest.java b/src/test/java/com/android/apksig/ApkSignerTest.java
index 40255a4..67f339f 100644
--- a/src/test/java/com/android/apksig/ApkSignerTest.java
+++ b/src/test/java/com/android/apksig/ApkSignerTest.java
@@ -46,6 +46,8 @@ import com.android.apksig.util.DataSource;
import com.android.apksig.util.DataSources;
import com.android.apksig.zip.ZipFormatException;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@@ -365,6 +367,15 @@ public class ApkSignerTest {
.setV2SigningEnabled(true)
.setV3SigningEnabled(true)
.setVerityEnabled(true));
+
+ signGolden(
+ "pinsapp-unsigned.apk",
+ new File(outDir, "golden-pinsapp-signed.apk"),
+ new ApkSigner.Builder(rsa2048SignerConfig)
+ .setV1SigningEnabled(true)
+ .setV2SigningEnabled(true)
+ .setV3SigningEnabled(true)
+ .setVerityEnabled(true));
}
private static void signGolden(
@@ -1249,6 +1260,41 @@ public class ApkSignerTest {
assertSourceStampVerified(signedApk, sourceStampVerificationResult);
}
+ @Test
+ public void testSignApk_Pinlist() throws Exception {
+ List<ApkSigner.SignerConfig> rsa2048SignerConfig =
+ Collections.singletonList(
+ getDefaultSignerConfigFromResources(FIRST_RSA_2048_SIGNER_RESOURCE_NAME));
+ assertGolden(
+ "pinsapp-unsigned.apk",
+ "golden-pinsapp-signed.apk",
+ new ApkSigner.Builder(rsa2048SignerConfig)
+ .setV1SigningEnabled(true)
+ .setV2SigningEnabled(true)
+ .setV3SigningEnabled(true)
+ .setVerityEnabled(true));
+ assertTrue("pinlist.meta file must be in the signed APK.",
+ resourceZipFileContains("golden-pinsapp-signed.apk", "pinlist.meta"));
+ }
+
+ private static boolean resourceZipFileContains(String resourceName, String zipEntryName)
+ throws IOException {
+ ZipInputStream zip = new ZipInputStream(
+ Resources.toInputStream(ApkSignerTest.class, resourceName));
+ while (true) {
+ ZipEntry entry = zip.getNextEntry();
+ if (entry == null) {
+ break;
+ }
+
+ if (entry.getName().equals(zipEntryName)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
private RSAPublicKey getRSAPublicKeyFromSigningBlock(File apk, int signatureVersionId)
throws Exception {
int signatureVersionBlockId;
diff --git a/src/test/resources/com/android/apksig/golden-pinsapp-signed.apk b/src/test/resources/com/android/apksig/golden-pinsapp-signed.apk
new file mode 100644
index 0000000..43c39f1
--- /dev/null
+++ b/src/test/resources/com/android/apksig/golden-pinsapp-signed.apk
Binary files differ
diff --git a/src/test/resources/com/android/apksig/pinsapp-unsigned.apk b/src/test/resources/com/android/apksig/pinsapp-unsigned.apk
new file mode 100755
index 0000000..b6a6e8f
--- /dev/null
+++ b/src/test/resources/com/android/apksig/pinsapp-unsigned.apk
Binary files differ