Embed testkeys into jar

This commit is contained in:
topjohnwu 2018-01-27 00:19:35 +08:00
parent 97cf15007f
commit c61135ee7b
9 changed files with 70 additions and 56 deletions

2
app

@ -1 +1 @@
Subproject commit 00d655f346fe6182d508d76d6b75d8e7357fcb9d
Subproject commit f37f330670b1dba2cc76d52d07587c7c605e096a

View File

@ -127,11 +127,6 @@ def build_binary(args):
def build_apk(args):
header('* Building Magisk Manager')
for key in ['public.certificate.x509.pem', 'private.key.pk8']:
source = os.path.join('ziptools', key)
target = os.path.join('app', 'src', 'main', 'assets', key)
cp(source, target)
for script in ['magisk_uninstaller.sh', 'util_functions.sh']:
source = os.path.join('scripts', script)
target = os.path.join('app', 'src', 'main', 'assets', script)
@ -331,7 +326,7 @@ def zip_uninstaller(args):
sign_adjust_zip(unsigned, output)
def sign_adjust_zip(unsigned, output):
signer_name = 'zipsigner-1.1.jar'
signer_name = 'zipsigner-2.0.jar'
jarsigner = os.path.join('crypto', 'build', 'libs', signer_name)
if os.name != 'nt' and not os.path.exists(os.path.join('ziptools', 'zipadjust')):
@ -348,14 +343,10 @@ def sign_adjust_zip(unsigned, output):
header('* Signing / Adjusting Zip')
publicKey = os.path.join('ziptools', 'public.certificate.x509.pem')
privateKey = os.path.join('ziptools', 'private.key.pk8')
signed = tempfile.mkstemp()[1]
# Unsigned->signed
proc = subprocess.run(['java', '-jar', jarsigner,
publicKey, privateKey, unsigned, signed])
proc = subprocess.run(['java', '-jar', jarsigner, unsigned, signed])
if proc.returncode != 0:
error('First sign flashable zip failed!')
@ -367,8 +358,7 @@ def sign_adjust_zip(unsigned, output):
error('Adjust flashable zip failed!')
# Adjusted -> output
proc = subprocess.run(['java', '-jar', jarsigner,
"-m", publicKey, privateKey, adjusted, output])
proc = subprocess.run(['java', '-jar', jarsigner, "-m", adjusted, output])
if proc.returncode != 0:
error('Second sign flashable zip failed!')

View File

@ -15,7 +15,7 @@ jar {
shadowJar {
baseName = 'zipsigner'
classifier = null
version = 1.1
version = 2.0
}
buildscript {
@ -23,7 +23,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.1'
classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.2'
}
}

View File

@ -102,7 +102,7 @@ class CryptoUtils {
return signer.sign();
}
static X509Certificate readPublicKey(InputStream input)
static X509Certificate readCertificate(InputStream input)
throws IOException, GeneralSecurityException {
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
@ -116,9 +116,9 @@ class CryptoUtils {
static PrivateKey readPrivateKey(InputStream input)
throws IOException, GeneralSecurityException {
try {
byte[] buffer = new byte[4096];
int size = input.read(buffer);
byte[] bytes = Arrays.copyOf(buffer, size);
ByteArrayStream buf = new ByteArrayStream();
buf.readFrom(input);
byte[] bytes = buf.toByteArray();
/* Check to see if this is in an EncryptedPrivateKeyInfo structure. */
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
/*

View File

@ -18,11 +18,9 @@ import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
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;
@ -69,21 +67,27 @@ public class SignAPK {
Security.insertProviderAt(sBouncyCastleProvider, 1);
}
public static void signZip(InputStream publicIn, InputStream privateIn,
public static void signZip(InputStream cert, InputStream key,
JarMap input, OutputStream output, boolean minSign) throws Exception {
int alignment = 4;
int hashes = 0;
X509Certificate publicKey = CryptoUtils.readPublicKey(publicIn);
hashes |= getDigestAlgorithm(publicKey);
if (cert == null) {
cert = SignAPK.class.getResourceAsStream("/keys/testkey.x509.pem");
}
X509Certificate certificate = CryptoUtils.readCertificate(cert);
hashes |= getDigestAlgorithm(certificate);
// Set the ZIP file timestamp to the starting valid time
// of the 0th certificate plus one hour (to match what
// we've historically done).
long timestamp = publicKey.getNotBefore().getTime() + 3600L * 1000;
PrivateKey privateKey = CryptoUtils.readPrivateKey(privateIn);
long timestamp = certificate.getNotBefore().getTime() + 3600L * 1000;
if (key == null) {
key = SignAPK.class.getResourceAsStream("/keys/testkey.pk8");
}
PrivateKey privateKey = CryptoUtils.readPrivateKey(key);
if (minSign) {
signWholeFile(input.getFile(), publicKey, privateKey, output);
signWholeFile(input.getFile(), certificate, privateKey, output);
} else {
JarOutputStream outputJar = new JarOutputStream(output);
// For signing .apks, use the maximum compression to make
@ -95,7 +99,8 @@ public class SignAPK {
outputJar.setLevel(9);
Manifest manifest = addDigestsToManifest(input, hashes);
copyFiles(manifest, input, outputJar, timestamp, alignment);
signFile(manifest, input, publicKey, privateKey, outputJar);
signFile(manifest, input, certificate, privateKey, outputJar);
outputJar.close();
}
}

View File

@ -35,7 +35,7 @@ public class SignBoot {
}
public static boolean doSignature(String target, InputStream imgIn, OutputStream imgOut,
InputStream keyIn, InputStream certIn) {
InputStream cert, InputStream key) {
try {
ByteArrayStream bas = new ByteArrayStream();
bas.readFrom(imgIn);
@ -51,23 +51,29 @@ public class SignBoot {
signableSize + " bytes");
}
BootSignature bootsig = new BootSignature(target, image.length);
X509Certificate cert = CryptoUtils.readPublicKey(certIn);
bootsig.setCertificate(cert);
PrivateKey key = CryptoUtils.readPrivateKey(keyIn);
bootsig.setSignature(bootsig.sign(image, key),
CryptoUtils.getSignatureAlgorithmIdentifier(key));
if (cert == null) {
cert = SignBoot.class.getResourceAsStream("/keys/testkey.x509.pem");
}
X509Certificate certificate = CryptoUtils.readCertificate(cert);
bootsig.setCertificate(certificate);
if (key == null) {
key = SignBoot.class.getResourceAsStream("/keys/testkey.pk8");
}
PrivateKey privateKey = CryptoUtils.readPrivateKey(key);
bootsig.setSignature(bootsig.sign(image, privateKey),
CryptoUtils.getSignatureAlgorithmIdentifier(privateKey));
byte[] encoded_bootsig = bootsig.getEncoded();
imgOut.write(image);
imgOut.write(encoded_bootsig);
imgOut.flush();
return true;
} catch (Exception e) {
e.printStackTrace(System.err);
e.printStackTrace();
return false;
}
}
public static boolean verifySignature(InputStream imgIn, InputStream certPath) {
public static boolean verifySignature(InputStream imgIn, InputStream certIn) {
try {
ByteArrayStream bas = new ByteArrayStream();
bas.readFrom(imgIn);
@ -80,8 +86,8 @@ public class SignBoot {
}
byte[] signature = Arrays.copyOfRange(image, signableSize, image.length);
BootSignature bootsig = new BootSignature(signature);
if (certPath != null) {
bootsig.setCertificate(CryptoUtils.readPublicKey(certPath));
if (certIn != null) {
bootsig.setCertificate(CryptoUtils.readCertificate(certIn));
}
if (bootsig.verify(Arrays.copyOf(image, signableSize))) {
System.err.println("Signature is VALID");
@ -90,7 +96,6 @@ public class SignBoot {
System.err.println("Signature is INVALID");
}
} catch (Exception e) {
e.printStackTrace(System.err);
System.err.println("Invalid image: not signed");
}
return false;

View File

@ -2,44 +2,58 @@ package com.topjohnwu.crypto;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.Security;
public class ZipSigner {
public static void main(String[] args) {
public static void usage() {
System.err.println("Usage: zipsigner [-m] [x509.pem] [pk8] input.jar output.jar");
System.err.println("If no certificate/private key pair is specified, it will use the embedded test keys.");
System.err.println(" -m: enable minimal signing");
System.exit(2);
}
public static void main(String[] args) throws Exception {
boolean minSign = false;
int argStart = 0;
if (args.length < 4) {
System.err.println("Usage: zipsigner [-m] publickey.x509[.pem] privatekey.pk8 input.jar output.jar");
System.exit(2);
}
if (args.length < 2)
usage();
if (args[0].equals("-m")) {
minSign = true;
argStart = 1;
}
InputStream cert = null;
InputStream key = null;
if (args.length - argStart == 4) {
cert = new BufferedInputStream(new FileInputStream(new File(args[argStart])));
key = new BufferedInputStream(new FileInputStream(new File(args[argStart + 1])));
argStart += 2;
}
if (args.length - argStart != 2)
usage();
SignAPK.sBouncyCastleProvider = new BouncyCastleProvider();
Security.insertProviderAt(SignAPK.sBouncyCastleProvider, 1);
File pubKey = new File(args[argStart]);
File privKey = new File(args[argStart + 1]);
File input = new File(args[argStart + 2]);
File output = new File(args[argStart + 3]);
File input = new File(args[argStart]);
File output = new File(args[argStart + 1]);
try (InputStream pub = new FileInputStream(pubKey);
InputStream priv = new FileInputStream(privKey);
JarMap jar = new JarMap(input, false);
try (JarMap jar = new JarMap(input, false);
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(output))) {
SignAPK.signZip(pub, priv, jar, out, minSign);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
SignAPK.signZip(cert, key, jar, out, minSign);
}
}
}