Update SignAPK to use less memory
This commit is contained in:
parent
c1dd23f5e0
commit
2c69e2c151
@ -8,7 +8,7 @@ android {
|
|||||||
applicationId "com.topjohnwu.magisk"
|
applicationId "com.topjohnwu.magisk"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 27
|
targetSdkVersion 27
|
||||||
versionCode 64
|
versionCode 66
|
||||||
versionName "5.4.3"
|
versionName "5.4.3"
|
||||||
ndk {
|
ndk {
|
||||||
moduleName 'zipadjust'
|
moduleName 'zipadjust'
|
||||||
|
@ -15,7 +15,7 @@ jar {
|
|||||||
shadowJar {
|
shadowJar {
|
||||||
baseName = 'zipsigner'
|
baseName = 'zipsigner'
|
||||||
classifier = null
|
classifier = null
|
||||||
version = 1.0
|
version = 1.1
|
||||||
}
|
}
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
|
@ -2,8 +2,6 @@ package com.topjohnwu.crypto;
|
|||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
@ -28,10 +26,8 @@ import java.util.zip.ZipFile;
|
|||||||
public class JarMap implements Closeable, AutoCloseable {
|
public class JarMap implements Closeable, AutoCloseable {
|
||||||
private JarFile jarFile;
|
private JarFile jarFile;
|
||||||
private JarInputStream jis;
|
private JarInputStream jis;
|
||||||
private InputStream is;
|
private boolean isInputStream = false;
|
||||||
private File file;
|
private LinkedHashMap<String, JarEntry> bufMap;
|
||||||
private boolean isInputStream = false, hasLoaded = false, verify;
|
|
||||||
private LinkedHashMap<String, JarEntry> bufMap = new LinkedHashMap<>();
|
|
||||||
|
|
||||||
public JarMap(File file) throws IOException {
|
public JarMap(File file) throws IOException {
|
||||||
this(file, true);
|
this(file, true);
|
||||||
@ -42,7 +38,6 @@ public class JarMap implements Closeable, AutoCloseable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public JarMap(File file, boolean verify, int mode) throws IOException {
|
public JarMap(File file, boolean verify, int mode) throws IOException {
|
||||||
this.file = file;
|
|
||||||
jarFile = new JarFile(file, verify, mode);
|
jarFile = new JarFile(file, verify, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,47 +55,30 @@ public class JarMap implements Closeable, AutoCloseable {
|
|||||||
|
|
||||||
public JarMap(InputStream is, boolean verify) throws IOException {
|
public JarMap(InputStream is, boolean verify) throws IOException {
|
||||||
isInputStream = true;
|
isInputStream = true;
|
||||||
this.is = is;
|
bufMap = new LinkedHashMap<>();
|
||||||
this.verify = verify;
|
jis = new JarInputStream(is, verify);
|
||||||
}
|
|
||||||
|
|
||||||
private void loadJarInputStream() {
|
|
||||||
if (!isInputStream || hasLoaded) return;
|
|
||||||
hasLoaded = true;
|
|
||||||
JarEntry entry;
|
JarEntry entry;
|
||||||
try {
|
while ((entry = jis.getNextJarEntry()) != null) {
|
||||||
jis = new JarInputStream(is, verify);
|
bufMap.put(entry.getName(), new JarMapEntry(entry, jis));
|
||||||
while ((entry = jis.getNextJarEntry()) != null) {
|
|
||||||
bufMap.put(entry.getName(), new JarMapEntry(entry, jis));
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getInputStream() {
|
public File getFile() {
|
||||||
try {
|
return isInputStream ? null : new File(jarFile.getName());
|
||||||
return isInputStream ? is : new FileInputStream(file);
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Manifest getManifest() throws IOException {
|
public Manifest getManifest() throws IOException {
|
||||||
loadJarInputStream();
|
|
||||||
return isInputStream ? jis.getManifest() : jarFile.getManifest();
|
return isInputStream ? jis.getManifest() : jarFile.getManifest();
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getInputStream(ZipEntry ze) throws IOException {
|
public InputStream getInputStream(ZipEntry ze) throws IOException {
|
||||||
loadJarInputStream();
|
return isInputStream ? ((JarMapEntry) bufMap.get(ze.getName())).data.getInputStream() :
|
||||||
return isInputStream ? ((JarMapEntry) bufMap.get(ze.getName())).getInputStream() :
|
|
||||||
jarFile.getInputStream(ze);
|
jarFile.getInputStream(ze);
|
||||||
}
|
}
|
||||||
|
|
||||||
public OutputStream getOutputStream(ZipEntry ze) {
|
public OutputStream getOutputStream(ZipEntry ze) {
|
||||||
if (!isInputStream) // Only support inputstream mode
|
if (!isInputStream) // Only support InputStream mode
|
||||||
return null;
|
return null;
|
||||||
loadJarInputStream();
|
|
||||||
ByteArrayStream bs = ((JarMapEntry) bufMap.get(ze.getName())).data;
|
ByteArrayStream bs = ((JarMapEntry) bufMap.get(ze.getName())).data;
|
||||||
bs.reset();
|
bs.reset();
|
||||||
return bs;
|
return bs;
|
||||||
@ -108,7 +86,6 @@ public class JarMap implements Closeable, AutoCloseable {
|
|||||||
|
|
||||||
public byte[] getRawData(ZipEntry ze) throws IOException {
|
public byte[] getRawData(ZipEntry ze) throws IOException {
|
||||||
if (isInputStream) {
|
if (isInputStream) {
|
||||||
loadJarInputStream();
|
|
||||||
return ((JarMapEntry) bufMap.get(ze.getName())).data.toByteArray();
|
return ((JarMapEntry) bufMap.get(ze.getName())).data.toByteArray();
|
||||||
} else {
|
} else {
|
||||||
ByteArrayStream bytes = new ByteArrayStream();
|
ByteArrayStream bytes = new ByteArrayStream();
|
||||||
@ -118,7 +95,6 @@ public class JarMap implements Closeable, AutoCloseable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Enumeration<JarEntry> entries() {
|
public Enumeration<JarEntry> entries() {
|
||||||
loadJarInputStream();
|
|
||||||
return isInputStream ? Collections.enumeration(bufMap.values()) : jarFile.entries();
|
return isInputStream ? Collections.enumeration(bufMap.values()) : jarFile.entries();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,16 +103,12 @@ public class JarMap implements Closeable, AutoCloseable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public JarEntry getJarEntry(String name) {
|
public JarEntry getJarEntry(String name) {
|
||||||
loadJarInputStream();
|
|
||||||
return isInputStream ? bufMap.get(name) : jarFile.getJarEntry(name);
|
return isInputStream ? bufMap.get(name) : jarFile.getJarEntry(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
if (isInputStream)
|
(isInputStream ? jis : jarFile).close();
|
||||||
is.close();
|
|
||||||
else
|
|
||||||
jarFile.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class JarMapEntry extends JarEntry {
|
private static class JarMapEntry extends JarEntry {
|
||||||
@ -146,8 +118,5 @@ public class JarMap implements Closeable, AutoCloseable {
|
|||||||
data = new ByteArrayStream();
|
data = new ByteArrayStream();
|
||||||
data.readFrom(is);
|
data.readFrom(is);
|
||||||
}
|
}
|
||||||
InputStream getInputStream() {
|
|
||||||
return data.getInputStream();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,12 +21,14 @@ import org.bouncycastle.util.encoders.Base64;
|
|||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.FilterOutputStream;
|
import java.io.FilterOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
import java.security.DigestOutputStream;
|
import java.security.DigestOutputStream;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
@ -36,7 +38,6 @@ import java.security.Security;
|
|||||||
import java.security.cert.CertificateEncodingException;
|
import java.security.cert.CertificateEncodingException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -84,7 +85,7 @@ public class SignAPK {
|
|||||||
|
|
||||||
outputFile = new BufferedOutputStream(new FileOutputStream(output));
|
outputFile = new BufferedOutputStream(new FileOutputStream(output));
|
||||||
if (minSign) {
|
if (minSign) {
|
||||||
signWholeFile(input.getInputStream(), publicKey, privateKey, outputFile);
|
signWholeFile(input.getFile(), publicKey, privateKey, outputFile);
|
||||||
} else {
|
} else {
|
||||||
JarOutputStream outputJar = new JarOutputStream(outputFile);
|
JarOutputStream outputJar = new JarOutputStream(outputFile);
|
||||||
// For signing .apks, use the maximum compression to make
|
// For signing .apks, use the maximum compression to make
|
||||||
@ -373,15 +374,12 @@ public class SignAPK {
|
|||||||
// Used for signWholeFile
|
// Used for signWholeFile
|
||||||
private static class CMSProcessableFile implements CMSTypedData {
|
private static class CMSProcessableFile implements CMSTypedData {
|
||||||
|
|
||||||
private InputStream is;
|
|
||||||
private ASN1ObjectIdentifier type;
|
private ASN1ObjectIdentifier type;
|
||||||
ByteArrayStream bos;
|
private RandomAccessFile file;
|
||||||
|
|
||||||
CMSProcessableFile(InputStream is) {
|
CMSProcessableFile(File file) throws FileNotFoundException {
|
||||||
this.is = is;
|
this.file = new RandomAccessFile(file, "r");
|
||||||
type = new ASN1ObjectIdentifier(CMSObjectIdentifiers.data.getId());
|
type = new ASN1ObjectIdentifier(CMSObjectIdentifiers.data.getId());
|
||||||
bos = new ByteArrayStream();
|
|
||||||
bos.readFrom(is);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -391,20 +389,30 @@ public class SignAPK {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(OutputStream out) throws IOException, CMSException {
|
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
|
@Override
|
||||||
public Object getContent() {
|
public Object getContent() {
|
||||||
return is;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] getTail() {
|
byte[] getTail() throws IOException {
|
||||||
return Arrays.copyOfRange(bos.getBuf(), bos.size() - 22, bos.size());
|
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)
|
PrivateKey privateKey, OutputStream outputStream)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
ByteArrayOutputStream temp = new ByteArrayOutputStream();
|
ByteArrayOutputStream temp = new ByteArrayOutputStream();
|
||||||
|
Loading…
Reference in New Issue
Block a user