Skip to content

Commit

Permalink
Merge pull request #28 from buffcow/main
Browse files Browse the repository at this point in the history
feat(sign): use signflinger to sign archive instead of apksigner
  • Loading branch information
shapun963 authored Oct 27, 2023
2 parents bcfa9d4 + cab490f commit cc33425
Show file tree
Hide file tree
Showing 35 changed files with 589 additions and 404 deletions.
50 changes: 26 additions & 24 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
@file:Suppress("UnstableApiUsage")

plugins {
kotlin("android")
id("com.android.application")
alias(libs.plugins.kotlin)
alias(libs.plugins.agp.app)
}

android {
compileSdk = 33
compileSdk = 34
namespace = "com.shapun.apkaabconverter"

defaultConfig {
minSdk = 26
targetSdk = 33
versionCode = 5
versionName = "1.5"
applicationId = android.namespace
targetSdk = 34
versionCode = 6
versionName = "1.6"
applicationId = namespace
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

Expand All @@ -30,11 +30,11 @@ android {
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "1.8"
jvmTarget = "17"
}
buildFeatures {
viewBinding = true
Expand All @@ -43,18 +43,20 @@ android {
}

dependencies {
implementation("androidx.core:core-ktx:1.10.1")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.9.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1")

implementation("com.google.guava:guava:31.1-jre")
implementation("com.google.protobuf:protobuf-java:3.23.0")
implementation("com.android.tools.build:apksig:8.0.1")
implementation("com.android.tools.build:bundletool:1.15.0")
implementation("org.bouncycastle:bcprov-jdk15on:1.70")

testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.androidx.lifecycle.common)

implementation(libs.google.guava)
implementation(libs.google.material)
implementation(libs.google.protobuf.java)

implementation(libs.bcprov.jdk15on)
implementation(libs.android.tools.zipflinger)
implementation(libs.android.tools.signflinger)
implementation(libs.android.tools.bundletool)

testImplementation(libs.junit)
androidTestImplementation(libs.androidx.test.junit)
androidTestImplementation(libs.androidx.test.espresso.core)
}
Binary file added app/src/main/assets/debug.keystore
Binary file not shown.
Binary file removed app/src/main/assets/testkey.pk8
Binary file not shown.
27 changes: 0 additions & 27 deletions app/src/main/assets/testkey.x509.pem

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@

import android.content.Context;

import com.android.apksig.ApkSigner;
import com.android.tools.build.bundletool.androidtools.Aapt2Command;
import com.android.tools.build.bundletool.commands.BuildApksCommand;
import com.android.tools.build.bundletool.model.SigningConfiguration;
import com.google.common.collect.ImmutableList;
import com.shapun.apkaabconverter.signing.model.CertificateInfo;

import java.io.ByteArrayOutputStream;
import java.io.File;
Expand All @@ -16,12 +15,12 @@
public class AABToApkConverter extends FileConverter {

private final File AAPT2Binary;
private final ApkSigner.SignerConfig signerConfig;
private final CertificateInfo signingCertInfo;

public AABToApkConverter(Builder builder) {
super(builder);
AAPT2Binary = new File(getContext().getApplicationInfo().nativeLibraryDir, "libaapt2.so");
signerConfig = builder.signerConfig;
signingCertInfo = builder.signingCertInfo;
}

public void start() {
Expand All @@ -35,25 +34,24 @@ public void start() {
.setOverwriteOutput(true)
.setApkBuildMode(BuildApksCommand.ApkBuildMode.UNIVERSAL)
.setOutputPrintStream(new PrintStream(outputStream));
if (signerConfig != null)
if (signingCertInfo != null)
builder.setSigningConfiguration(SigningConfiguration.builder()
.setSignerConfig(signerConfig.getPrivateKey(),
ImmutableList.copyOf(signerConfig.getCertificates()))
.setSignerConfig(signingCertInfo.getKey(),signingCertInfo.getCertificate())
.build());
builder.build().execute();
addLog(outputStream.toString());
addLog("Successfully converted AAB to Apk");
}

public static class Builder extends FileConverter.Builder<Builder> {
private ApkSigner.SignerConfig signerConfig;
private CertificateInfo signingCertInfo;

public Builder(Context context, Path aabPath, Path outputPath) {
super(context, aabPath, outputPath);
}

public Builder setSignerConfig(ApkSigner.SignerConfig signerConfig) {
this.signerConfig = signerConfig;
public Builder setSigningCertInfo(CertificateInfo signingCertInfo) {
this.signingCertInfo = signingCertInfo;
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

import android.content.Context;

import com.android.apksig.ApkSigner;
import com.android.apksig.apk.ApkFormatException;
import com.android.bundle.Config;
import com.android.tools.build.bundletool.commands.BuildBundleCommand;
import com.google.common.collect.ImmutableList;
import com.shapun.apkaabconverter.model.MetaData;
import com.shapun.apkaabconverter.zipalign.ZipAligner;
import com.shapun.apkaabconverter.signing.helper.SignHelper;
import com.shapun.apkaabconverter.signing.model.CertificateInfo;

import java.io.File;
import java.io.FileInputStream;
Expand All @@ -19,9 +18,6 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
Expand All @@ -30,6 +26,8 @@
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import kotlin.io.FilesKt;

public class ApkToAABConverter extends FileConverter {

private static final int BUFFER_SIZE = 1024 * 2;
Expand All @@ -39,9 +37,7 @@ public class ApkToAABConverter extends FileConverter {
private final Path mBundleConfigPath;
private final Config.BundleConfig mBundleConfig;
private final Path mNonSignedAAB;
private final Path mSignedAAB;
private final ApkSigner.SignerConfig mSignerConfig;
private final boolean mAlign;
private final CertificateInfo mSigningCertInfo;
private final List<MetaData> mMetaData;

public ApkToAABConverter(Builder builder) {
Expand All @@ -57,12 +53,10 @@ public ApkToAABConverter(Builder builder) {
mProtoOutput = mTempDir.resolve("proto.zip");
mBaseZip = mTempDir.resolve("base.zip");
mNonSignedAAB = mTempDir.resolve("non-signed.aab");
mSignedAAB = mTempDir.resolve("signed.aab");
mSignerConfig = builder.signerConfig;
mSigningCertInfo = builder.signingCertInfo;
mBundleConfigPath = builder.bundleConfigPath;
mBundleConfig = builder.bundleConfig;
mMetaData = builder.metaData;
mAlign = builder.align;
}

@Override
Expand All @@ -71,7 +65,6 @@ public void start() throws Exception {
createBaseZip();
buildAab();
sign();
if (mAlign) align();
}

private void createProtoFormatZip() throws Exception {
Expand Down Expand Up @@ -165,35 +158,30 @@ private void buildAab() {
addLog("Successfully converted Apk to AAB");
}

public void sign() throws ApkFormatException, IOException, NoSuchAlgorithmException, SignatureException, InvalidKeyException {
if (mSignerConfig != null) {
public void sign() {
if (mSigningCertInfo != null) {
addLog("Signing AAB");
new ApkSigner.Builder(ImmutableList.of(mSignerConfig))
.setInputApk(mNonSignedAAB.toFile())
.setOutputApk(mAlign ? mSignedAAB.toFile() : getOutputPath().toFile())
//ToDo: use ApkUtils.getMinSdkVersion()
.setMinSdkVersion(1)//ApkUtils.getMinimumSdkVersion(getInputPath()))
.build()
.sign();
SignHelper.INSTANCE.signWithFlinger(
mSigningCertInfo,
mNonSignedAAB.toFile(),
getOutputPath().toFile()
);
} else {
addLog("No signer config provided, skipping signing");
FilesKt.copyTo(
mNonSignedAAB.toFile(),
getOutputPath().toFile(),
true,
8 * 1024
);
}
}

public void align() {
addLog("Aligning aab");
ZipAligner aligner = new ZipAligner((mSignerConfig == null ? mNonSignedAAB : mSignedAAB), getOutputPath());
aligner.setVerbose(isVerbose());
aligner.align();
if(isVerbose())addLog(aligner.getLogs());
}

public static class Builder extends FileConverter.Builder<Builder> {
private Path bundleConfigPath;
private Config.BundleConfig bundleConfig;
private final List<MetaData> metaData;
private ApkSigner.SignerConfig signerConfig;
private boolean align = false;
private CertificateInfo signingCertInfo;

public Builder(Context context, Path apkPath, Path outputPath) {
super(context, apkPath, outputPath);
Expand All @@ -206,7 +194,7 @@ public Builder setBundleConfig(Path configPath) {
return this;
}

public Builder setBundleConfig(Config.BundleConfig bundleConfig){
public Builder setBundleConfig(Config.BundleConfig bundleConfig) {
bundleConfigPath = null;
this.bundleConfig = bundleConfig;
return this;
Expand All @@ -217,13 +205,8 @@ public Builder addMetaData(MetaData metaData) {
return this;
}

public Builder align() {
this.align = true;
return this;
}

public Builder setSignerConfig(ApkSigner.SignerConfig signerConfig) {
this.signerConfig = signerConfig;
public Builder setSigningCertInfo(CertificateInfo certInfo) {
this.signingCertInfo = certInfo;
return this;
}

Expand Down
35 changes: 35 additions & 0 deletions app/src/main/java/com/shapun/apkaabconverter/extension/ViewExt.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* view extension
*
* @author qingyu
* <p>
* Create on 2023/10/09 16:08
*/

@file:Suppress("unused")

package com.shapun.apkaabconverter.extension

import android.view.View
import android.widget.EditText
import com.google.android.material.textfield.TextInputLayout

fun View.show() {
visibility = View.VISIBLE
}

fun View.hide() {
visibility = View.GONE
}

fun EditText.clearText() {
text = null
}

fun TextInputLayout.error(msg: String?) {
if (msg.isNullOrBlank()) clearError() else error = msg
}

fun TextInputLayout.clearError() {
isErrorEnabled = false
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class AABToApkDialogFragment : BaseDialogFragment<DialogAabToApkBinding>() {
.setVerbose(binding.cbVerbose.isChecked)
val signOptionsFragment =
childFragmentManager.findFragmentByTag("SignOptionsFragment") as SignOptionsFragment
builder.setSignerConfig(signOptionsFragment.getSigningConfig())
builder.setSigningCertInfo(signOptionsFragment.getSigningCertInfo())
builder.build().start()
Utils.copy(requireContext(), mTempOutputPath, mApkUri!!)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,7 @@ class ApkToAABDialogFragment : BaseDialogFragment<DialogApkToAabBinding>() {
mMetaData.forEach(this::addMetaData)
val signOptionsFragment =
childFragmentManager.findFragmentByTag("SignOptionsFragment") as SignOptionsFragment
setSignerConfig(signOptionsFragment.getSigningConfig())
if (binding.cbAlign.isChecked) align()
setSigningCertInfo(signOptionsFragment.getSigningCertInfo())
build().start()
Utils.copy(requireContext(), mTempOutputPath, mAABUri!!)
}
Expand Down
Loading

0 comments on commit cc33425

Please sign in to comment.