Skip to content

Commit 67dcfab

Browse files
committed
refactor zip utils, try to correctly zip v2 package
1 parent 7adc607 commit 67dcfab

File tree

4 files changed

+101
-70
lines changed

4 files changed

+101
-70
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -792,8 +792,8 @@ private File signPackage(File projectFolder, String keyStorePassword, String fil
792792
File signedPackageV2 = new File(projectFolder,
793793
path + sketch.getName().toLowerCase() + "_release_signed_v2." + fileExt);
794794
ApkSignerV2.signJarV2(signedPackageV1, signedPackageV2,
795-
AndroidKeyStore.ALIAS_STRING, keyStorePassword,
796-
keyStore.getAbsolutePath(), keyStorePassword);
795+
AndroidKeyStore.ALIAS_STRING, keyStorePassword,
796+
keyStore.getAbsolutePath(), keyStorePassword);
797797
return signedPackageV2;
798798
} else {
799799
File alignedPackage = zipalignPackage(signedPackageV1, projectFolder, fileExt);

mode/src/processing/mode/android/ApkSignerV2.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@
4949
import java.io.FileOutputStream;
5050
import java.io.IOException;
5151

52+
import java.util.jar.Manifest;
53+
import java.util.jar.Attributes;
54+
import java.util.jar.JarOutputStream;
55+
5256
/**
5357
* APK Signature Scheme v2 signer.
5458
*
@@ -121,6 +125,10 @@ public static final class SignerConfig {
121125
}
122126

123127

128+
private static final String DIGEST_ALGORITHM = "SHA1";
129+
private static final String DIGEST_ATTR = "SHA1-Digest";
130+
131+
124132
public static void signJarV2(File jarToSign, File outputJar, String alias,
125133
String keypass, String keystore, String storepass)
126134
throws GeneralSecurityException, IOException,
@@ -162,7 +170,9 @@ public static void signJarV2(File jarToSign, File outputJar, String alias,
162170
inputBuffer.rewind();
163171
ByteBuffer[] output = sign(inputBuffer, signerConfigs);
164172

165-
FileOutputStream outputStream = new FileOutputStream(outputJar);
173+
// Save byte buffer with V2 signed jar into temp file
174+
File tempJar = new File(outputJar.getAbsolutePath() + ".tmp");
175+
FileOutputStream outputStream = new FileOutputStream(tempJar);
166176
for (ByteBuffer buf: output) {
167177
if (buf.hasArray()) {
168178
outputStream.write(buf.array());
@@ -174,6 +184,16 @@ public static void signJarV2(File jarToSign, File outputJar, String alias,
174184
}
175185
outputStream.close();
176186

187+
// Create zipped package
188+
Manifest manifest = new Manifest();
189+
Attributes main = manifest.getMainAttributes();
190+
main.putValue("Manifest-Version", "1.0");
191+
main.putValue("Created-By", "1.0 (Android)");
192+
main.putValue("X-Android-APK-Signed", "true");
193+
194+
JarOutputStream signedJar = new JarOutputStream(new FileOutputStream(outputJar, false));
195+
ZipUtils.writeZip(new FileInputStream(tempJar), signedJar, manifest, DIGEST_ALGORITHM, DIGEST_ATTR);
196+
177197
System.out.println("DONE!");
178198
}
179199

mode/src/processing/mode/android/JarSigner.java

Lines changed: 2 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@
3333
import java.util.jar.JarFile;
3434
import java.util.jar.JarOutputStream;
3535
import java.util.jar.Manifest;
36-
import java.util.zip.ZipEntry;
37-
import java.util.zip.ZipInputStream;
3836
import java.util.Base64;
3937
import sun.security.pkcs.SignerInfo;
4038
import sun.security.x509.AlgorithmId;
@@ -49,8 +47,7 @@ public class JarSigner {
4947
private static final String DIGEST_ALGORITHM = "SHA1";
5048
private static final String DIGEST_ATTR = "SHA1-Digest";
5149
private static final String DIGEST_MANIFEST_ATTR = "SHA1-Digest-Manifest";
52-
private static SignatureOutputStream certFileContents = null;
53-
private static byte[] buffer;
50+
private static SignatureOutputStream certFileContents = null;
5451

5552
public static void signJarV1(File jarToSign, File outputJar, String alias,
5653
String keypass, String keystore, String storepass)
@@ -84,73 +81,11 @@ public static void signJarV1(File jarToSign, File outputJar, String alias,
8481
main.putValue("X-Android-APK-Signed", "true");
8582
}
8683

87-
writeZip(new FileInputStream(jarToSign), signedJar, manifest);
84+
ZipUtils.writeZip(new FileInputStream(jarToSign), signedJar, manifest, DIGEST_ALGORITHM, DIGEST_ATTR);
8885

8986
closeJar(signedJar, manifest, privateKey, x509Cert);
9087
}
9188

92-
private static void writeZip(InputStream input, JarOutputStream output, Manifest manifest)
93-
throws IOException, NoSuchAlgorithmException {
94-
Base64.Encoder base64Encoder = Base64.getEncoder();
95-
MessageDigest messageDigest = MessageDigest.getInstance(DIGEST_ALGORITHM);
96-
buffer = new byte[4096];
97-
98-
ZipInputStream zis = new ZipInputStream(input);
99-
100-
try {
101-
// loop on the entries of the intermediary package and put them in the final package.
102-
ZipEntry entry;
103-
while ((entry = zis.getNextEntry()) != null) {
104-
String name = entry.getName();
105-
106-
// do not take directories or anything inside a potential META-INF folder.
107-
if (entry.isDirectory() || name.startsWith("META-INF/")) {
108-
continue;
109-
}
110-
111-
JarEntry newEntry;
112-
113-
// Preserve the STORED method of the input entry.
114-
if (entry.getMethod() == JarEntry.STORED) {
115-
newEntry = new JarEntry(entry);
116-
} else {
117-
// Create a new entry so that the compressed len is recomputed.
118-
newEntry = new JarEntry(name);
119-
}
120-
121-
writeEntry(output, zis, newEntry, messageDigest, manifest, base64Encoder);
122-
123-
zis.closeEntry();
124-
}
125-
} finally {
126-
zis.close();
127-
}
128-
}
129-
130-
private static void writeEntry(JarOutputStream output, InputStream input, JarEntry entry,
131-
MessageDigest digest, Manifest manifest, Base64.Encoder encoder) throws IOException {
132-
output.putNextEntry(entry);
133-
134-
// Write input stream to the jar output.
135-
int count;
136-
while ((count = input.read(buffer)) != -1) {
137-
output.write(buffer, 0, count);
138-
139-
if (digest != null) digest.update(buffer, 0, count);
140-
}
141-
142-
output.closeEntry();
143-
144-
if (manifest != null) {
145-
Attributes attr = manifest.getAttributes(entry.getName());
146-
if (attr == null) {
147-
attr = new Attributes();
148-
manifest.getEntries().put(entry.getName(), attr);
149-
}
150-
attr.putValue(DIGEST_ATTR, encoder.encodeToString(digest.digest()));
151-
}
152-
}
153-
15489
private static void closeJar(JarOutputStream jar, Manifest manifest,
15590
PrivateKey key, X509Certificate cert)
15691
throws IOException, GeneralSecurityException {

mode/src/processing/mode/android/ZipUtils.java

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,27 @@
1818
import java.nio.ByteBuffer;
1919
import java.nio.ByteOrder;
2020

21+
import java.security.MessageDigest;
22+
import java.security.NoSuchAlgorithmException;
23+
import java.io.InputStream;
24+
import java.io.IOException;
25+
import java.util.jar.JarEntry;
26+
import java.util.jar.Attributes;
27+
import java.util.jar.Manifest;
28+
import java.util.jar.JarOutputStream;
29+
import java.util.zip.ZipEntry;
30+
import java.util.zip.ZipInputStream;
31+
import java.util.Base64;
32+
2133
/**
2234
* Assorted ZIP format helpers.
2335
*
2436
* <p>NOTE: Most helper methods operating on {@code ByteBuffer} instances expect that the byte
2537
* order of these buffers is little-endian.
2638
*/
2739
public abstract class ZipUtils {
40+
private static byte[] buffer;
41+
2842
private ZipUtils() {}
2943
private static final int ZIP_EOCD_REC_MIN_SIZE = 22;
3044
private static final int ZIP_EOCD_REC_SIG = 0x06054b50;
@@ -142,4 +156,66 @@ private static void setUnsignedInt32(ByteBuffer buffer, int offset, long value)
142156
}
143157
buffer.putInt(buffer.position() + offset, (int) value);
144158
}
159+
160+
public static void writeZip(InputStream input, JarOutputStream output, Manifest manifest,
161+
String digestAlgorithm, String digestAttr)
162+
throws IOException, NoSuchAlgorithmException {
163+
Base64.Encoder base64Encoder = Base64.getEncoder();
164+
MessageDigest messageDigest = MessageDigest.getInstance(digestAlgorithm);
165+
buffer = new byte[4096];
166+
167+
ZipInputStream zis = new ZipInputStream(input);
168+
169+
try {
170+
// loop on the entries of the intermediary package and put them in the final package.
171+
ZipEntry entry;
172+
while ((entry = zis.getNextEntry()) != null) {
173+
String name = entry.getName();
174+
175+
// do not take directories or anything inside a potential META-INF folder.
176+
if (entry.isDirectory() || name.startsWith("META-INF/")) {
177+
continue;
178+
}
179+
180+
JarEntry newEntry;
181+
182+
// Preserve the STORED method of the input entry.
183+
if (entry.getMethod() == JarEntry.STORED) {
184+
newEntry = new JarEntry(entry);
185+
} else {
186+
// Create a new entry so that the compressed len is recomputed.
187+
newEntry = new JarEntry(name);
188+
}
189+
190+
writeEntry(output, zis, newEntry, messageDigest, manifest, base64Encoder, digestAttr);
191+
192+
zis.closeEntry();
193+
}
194+
} finally {
195+
zis.close();
196+
}
197+
}
198+
199+
private static void writeEntry(JarOutputStream output, InputStream input, JarEntry entry,
200+
MessageDigest digest, Manifest manifest, Base64.Encoder encoder, String digestAttr) throws IOException {
201+
output.putNextEntry(entry);
202+
203+
// Write input stream to the jar output.
204+
int count;
205+
while ((count = input.read(buffer)) != -1) {
206+
output.write(buffer, 0, count);
207+
if (digest != null) digest.update(buffer, 0, count);
208+
}
209+
210+
output.closeEntry();
211+
212+
if (manifest != null) {
213+
Attributes attr = manifest.getAttributes(entry.getName());
214+
if (attr == null) {
215+
attr = new Attributes();
216+
manifest.getEntries().put(entry.getName(), attr);
217+
}
218+
attr.putValue(digestAttr, encoder.encodeToString(digest.digest()));
219+
}
220+
}
145221
}

0 commit comments

Comments
 (0)