Fix v1 signing
This commit is contained in:
parent
1ced48aa49
commit
980c7bba4b
|
|
@ -8,7 +8,7 @@ buildscript {
|
|||
maven { url "https://jitpack.io" }
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.1.0-alpha09'
|
||||
classpath 'com.android.tools.build:gradle:7.1.0-alpha10'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import java.io.InputStream;
|
|||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.security.KeyStore;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
|
@ -142,8 +143,6 @@ public class LSPatch {
|
|||
throw new PatchError(outputPath + " exists. Use --force to overwrite");
|
||||
System.out.println("Processing " + srcApkFile + " -> " + outputFile);
|
||||
|
||||
if (v1) System.err.println("\nWarning: Sign with v1 signature may cause installation failure\n");
|
||||
|
||||
patch(srcApkFile, outputFile);
|
||||
}
|
||||
}
|
||||
|
|
@ -265,7 +264,27 @@ public class LSPatch {
|
|||
if (verbose)
|
||||
System.out.println("Creating nested apk link...");
|
||||
|
||||
NestedZipLink nestedZipLink = new NestedZipLink(dstZFile);
|
||||
SigningExtension signingExtension = null;
|
||||
// sign apk
|
||||
System.out.println("Signing apk...");
|
||||
try {
|
||||
var keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
try (var is = getClass().getClassLoader().getResourceAsStream("assets/keystore")) {
|
||||
keyStore.load(is, "123456".toCharArray());
|
||||
}
|
||||
var entry = (KeyStore.PrivateKeyEntry) keyStore.getEntry("key0", new KeyStore.PasswordProtection("123456".toCharArray()));
|
||||
signingExtension = new SigningExtension(SigningOptions.builder()
|
||||
.setMinSdkVersion(27)
|
||||
.setV1SigningEnabled(v1)
|
||||
.setV2SigningEnabled(v2)
|
||||
.setCertificates((X509Certificate[]) entry.getCertificateChain())
|
||||
.setKey(entry.getPrivateKey())
|
||||
.build());
|
||||
} catch (Exception e) {
|
||||
throw new PatchError("Failed to create signer: " + e);
|
||||
}
|
||||
|
||||
NestedZipLink nestedZipLink = new NestedZipLink(dstZFile, signingExtension);
|
||||
StoredEntry originalZipEntry = dstZFile.get(ORIGINAL_APK_ASSET_PATH);
|
||||
NestedZip nestedZip = new NestedZip(srcZFile, originalZipEntry);
|
||||
for (StoredEntry entry : srcZFile.entries()) {
|
||||
|
|
@ -291,25 +310,10 @@ public class LSPatch {
|
|||
nestedZipLink.nestedZips.add(nestedZip);
|
||||
}
|
||||
|
||||
dstZFile.addZFileExtension(nestedZipLink);
|
||||
|
||||
// sign apk
|
||||
System.out.println("Signing apk...");
|
||||
try {
|
||||
var keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
try (var is = getClass().getClassLoader().getResourceAsStream("assets/keystore")) {
|
||||
keyStore.load(is, "123456".toCharArray());
|
||||
}
|
||||
var entry = (KeyStore.PrivateKeyEntry) keyStore.getEntry("key0", new KeyStore.PasswordProtection("123456".toCharArray()));
|
||||
new SigningExtension(SigningOptions.builder()
|
||||
.setMinSdkVersion(27)
|
||||
.setV1SigningEnabled(v1)
|
||||
.setV2SigningEnabled(v2)
|
||||
.setCertificates((X509Certificate[]) entry.getCertificateChain())
|
||||
.setKey(entry.getPrivateKey())
|
||||
.build()).register(dstZFile);
|
||||
} catch (Exception e) {
|
||||
throw new PatchError("Failed to sign apk: " + e);
|
||||
nestedZipLink.register();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new PatchError("Failed to create link: " + e);
|
||||
}
|
||||
|
||||
System.out.println("Done. Output APK: " + outputFile.getAbsolutePath());
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package org.lsposed.patch.util;
|
||||
|
||||
import com.android.apksig.ApkSignerEngine;
|
||||
import com.android.apksig.internal.util.Pair;
|
||||
import com.android.tools.build.apkzlib.sign.SigningExtension;
|
||||
import com.android.tools.build.apkzlib.utils.IOExceptionRunnable;
|
||||
import com.android.tools.build.apkzlib.zip.CentralDirectoryHeader;
|
||||
import com.android.tools.build.apkzlib.zip.EncodeUtils;
|
||||
|
|
@ -8,9 +10,12 @@ import com.android.tools.build.apkzlib.zip.StoredEntry;
|
|||
import com.android.tools.build.apkzlib.zip.ZFile;
|
||||
import com.android.tools.build.apkzlib.zip.ZFileExtension;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
|
@ -38,14 +43,38 @@ public class NestedZipLink extends ZFileExtension {
|
|||
|
||||
private boolean written;
|
||||
|
||||
public NestedZipLink(ZFile zFile) {
|
||||
public final SigningExtension signingExtension;
|
||||
|
||||
public NestedZipLink(ZFile zFile, SigningExtension signingExtension) {
|
||||
this.zFile = zFile;
|
||||
this.signingExtension = signingExtension;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IOExceptionRunnable beforeUpdate() {
|
||||
written = false;
|
||||
return null;
|
||||
return () -> {
|
||||
written = false;
|
||||
try {
|
||||
|
||||
var signerField = SigningExtension.class.getDeclaredField("signer");
|
||||
signerField.setAccessible(true);
|
||||
var signer = (ApkSignerEngine) signerField.get(signingExtension);
|
||||
|
||||
for (var nestedZip : nestedZips) {
|
||||
for (var link : nestedZip.links) {
|
||||
var entry = nestedZip.zip.get(link.getFirst());
|
||||
if (entry == null)
|
||||
throw new IOException("Entry " + link + " does not exist in nested zip");
|
||||
notifySigner(signer, link.getFirst(), entry);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
var ex = new IOException("Error when writing link entries");
|
||||
ex.addSuppressed(e);
|
||||
throw ex;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -93,7 +122,8 @@ public class NestedZipLink extends ZFileExtension {
|
|||
long nestedZipOffset = nestedZip.entry.getCentralDirectoryHeader().getOffset();
|
||||
for (var link : nestedZip.links) {
|
||||
var entry = nestedZip.zip.get(link.getFirst());
|
||||
if (entry == null) throw new IOException("Entry " + link + " does not exist in nested zip");
|
||||
if (entry == null)
|
||||
throw new IOException("Entry " + link + " does not exist in nested zip");
|
||||
CentralDirectoryHeader cdh = entry.getCentralDirectoryHeader();
|
||||
field_entry_file.set(entry, zFile);
|
||||
field_cdh_file.set(cdh, zFile);
|
||||
|
|
@ -107,6 +137,21 @@ public class NestedZipLink extends ZFileExtension {
|
|||
computeEocd.invoke(zFile);
|
||||
}
|
||||
|
||||
private void notifySigner(ApkSignerEngine signer, String entryName, StoredEntry entry) throws IOException {
|
||||
ApkSignerEngine.InspectJarEntryRequest inspectEntryRequest = signer.outputJarEntry(entryName);
|
||||
if (inspectEntryRequest != null) {
|
||||
try (InputStream inputStream = new BufferedInputStream(entry.open())) {
|
||||
int bytesRead;
|
||||
byte[] buffer = new byte[65536];
|
||||
var dataSink = inspectEntryRequest.getDataSink();
|
||||
while ((bytesRead = inputStream.read(buffer)) > 0) {
|
||||
dataSink.consume(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
inspectEntryRequest.done();
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] encodeFileName(String name) throws Exception {
|
||||
Class<?> GPFlags = Class.forName("com.android.tools.build.apkzlib.zip.GPFlags");
|
||||
Method make = GPFlags.getDeclaredMethod("make", boolean.class);
|
||||
|
|
@ -117,4 +162,9 @@ public class NestedZipLink extends ZFileExtension {
|
|||
var flags = make.invoke(null, encodeWithUtf8);
|
||||
return (byte[]) encode.invoke(null, name, flags);
|
||||
}
|
||||
|
||||
public void register() throws NoSuchAlgorithmException, IOException {
|
||||
zFile.addZFileExtension(this);
|
||||
signingExtension.register(zFile);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue