Skip to content

Commit e89b0ab

Browse files
committed
incorporated APK Signer V2 from Android project
1 parent 5d3e2ea commit e89b0ab

File tree

5 files changed

+971
-6
lines changed

5 files changed

+971
-6
lines changed

mode/src/processing/ZipUtils.java

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*
2+
* Copyright (C) 2016 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package processing.mode.android;
17+
18+
import java.nio.ByteBuffer;
19+
import java.nio.ByteOrder;
20+
21+
/**
22+
* Assorted ZIP format helpers.
23+
*
24+
* <p>NOTE: Most helper methods operating on {@code ByteBuffer} instances expect that the byte
25+
* order of these buffers is little-endian.
26+
*/
27+
public abstract class ZipUtils {
28+
private ZipUtils() {}
29+
private static final int ZIP_EOCD_REC_MIN_SIZE = 22;
30+
private static final int ZIP_EOCD_REC_SIG = 0x06054b50;
31+
private static final int ZIP_EOCD_CENTRAL_DIR_SIZE_FIELD_OFFSET = 12;
32+
private static final int ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_OFFSET = 16;
33+
private static final int ZIP_EOCD_COMMENT_LENGTH_FIELD_OFFSET = 20;
34+
private static final int ZIP64_EOCD_LOCATOR_SIZE = 20;
35+
private static final int ZIP64_EOCD_LOCATOR_SIG = 0x07064b50;
36+
private static final int UINT32_MAX_VALUE = 0xffff;
37+
/**
38+
* Returns the position at which ZIP End of Central Directory record starts in the provided
39+
* buffer or {@code -1} if the record is not present.
40+
*
41+
* <p>NOTE: Byte order of {@code zipContents} must be little-endian.
42+
*/
43+
public static int findZipEndOfCentralDirectoryRecord(ByteBuffer zipContents) {
44+
assertByteOrderLittleEndian(zipContents);
45+
// ZIP End of Central Directory (EOCD) record is located at the very end of the ZIP archive.
46+
// The record can be identified by its 4-byte signature/magic which is located at the very
47+
// beginning of the record. A complication is that the record is variable-length because of
48+
// the comment field.
49+
// The algorithm for locating the ZIP EOCD record is as follows. We search backwards from
50+
// end of the buffer for the EOCD record signature. Whenever we find a signature, we check
51+
// the candidate record's comment length is such that the remainder of the record takes up
52+
// exactly the remaining bytes in the buffer. The search is bounded because the maximum
53+
// size of the comment field is 65535 bytes because the field is an unsigned 32-bit number.
54+
int archiveSize = zipContents.capacity();
55+
System.out.println(archiveSize + " " + ZIP_EOCD_REC_MIN_SIZE);
56+
if (archiveSize < ZIP_EOCD_REC_MIN_SIZE) {
57+
System.out.println("File size smaller than EOCD min size");
58+
return -1;
59+
}
60+
int maxCommentLength = Math.min(archiveSize - ZIP_EOCD_REC_MIN_SIZE, UINT32_MAX_VALUE);
61+
int eocdWithEmptyCommentStartPosition = archiveSize - ZIP_EOCD_REC_MIN_SIZE;
62+
for (int expectedCommentLength = 0; expectedCommentLength < maxCommentLength;
63+
expectedCommentLength++) {
64+
int eocdStartPos = eocdWithEmptyCommentStartPosition - expectedCommentLength;
65+
if (zipContents.getInt(eocdStartPos) == ZIP_EOCD_REC_SIG) {
66+
int actualCommentLength =
67+
getUnsignedInt16(
68+
zipContents, eocdStartPos + ZIP_EOCD_COMMENT_LENGTH_FIELD_OFFSET);
69+
if (actualCommentLength == expectedCommentLength) {
70+
return eocdStartPos;
71+
}
72+
}
73+
}
74+
return -1;
75+
}
76+
/**
77+
* Returns {@code true} if the provided buffer contains a ZIP64 End of Central Directory
78+
* Locator.
79+
*
80+
* <p>NOTE: Byte order of {@code zipContents} must be little-endian.
81+
*/
82+
public static final boolean isZip64EndOfCentralDirectoryLocatorPresent(
83+
ByteBuffer zipContents, int zipEndOfCentralDirectoryPosition) {
84+
assertByteOrderLittleEndian(zipContents);
85+
// ZIP64 End of Central Directory Locator immediately precedes the ZIP End of Central
86+
// Directory Record.
87+
int locatorPosition = zipEndOfCentralDirectoryPosition - ZIP64_EOCD_LOCATOR_SIZE;
88+
if (locatorPosition < 0) {
89+
return false;
90+
}
91+
return zipContents.getInt(locatorPosition) == ZIP64_EOCD_LOCATOR_SIG;
92+
}
93+
/**
94+
* Returns the offset of the start of the ZIP Central Directory in the archive.
95+
*
96+
* <p>NOTE: Byte order of {@code zipEndOfCentralDirectory} must be little-endian.
97+
*/
98+
public static long getZipEocdCentralDirectoryOffset(ByteBuffer zipEndOfCentralDirectory) {
99+
assertByteOrderLittleEndian(zipEndOfCentralDirectory);
100+
return getUnsignedInt32(
101+
zipEndOfCentralDirectory,
102+
zipEndOfCentralDirectory.position() + ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_OFFSET);
103+
}
104+
/**
105+
* Sets the offset of the start of the ZIP Central Directory in the archive.
106+
*
107+
* <p>NOTE: Byte order of {@code zipEndOfCentralDirectory} must be little-endian.
108+
*/
109+
public static void setZipEocdCentralDirectoryOffset(
110+
ByteBuffer zipEndOfCentralDirectory, long offset) {
111+
assertByteOrderLittleEndian(zipEndOfCentralDirectory);
112+
setUnsignedInt32(
113+
zipEndOfCentralDirectory,
114+
zipEndOfCentralDirectory.position() + ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_OFFSET,
115+
offset);
116+
}
117+
/**
118+
* Returns the size (in bytes) of the ZIP Central Directory.
119+
*
120+
* <p>NOTE: Byte order of {@code zipEndOfCentralDirectory} must be little-endian.
121+
*/
122+
public static long getZipEocdCentralDirectorySizeBytes(ByteBuffer zipEndOfCentralDirectory) {
123+
assertByteOrderLittleEndian(zipEndOfCentralDirectory);
124+
return getUnsignedInt32(
125+
zipEndOfCentralDirectory,
126+
zipEndOfCentralDirectory.position() + ZIP_EOCD_CENTRAL_DIR_SIZE_FIELD_OFFSET);
127+
}
128+
private static void assertByteOrderLittleEndian(ByteBuffer buffer) {
129+
if (buffer.order() != ByteOrder.LITTLE_ENDIAN) {
130+
throw new IllegalArgumentException("ByteBuffer byte order must be little endian");
131+
}
132+
}
133+
private static int getUnsignedInt16(ByteBuffer buffer, int offset) {
134+
return buffer.getShort(offset) & 0xffff;
135+
}
136+
private static long getUnsignedInt32(ByteBuffer buffer, int offset) {
137+
return buffer.getInt(offset) & 0xffffffffL;
138+
}
139+
private static void setUnsignedInt32(ByteBuffer buffer, int offset, long value) {
140+
if ((value < 0) || (value > 0xffffffffL)) {
141+
throw new IllegalArgumentException("uint32 value of out range: " + value);
142+
}
143+
buffer.putInt(buffer.position() + offset, (int) value);
144+
}
145+
}

mode/src/processing/mode/android/AndroidBuild.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -781,17 +781,22 @@ private File signPackage(File projectFolder, String keyStorePassword, String fil
781781
File unsignedPackage = new File(projectFolder,
782782
path + sketch.getName().toLowerCase() + "_release_unsigned." + fileExt);
783783
if (!unsignedPackage.exists()) return null;
784-
File signedPackage = new File(projectFolder,
785-
path + sketch.getName().toLowerCase() + "_release_signed." + fileExt);
784+
File signedPackageV1 = new File(projectFolder,
785+
path + sketch.getName().toLowerCase() + "_release_signed_v1." + fileExt);
786786

787-
JarSigner.signJarV1(unsignedPackage, signedPackage,
787+
JarSigner.signJarV1(unsignedPackage, signedPackageV1,
788788
AndroidKeyStore.ALIAS_STRING, keyStorePassword,
789789
keyStore.getAbsolutePath(), keyStorePassword);
790790

791791
if (isAAB) {
792-
return signedPackage;
792+
File signedPackageV2 = new File(projectFolder,
793+
path + sketch.getName().toLowerCase() + "_release_signed_v2." + fileExt);
794+
ApkSignerV2.signJarV2(signedPackageV1, signedPackageV2,
795+
AndroidKeyStore.ALIAS_STRING, keyStorePassword,
796+
keyStore.getAbsolutePath(), keyStorePassword);
797+
return signedPackageV2;
793798
} else {
794-
File alignedPackage = zipalignPackage(signedPackage, projectFolder, fileExt);
799+
File alignedPackage = zipalignPackage(signedPackageV1, projectFolder, fileExt);
795800
return alignedPackage;
796801
}
797802
}

0 commit comments

Comments
 (0)