diff --git a/app/build.gradle b/app/build.gradle index 52cf3dba6..d5bcd6ac6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,7 +8,7 @@ android { applicationId "com.topjohnwu.magisk" minSdkVersion 21 targetSdkVersion 27 - versionCode 64 + versionCode 66 versionName "5.4.3" ndk { moduleName 'zipadjust' diff --git a/crypto/build.gradle b/crypto/build.gradle index 9a9a419ec..edfb254cd 100644 --- a/crypto/build.gradle +++ b/crypto/build.gradle @@ -15,7 +15,7 @@ jar { shadowJar { baseName = 'zipsigner' classifier = null - version = 1.0 + version = 1.1 } buildscript { diff --git a/crypto/src/main/java/com/topjohnwu/crypto/JarMap.java b/crypto/src/main/java/com/topjohnwu/crypto/JarMap.java index 334c5b8db..9db773949 100644 --- a/crypto/src/main/java/com/topjohnwu/crypto/JarMap.java +++ b/crypto/src/main/java/com/topjohnwu/crypto/JarMap.java @@ -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 bufMap = new LinkedHashMap<>(); + private boolean isInputStream = false; + private LinkedHashMap 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 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(); - } } } diff --git a/crypto/src/main/java/com/topjohnwu/crypto/SignAPK.java b/crypto/src/main/java/com/topjohnwu/crypto/SignAPK.java index a89691165..96c2aca5a 100644 --- a/crypto/src/main/java/com/topjohnwu/crypto/SignAPK.java +++ b/crypto/src/main/java/com/topjohnwu/crypto/SignAPK.java @@ -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();