Update SignAPK to use less memory

This commit is contained in:
topjohnwu 2017-12-01 11:19:38 +08:00
parent c1dd23f5e0
commit 2c69e2c151
4 changed files with 34 additions and 57 deletions

View File

@ -8,7 +8,7 @@ android {
applicationId "com.topjohnwu.magisk"
minSdkVersion 21
targetSdkVersion 27
versionCode 64
versionCode 66
versionName "5.4.3"
ndk {
moduleName 'zipadjust'

View File

@ -15,7 +15,7 @@ jar {
shadowJar {
baseName = 'zipsigner'
classifier = null
version = 1.0
version = 1.1
}
buildscript {

View File

@ -2,8 +2,6 @@ package com.topjohnwu.crypto;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -28,10 +26,8 @@ import java.util.zip.ZipFile;
public class JarMap implements Closeable, AutoCloseable {
private JarFile jarFile;
private JarInputStream jis;
private InputStream is;
private File file;
private boolean isInputStream = false, hasLoaded = false, verify;
private LinkedHashMap<String, JarEntry> bufMap = new LinkedHashMap<>();
private boolean isInputStream = false;
private LinkedHashMap<String, JarEntry> bufMap;
public JarMap(File file) throws IOException {
this(file, true);
@ -42,7 +38,6 @@ public class JarMap implements Closeable, AutoCloseable {
}
public JarMap(File file, boolean verify, int mode) throws IOException {
this.file = file;
jarFile = new JarFile(file, verify, mode);
}
@ -60,47 +55,30 @@ public class JarMap implements Closeable, AutoCloseable {
public JarMap(InputStream is, boolean verify) throws IOException {
isInputStream = true;
this.is = is;
this.verify = verify;
}
private void loadJarInputStream() {
if (!isInputStream || hasLoaded) return;
hasLoaded = true;
bufMap = new LinkedHashMap<>();
jis = new JarInputStream(is, verify);
JarEntry entry;
try {
jis = new JarInputStream(is, verify);
while ((entry = jis.getNextJarEntry()) != null) {
bufMap.put(entry.getName(), new JarMapEntry(entry, jis));
}
} catch (IOException e) {
e.printStackTrace();
while ((entry = jis.getNextJarEntry()) != null) {
bufMap.put(entry.getName(), new JarMapEntry(entry, jis));
}
}
public InputStream getInputStream() {
try {
return isInputStream ? is : new FileInputStream(file);
} catch (FileNotFoundException e) {
return null;
}
public File getFile() {
return isInputStream ? null : new File(jarFile.getName());
}
public Manifest getManifest() throws IOException {
loadJarInputStream();
return isInputStream ? jis.getManifest() : jarFile.getManifest();
}
public InputStream getInputStream(ZipEntry ze) throws IOException {
loadJarInputStream();
return isInputStream ? ((JarMapEntry) bufMap.get(ze.getName())).getInputStream() :
return isInputStream ? ((JarMapEntry) bufMap.get(ze.getName())).data.getInputStream() :
jarFile.getInputStream(ze);
}
public OutputStream getOutputStream(ZipEntry ze) {
if (!isInputStream) // Only support inputstream mode
if (!isInputStream) // Only support InputStream mode
return null;
loadJarInputStream();
ByteArrayStream bs = ((JarMapEntry) bufMap.get(ze.getName())).data;
bs.reset();
return bs;
@ -108,7 +86,6 @@ public class JarMap implements Closeable, AutoCloseable {
public byte[] getRawData(ZipEntry ze) throws IOException {
if (isInputStream) {
loadJarInputStream();
return ((JarMapEntry) bufMap.get(ze.getName())).data.toByteArray();
} else {
ByteArrayStream bytes = new ByteArrayStream();
@ -118,7 +95,6 @@ public class JarMap implements Closeable, AutoCloseable {
}
public Enumeration<JarEntry> entries() {
loadJarInputStream();
return isInputStream ? Collections.enumeration(bufMap.values()) : jarFile.entries();
}
@ -127,16 +103,12 @@ public class JarMap implements Closeable, AutoCloseable {
}
public JarEntry getJarEntry(String name) {
loadJarInputStream();
return isInputStream ? bufMap.get(name) : jarFile.getJarEntry(name);
}
@Override
public void close() throws IOException {
if (isInputStream)
is.close();
else
jarFile.close();
(isInputStream ? jis : jarFile).close();
}
private static class JarMapEntry extends JarEntry {
@ -146,8 +118,5 @@ public class JarMap implements Closeable, AutoCloseable {
data = new ByteArrayStream();
data.readFrom(is);
}
InputStream getInputStream() {
return data.getInputStream();
}
}
}

View File

@ -21,12 +21,14 @@ import org.bouncycastle.util.encoders.Base64;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.RandomAccessFile;
import java.security.DigestOutputStream;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
@ -36,7 +38,6 @@ import java.security.Security;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Locale;
@ -84,7 +85,7 @@ public class SignAPK {
outputFile = new BufferedOutputStream(new FileOutputStream(output));
if (minSign) {
signWholeFile(input.getInputStream(), publicKey, privateKey, outputFile);
signWholeFile(input.getFile(), publicKey, privateKey, outputFile);
} else {
JarOutputStream outputJar = new JarOutputStream(outputFile);
// For signing .apks, use the maximum compression to make
@ -373,15 +374,12 @@ public class SignAPK {
// Used for signWholeFile
private static class CMSProcessableFile implements CMSTypedData {
private InputStream is;
private ASN1ObjectIdentifier type;
ByteArrayStream bos;
private RandomAccessFile file;
CMSProcessableFile(InputStream is) {
this.is = is;
CMSProcessableFile(File file) throws FileNotFoundException {
this.file = new RandomAccessFile(file, "r");
type = new ASN1ObjectIdentifier(CMSObjectIdentifiers.data.getId());
bos = new ByteArrayStream();
bos.readFrom(is);
}
@Override
@ -391,20 +389,30 @@ public class SignAPK {
@Override
public void write(OutputStream out) throws IOException, CMSException {
bos.writeTo(out, 0, bos.size() - 2);
file.seek(0);
int read;
byte buffer[] = new byte[4096];
int len = (int) file.length() - 2;
while ((read = file.read(buffer, 0, len < buffer.length ? len : buffer.length)) > 0) {
out.write(buffer, 0, read);
len -= read;
}
}
@Override
public Object getContent() {
return is;
return file;
}
byte[] getTail() {
return Arrays.copyOfRange(bos.getBuf(), bos.size() - 22, bos.size());
byte[] getTail() throws IOException {
byte tail[] = new byte[22];
file.seek(file.length() - 22);
file.readFully(tail);
return tail;
}
}
private static void signWholeFile(InputStream input, X509Certificate publicKey,
private static void signWholeFile(File input, X509Certificate publicKey,
PrivateKey privateKey, OutputStream outputStream)
throws Exception {
ByteArrayOutputStream temp = new ByteArrayOutputStream();