12 |
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # APK Signer
2 | Simple Android app to sign APKs, supports signing split APKs and multiple files.
3 |
4 | # Usage
5 |
6 | There are 3 ways to open the APK to sign:
7 | * Share the file and select Sign APK in the share menu
8 | * Press (open) the file and select Sign APK in available options
9 | * Open the app from launcher and press the button then select the APK file(s).
10 |
11 | Note: Some apps verify the signature of the APK or take other measures to check if the app was modified, which may cause it to crash on startup.
12 |
13 | # Used projects
14 | ⭐ [Android port of apksig library](https://github.com/MuntashirAkon/apksig-android) by [MuntashirAkon](https://github.com/MuntashirAkon) to sign APKs
15 |
16 | * Apache Commons Compress
17 | * PseudoApkSigner by Aefyr for backup signing on older Android versions
18 | * AmbilWarna Color Picker
19 | * android-filepicker by Angad Singh for file picker on older Android versions
20 |
21 | # Todo
22 | * Support v4 signature scheme
23 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.android.application")
3 | }
4 |
5 | android {
6 | namespace = "io.github.abdurazaaqmohammed.ApkSigner"
7 | compileSdk = 35
8 |
9 | defaultConfig {
10 | applicationId = "io.github.abdurazaaqmohammed.ApkSigner"
11 | minSdk = 1
12 | targetSdk = 35
13 | versionCode = 1
14 | versionName = "1.0"
15 | }
16 |
17 | buildTypes {
18 | release {
19 | isMinifyEnabled = true
20 | isShrinkResources = true
21 | proguardFiles(
22 | getDefaultProguardFile("proguard-android-optimize.txt"),
23 | "proguard-rules.pro"
24 | )
25 | }
26 | }
27 | compileOptions {
28 | sourceCompatibility = JavaVersion.VERSION_1_8
29 | targetCompatibility = JavaVersion.VERSION_1_8
30 | }
31 | buildFeatures {
32 | viewBinding = false
33 | }
34 | dependencies {
35 | implementation("org.apache.commons:commons-compress:1.24.0")
36 | }
37 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 | -dontwarn org.xmlpull.v1.**
15 | -dontwarn org.kxml2.io.**
16 | -dontwarn android.content.res.**
17 | -dontwarn org.**
18 | -keep class * {
19 | *;
20 | }
21 | # Uncomment this to preserve the line number information for
22 | # debugging stack traces.
23 | #-keepattributes SourceFile,LineNumberTable
24 |
25 | # If you keep the line number information, uncomment this to
26 | # hide the original source file name.
27 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/app/src/main.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdurazaaqMohammed/APKSigner/2c54aaf57b485b9231b4458482d80ef535b3a8fe/app/src/main.zip
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
9 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/assets/debug23.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdurazaaqMohammed/APKSigner/2c54aaf57b485b9231b4458482d80ef535b3a8fe/app/src/main/assets/debug23.keystore
--------------------------------------------------------------------------------
/app/src/main/assets/testkey.past:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdurazaaqMohammed/APKSigner/2c54aaf57b485b9231b4458482d80ef535b3a8fe/app/src/main/assets/testkey.past
--------------------------------------------------------------------------------
/app/src/main/assets/testkey.pk8:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdurazaaqMohammed/APKSigner/2c54aaf57b485b9231b4458482d80ef535b3a8fe/app/src/main/assets/testkey.pk8
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AbdurazaaqMohammed/APKSigner/2c54aaf57b485b9231b4458482d80ef535b3a8fe/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/src/main/java/com/aefyr/pseudoapksigner/Constants.java:
--------------------------------------------------------------------------------
1 | package com.aefyr.pseudoapksigner;
2 |
3 | public class Constants {
4 | static final String LINE_ENDING = "\r\n";
5 | static final String GENERATOR_NAME = "Android Gradle 8.0.2";
6 | public static final String UTF8 = "UTF-8";
7 | public static final String UTF16 = "UTF-16LE";
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/main/java/com/aefyr/pseudoapksigner/IOUtils.java:
--------------------------------------------------------------------------------
1 | package com.aefyr.pseudoapksigner;
2 |
3 |
4 | import android.content.Context;
5 |
6 | import com.starry.FileUtils;
7 |
8 | import java.io.File;
9 | import java.io.IOException;
10 | import java.io.InputStream;
11 | import java.io.OutputStream;
12 |
13 | public class IOUtils {
14 |
15 | public static void copyFileFromAssets(Context context, String assetFileName, File destination) throws IOException {
16 | try (InputStream inputStream = context.getAssets().open(assetFileName)) {
17 | OutputStream outputStream = FileUtils.getOutputStream(destination);
18 | byte[] buf = new byte[1024 * 1024];
19 | int len;
20 | while ((len = inputStream.read(buf)) > 0) outputStream.write(buf, 0, len);
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/aefyr/pseudoapksigner/ManifestBuilder.java:
--------------------------------------------------------------------------------
1 | package com.aefyr.pseudoapksigner;
2 |
3 | import java.util.ArrayList;
4 | import java.util.LinkedHashMap;
5 | import java.util.List;
6 |
7 | class ManifestBuilder {
8 |
9 | private ArrayList mEntries;
10 |
11 | private long mVersion = 0;
12 | private String mCachedManifest;
13 | private long mCachedVersion = -1;
14 |
15 | ManifestBuilder() {
16 | mEntries = new ArrayList<>();
17 | }
18 |
19 | String build() {
20 | if (mVersion == mCachedVersion)
21 | return mCachedManifest;
22 |
23 | StringBuilder stringBuilder = new StringBuilder();
24 |
25 | stringBuilder.append(generateHeader().toString());
26 | for (ManifestEntry entry : mEntries) {
27 | stringBuilder.append(entry.toString());
28 | }
29 |
30 | mCachedVersion = mVersion;
31 | mCachedManifest = stringBuilder.toString();
32 |
33 | return mCachedManifest;
34 | }
35 |
36 | private ManifestEntry generateHeader() {
37 | ManifestEntry header = new ManifestEntry();
38 | header.setAttribute("Manifest-Version", "1.0");
39 | header.setAttribute("Created-By", Constants.GENERATOR_NAME);
40 | return header;
41 | }
42 |
43 | static class ManifestEntry {
44 | private LinkedHashMap mAttributes;
45 |
46 | ManifestEntry() {
47 | mAttributes = new LinkedHashMap<>();
48 | }
49 |
50 | void setAttribute(String attribute, String value) {
51 | mAttributes.put(attribute, value);
52 | }
53 |
54 | String getAttribute(String attribute) {
55 | return mAttributes.get(attribute);
56 | }
57 |
58 | @Override
59 | public String toString() {
60 | StringBuilder stringBuilder = new StringBuilder();
61 |
62 | for (String key : mAttributes.keySet())
63 | stringBuilder.append(String.format("%s: %s" + Constants.LINE_ENDING, key, mAttributes.get(key)));
64 |
65 | stringBuilder.append(Constants.LINE_ENDING);
66 |
67 | return stringBuilder.toString();
68 | }
69 | }
70 |
71 | void addEntry(ManifestEntry entry) {
72 | mEntries.add(entry);
73 | mVersion++;
74 | }
75 |
76 | List getEntries() {
77 | return mEntries;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/app/src/main/java/com/aefyr/pseudoapksigner/SignatureFileGenerator.java:
--------------------------------------------------------------------------------
1 | package com.aefyr.pseudoapksigner;
2 |
3 | class SignatureFileGenerator {
4 |
5 | private ManifestBuilder mManifest;
6 | private String mHashingAlgorithm;
7 |
8 | SignatureFileGenerator(ManifestBuilder manifestBuilder, String hashingAlgorithm) {
9 | mManifest = manifestBuilder;
10 | mHashingAlgorithm = hashingAlgorithm;
11 | }
12 |
13 | String generate() throws Exception {
14 | StringBuilder stringBuilder = new StringBuilder();
15 | stringBuilder.append(generateHeader().toString());
16 |
17 | for (ManifestBuilder.ManifestEntry manifestEntry : mManifest.getEntries()) {
18 | ManifestBuilder.ManifestEntry sfEntry = new ManifestBuilder.ManifestEntry();
19 | sfEntry.setAttribute("Name", manifestEntry.getAttribute("Name"));
20 | sfEntry.setAttribute(mHashingAlgorithm + "-Digest", Utils.base64Encode(Utils.hash(manifestEntry.toString().getBytes(Constants.UTF8), mHashingAlgorithm)));
21 | stringBuilder.append(sfEntry.toString());
22 | }
23 |
24 | return stringBuilder.toString();
25 | }
26 |
27 | private ManifestBuilder.ManifestEntry generateHeader() throws Exception {
28 | ManifestBuilder.ManifestEntry header = new ManifestBuilder.ManifestEntry();
29 | header.setAttribute("Signature-Version", "1.0");
30 | header.setAttribute("Created-By", Constants.GENERATOR_NAME);
31 | header.setAttribute(mHashingAlgorithm + "-Digest-Manifest", Utils.base64Encode(Utils.hash(mManifest.build().getBytes(Constants.UTF8), mHashingAlgorithm)));
32 | return header;
33 | }
34 |
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/app/src/main/java/com/aefyr/pseudoapksigner/Utils.java:
--------------------------------------------------------------------------------
1 | package com.aefyr.pseudoapksigner;
2 |
3 | import com.starry.FileUtils;
4 |
5 | import java.io.File;
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.io.OutputStream;
9 | import java.security.KeyFactory;
10 | import java.security.MessageDigest;
11 | import java.security.PrivateKey;
12 | import java.security.Signature;
13 | import java.security.interfaces.RSAPrivateKey;
14 | import java.security.spec.PKCS8EncodedKeySpec;
15 |
16 | public class Utils {
17 |
18 | static byte[] hash(byte[] bytes, String hashingAlgorithm) throws Exception {
19 | MessageDigest messageDigest = MessageDigest.getInstance(hashingAlgorithm);
20 | messageDigest.update(bytes);
21 | return messageDigest.digest();
22 | }
23 |
24 | static String base64Encode(byte[] bytes) {
25 | return Base64.encodeToString(bytes, 0);
26 | }
27 |
28 | static void copyStream(InputStream from, OutputStream to) throws IOException {
29 | byte[] buf = new byte[1024 * 1024];
30 | int len;
31 | while ((len = from.read(buf)) > 0) {
32 | to.write(buf, 0, len);
33 | }
34 | }
35 |
36 | static byte[] sign(String hashingAlgorithm, PrivateKey privateKey, byte[] message) throws Exception {
37 | Signature sign = Signature.getInstance(hashingAlgorithm + "withRSA");
38 | sign.initSign(privateKey);
39 | sign.update(message);
40 | return sign.sign();
41 | }
42 |
43 | static RSAPrivateKey readPrivateKey(File file) throws Exception {
44 | PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(readFile(file));
45 | return (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(keySpec);
46 | }
47 |
48 | static byte[] readFile(File file) throws IOException {
49 | byte[] fileBytes = new byte[(int) file.length()];
50 |
51 | try(InputStream inputStream = FileUtils.getInputStream(file)){
52 | inputStream.read(fileBytes);
53 | }
54 | return fileBytes;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/java/com/aefyr/pseudoapksigner/ZipAlignZipOutputStream.java:
--------------------------------------------------------------------------------
1 | package com.aefyr.pseudoapksigner;
2 |
3 | import java.io.IOException;
4 | import java.io.OutputStream;
5 | import java.util.zip.ZipEntry;
6 | import java.util.zip.ZipOutputStream;
7 |
8 | public class ZipAlignZipOutputStream extends ZipOutputStream {
9 |
10 | private BytesCounterOutputStream mBytesCounter;
11 | private int mAlignment;
12 |
13 | public static ZipAlignZipOutputStream create(OutputStream outputStream, int alignment) {
14 | BytesCounterOutputStream bytesCounterOutputStream = new BytesCounterOutputStream(outputStream);
15 | ZipAlignZipOutputStream zipAlignZipOutputStream = new ZipAlignZipOutputStream(bytesCounterOutputStream, alignment);
16 | zipAlignZipOutputStream.mBytesCounter = bytesCounterOutputStream;
17 | return zipAlignZipOutputStream;
18 | }
19 |
20 | private ZipAlignZipOutputStream(BytesCounterOutputStream outputStream, int alignment) {
21 | super(outputStream);
22 | mAlignment = alignment;
23 | }
24 |
25 | public void setAlignment(int alignment) {
26 | mAlignment = alignment;
27 | }
28 |
29 | public int getAlignment() {
30 | return mAlignment;
31 | }
32 |
33 | @Override
34 | public void putNextEntry(ZipEntry zipEntry) throws IOException {
35 | if (zipEntry.getMethod() == ZipEntry.STORED) {
36 | int headerSize = 30;
37 | headerSize += zipEntry.getName().getBytes().length;
38 |
39 | int requiredPadding = (int) (mAlignment - ((mBytesCounter.getBytesWritten() + headerSize) % mAlignment));
40 | zipEntry.setExtra(new byte[requiredPadding]);
41 | }
42 |
43 | super.putNextEntry(zipEntry);
44 | }
45 |
46 | private static class BytesCounterOutputStream extends OutputStream {
47 |
48 | private OutputStream mWrappedOutputStream;
49 | private long mBytesWritten = 0;
50 |
51 | private BytesCounterOutputStream(OutputStream outputStream) {
52 | mWrappedOutputStream = outputStream;
53 | }
54 |
55 | @Override
56 | public void write(byte[] b) throws IOException {
57 | mWrappedOutputStream.write(b);
58 | mBytesWritten += b.length;
59 | }
60 |
61 | @Override
62 | public void write(int b) throws IOException {
63 | mWrappedOutputStream.write(b);
64 | mBytesWritten++;
65 | }
66 |
67 | @Override
68 | public void write(byte[] b, int off, int len) throws IOException {
69 | mWrappedOutputStream.write(b, off, len);
70 | mBytesWritten += len;
71 | }
72 |
73 | private long getBytesWritten() {
74 | return mBytesWritten;
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/Constants.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig;
18 |
19 | import com.android.apksig.internal.apk.stamp.SourceStampConstants;
20 | import com.android.apksig.internal.apk.v1.V1SchemeConstants;
21 | import com.android.apksig.internal.apk.v2.V2SchemeConstants;
22 | import com.android.apksig.internal.apk.v3.V3SchemeConstants;
23 |
24 | /**
25 | * Exports internally defined constants to allow clients to reference these values without relying
26 | * on internal code.
27 | */
28 | public class Constants {
29 | private Constants() {}
30 |
31 | public static final int VERSION_SOURCE_STAMP = 0;
32 | public static final int VERSION_JAR_SIGNATURE_SCHEME = 1;
33 | public static final int VERSION_APK_SIGNATURE_SCHEME_V2 = 2;
34 | public static final int VERSION_APK_SIGNATURE_SCHEME_V3 = 3;
35 | public static final int VERSION_APK_SIGNATURE_SCHEME_V31 = 31;
36 | public static final int VERSION_APK_SIGNATURE_SCHEME_V4 = 4;
37 |
38 | public static final String MANIFEST_ENTRY_NAME = V1SchemeConstants.MANIFEST_ENTRY_NAME;
39 |
40 | public static final int APK_SIGNATURE_SCHEME_V2_BLOCK_ID =
41 | V2SchemeConstants.APK_SIGNATURE_SCHEME_V2_BLOCK_ID;
42 |
43 | public static final int APK_SIGNATURE_SCHEME_V3_BLOCK_ID =
44 | V3SchemeConstants.APK_SIGNATURE_SCHEME_V3_BLOCK_ID;
45 | public static final int APK_SIGNATURE_SCHEME_V31_BLOCK_ID =
46 | V3SchemeConstants.APK_SIGNATURE_SCHEME_V31_BLOCK_ID;
47 | public static final int PROOF_OF_ROTATION_ATTR_ID = V3SchemeConstants.PROOF_OF_ROTATION_ATTR_ID;
48 |
49 | public static final int V1_SOURCE_STAMP_BLOCK_ID =
50 | SourceStampConstants.V1_SOURCE_STAMP_BLOCK_ID;
51 | public static final int V2_SOURCE_STAMP_BLOCK_ID =
52 | SourceStampConstants.V2_SOURCE_STAMP_BLOCK_ID;
53 |
54 | public static final String OID_RSA_ENCRYPTION = "1.2.840.113549.1.1.1";
55 | }
56 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/apk/ApkFormatException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.apk;
18 |
19 | /**
20 | * Indicates that an APK is not well-formed. For example, this may indicate that the APK is not a
21 | * well-formed ZIP archive, in which case {@link #getCause()} will return a
22 | * {@link com.android.apksig.zip.ZipFormatException ZipFormatException}, or that the APK contains
23 | * multiple ZIP entries with the same name.
24 | */
25 | public class ApkFormatException extends Exception {
26 | private static final long serialVersionUID = 1L;
27 |
28 | public ApkFormatException(String message) {
29 | super(message);
30 | }
31 |
32 | public ApkFormatException(String message, Throwable cause) {
33 | super(message, cause);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/apk/ApkSigningBlockNotFoundException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.apk;
18 |
19 | /**
20 | * Indicates that no APK Signing Block was found in an APK.
21 | */
22 | public class ApkSigningBlockNotFoundException extends Exception {
23 | private static final long serialVersionUID = 1L;
24 |
25 | public ApkSigningBlockNotFoundException(String message) {
26 | super(message);
27 | }
28 |
29 | public ApkSigningBlockNotFoundException(String message, Throwable cause) {
30 | super(message, cause);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/apk/CodenameMinSdkVersionException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.apk;
18 |
19 | /**
20 | * Indicates that there was an issue determining the minimum Android platform version supported by
21 | * an APK because the version is specified as a codename, rather than as API Level number, and the
22 | * codename is in an unexpected format.
23 | */
24 | public class CodenameMinSdkVersionException extends MinSdkVersionException {
25 |
26 | private static final long serialVersionUID = 1L;
27 |
28 | /** Encountered codename. */
29 | private final String mCodename;
30 |
31 | /**
32 | * Constructs a new {@code MinSdkVersionCodenameException} with the provided message and
33 | * codename.
34 | */
35 | public CodenameMinSdkVersionException(String message, String codename) {
36 | super(message);
37 | mCodename = codename;
38 | }
39 |
40 | /**
41 | * Returns the codename.
42 | */
43 | public String getCodename() {
44 | return mCodename;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/apk/MinSdkVersionException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.apk;
18 |
19 | /**
20 | * Indicates that there was an issue determining the minimum Android platform version supported by
21 | * an APK.
22 | */
23 | public class MinSdkVersionException extends ApkFormatException {
24 |
25 | private static final long serialVersionUID = 1L;
26 |
27 | /**
28 | * Constructs a new {@code MinSdkVersionException} with the provided message.
29 | */
30 | public MinSdkVersionException(String message) {
31 | super(message);
32 | }
33 |
34 | /**
35 | * Constructs a new {@code MinSdkVersionException} with the provided message and cause.
36 | */
37 | public MinSdkVersionException(String message, Throwable cause) {
38 | super(message, cause);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/apk/ApkSignerInfo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.internal.apk;
18 |
19 | import com.android.apksig.ApkVerificationIssue;
20 |
21 | import java.security.cert.X509Certificate;
22 | import java.util.ArrayList;
23 | import java.util.List;
24 |
25 | /**
26 | * Base implementation of an APK signer.
27 | */
28 | public class ApkSignerInfo {
29 | public int index;
30 | public long timestamp;
31 | public List certs = new ArrayList<>();
32 | public List certificateLineage = new ArrayList<>();
33 |
34 | private final List mWarnings = new ArrayList<>();
35 | private final List mErrors = new ArrayList<>();
36 |
37 | /**
38 | * Adds a new {@link ApkVerificationIssue} as an error to this signer using the provided {@code
39 | * issueId} and {@code params}.
40 | */
41 | public void addError(int issueId, Object... params) {
42 | mErrors.add(new ApkVerificationIssue(issueId, params));
43 | }
44 |
45 | /**
46 | * Adds a new {@link ApkVerificationIssue} as a warning to this signer using the provided {@code
47 | * issueId} and {@code params}.
48 | */
49 | public void addWarning(int issueId, Object... params) {
50 | mWarnings.add(new ApkVerificationIssue(issueId, params));
51 | }
52 |
53 | /**
54 | * Returns {@code true} if any errors were encountered during verification for this signer.
55 | */
56 | public boolean containsErrors() {
57 | return !mErrors.isEmpty();
58 | }
59 |
60 | /**
61 | * Returns {@code true} if any warnings were encountered during verification for this signer.
62 | */
63 | public boolean containsWarnings() {
64 | return !mWarnings.isEmpty();
65 | }
66 |
67 | /**
68 | * Returns the errors encountered during verification for this signer.
69 | */
70 | public List extends ApkVerificationIssue> getErrors() {
71 | return mErrors;
72 | }
73 |
74 | /**
75 | * Returns the warnings encountered during verification for this signer.
76 | */
77 | public List extends ApkVerificationIssue> getWarnings() {
78 | return mWarnings;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/apk/ApkSupportedSignature.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.internal.apk;
18 |
19 | /**
20 | * Base implementation of a supported signature for an APK.
21 | */
22 | public class ApkSupportedSignature {
23 | public final SignatureAlgorithm algorithm;
24 | public final byte[] signature;
25 |
26 | /**
27 | * Constructs a new supported signature using the provided {@code algorithm} and {@code
28 | * signature} bytes.
29 | */
30 | public ApkSupportedSignature(SignatureAlgorithm algorithm, byte[] signature) {
31 | this.algorithm = algorithm;
32 | this.signature = signature;
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/apk/ContentDigestAlgorithm.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.internal.apk;
18 |
19 | /** APK Signature Scheme v2 content digest algorithm. */
20 | public enum ContentDigestAlgorithm {
21 | /** SHA2-256 over 1 MB chunks. */
22 | CHUNKED_SHA256(1, "SHA-256", 256 / 8),
23 |
24 | /** SHA2-512 over 1 MB chunks. */
25 | CHUNKED_SHA512(2, "SHA-512", 512 / 8),
26 |
27 | /** SHA2-256 over 4 KB chunks for APK verity. */
28 | VERITY_CHUNKED_SHA256(3, "SHA-256", 256 / 8),
29 |
30 | /** Non-chunk SHA2-256. */
31 | SHA256(4, "SHA-256", 256 / 8);
32 |
33 | private final int mId;
34 | private final String mJcaMessageDigestAlgorithm;
35 | private final int mChunkDigestOutputSizeBytes;
36 |
37 | private ContentDigestAlgorithm(
38 | int id, String jcaMessageDigestAlgorithm, int chunkDigestOutputSizeBytes) {
39 | mId = id;
40 | mJcaMessageDigestAlgorithm = jcaMessageDigestAlgorithm;
41 | mChunkDigestOutputSizeBytes = chunkDigestOutputSizeBytes;
42 | }
43 |
44 | /** Returns the ID of the digest algorithm used on the APK. */
45 | public int getId() {
46 | return mId;
47 | }
48 |
49 | /**
50 | * Returns the {@link java.security.MessageDigest} algorithm used for computing digests of
51 | * chunks by this content digest algorithm.
52 | */
53 | String getJcaMessageDigestAlgorithm() {
54 | return mJcaMessageDigestAlgorithm;
55 | }
56 |
57 | /** Returns the size (in bytes) of the digest of a chunk of content. */
58 | int getChunkDigestOutputSizeBytes() {
59 | return mChunkDigestOutputSizeBytes;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/apk/NoApkSupportedSignaturesException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.internal.apk;
18 |
19 | /**
20 | * Base exception that is thrown when there are no signatures that support the full range of
21 | * requested platform versions.
22 | */
23 | public class NoApkSupportedSignaturesException extends Exception {
24 | public NoApkSupportedSignaturesException(String message) {
25 | super(message);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/apk/SignatureInfo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.internal.apk;
18 |
19 | import java.nio.ByteBuffer;
20 |
21 | /**
22 | * APK Signature Scheme block and additional information relevant to verifying the signatures
23 | * contained in the block against the file.
24 | */
25 | public class SignatureInfo {
26 | /** Contents of APK Signature Scheme block. */
27 | public final ByteBuffer signatureBlock;
28 |
29 | /** Position of the APK Signing Block in the file. */
30 | public final long apkSigningBlockOffset;
31 |
32 | /** Position of the ZIP Central Directory in the file. */
33 | public final long centralDirOffset;
34 |
35 | /** Position of the ZIP End of Central Directory (EoCD) in the file. */
36 | public final long eocdOffset;
37 |
38 | /** Contents of ZIP End of Central Directory (EoCD) of the file. */
39 | public final ByteBuffer eocd;
40 |
41 | public SignatureInfo(
42 | ByteBuffer signatureBlock,
43 | long apkSigningBlockOffset,
44 | long centralDirOffset,
45 | long eocdOffset,
46 | ByteBuffer eocd) {
47 | this.signatureBlock = signatureBlock;
48 | this.apkSigningBlockOffset = apkSigningBlockOffset;
49 | this.centralDirOffset = centralDirOffset;
50 | this.eocdOffset = eocdOffset;
51 | this.eocd = eocd;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/apk/SignatureNotFoundException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.internal.apk;
18 |
19 | /**
20 | * Base exception that is thrown when the APK is not signed with the requested signature scheme.
21 | */
22 | public class SignatureNotFoundException extends Exception {
23 | public SignatureNotFoundException(String message) {
24 | super(message);
25 | }
26 |
27 | public SignatureNotFoundException(String message, Throwable cause) {
28 | super(message, cause);
29 | }
30 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/apk/stamp/SourceStampConstants.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.internal.apk.stamp;
18 |
19 | /** Constants used for source stamp signing and verification. */
20 | public class SourceStampConstants {
21 | private SourceStampConstants() {}
22 |
23 | public static final int V1_SOURCE_STAMP_BLOCK_ID = 0x2b09189e;
24 | public static final int V2_SOURCE_STAMP_BLOCK_ID = 0x6dff800d;
25 | public static final String SOURCE_STAMP_CERTIFICATE_HASH_ZIP_ENTRY_NAME = "stamp-cert-sha256";
26 | public static final int PROOF_OF_ROTATION_ATTR_ID = 0x9d6303f7;
27 | /**
28 | * The source stamp timestamp attribute value is an 8-byte little-endian encoded long
29 | * representing the epoch time in seconds when the stamp block was signed. The first 8 bytes
30 | * of the attribute value buffer will be used to read the timestamp, and any additional buffer
31 | * space will be ignored.
32 | */
33 | public static final int STAMP_TIME_ATTR_ID = 0xe43c5946;
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/apk/v1/DigestAlgorithm.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.internal.apk.v1;
18 |
19 | import java.util.Comparator;
20 |
21 | /**
22 | * Digest algorithm used with JAR signing (aka v1 signing scheme).
23 | */
24 | public enum DigestAlgorithm {
25 | /** SHA-1 */
26 | SHA1("SHA-1"),
27 |
28 | /** SHA2-256 */
29 | SHA256("SHA-256");
30 |
31 | private final String mJcaMessageDigestAlgorithm;
32 |
33 | private DigestAlgorithm(String jcaMessageDigestAlgoritm) {
34 | mJcaMessageDigestAlgorithm = jcaMessageDigestAlgoritm;
35 | }
36 |
37 | /**
38 | * Returns the {@link java.security.MessageDigest} algorithm represented by this digest
39 | * algorithm.
40 | */
41 | String getJcaMessageDigestAlgorithm() {
42 | return mJcaMessageDigestAlgorithm;
43 | }
44 |
45 | public static Comparator BY_STRENGTH_COMPARATOR = new StrengthComparator();
46 |
47 | private static class StrengthComparator implements Comparator {
48 | @Override
49 | public int compare(DigestAlgorithm a1, DigestAlgorithm a2) {
50 | switch (a1) {
51 | case SHA1:
52 | switch (a2) {
53 | case SHA1:
54 | return 0;
55 | case SHA256:
56 | return -1;
57 | }
58 | throw new RuntimeException("Unsupported algorithm: " + a2);
59 |
60 | case SHA256:
61 | switch (a2) {
62 | case SHA1:
63 | return 1;
64 | case SHA256:
65 | return 0;
66 | }
67 | throw new RuntimeException("Unsupported algorithm: " + a2);
68 |
69 | default:
70 | throw new RuntimeException("Unsupported algorithm: " + a1);
71 | }
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/apk/v1/V1SchemeConstants.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.internal.apk.v1;
18 |
19 | /** Constants used by the Jar Signing / V1 Signature Scheme signing and verification. */
20 | public class V1SchemeConstants {
21 | private V1SchemeConstants() {}
22 |
23 | public static final String MANIFEST_ENTRY_NAME = "META-INF/MANIFEST.MF";
24 | public static final String SF_ATTRIBUTE_NAME_ANDROID_APK_SIGNED_NAME_STR =
25 | "X-Android-APK-Signed";
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/apk/v2/V2SchemeConstants.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.internal.apk.v2;
18 |
19 | /** Constants used by the V2 Signature Scheme signing and verification. */
20 | public class V2SchemeConstants {
21 | private V2SchemeConstants() {}
22 |
23 | public static final int APK_SIGNATURE_SCHEME_V2_BLOCK_ID = 0x7109871a;
24 | public static final int STRIPPING_PROTECTION_ATTR_ID = 0xbeeff00d;
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/apk/v3/V3SchemeConstants.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.internal.apk.v3;
18 |
19 | import com.android.apksig.internal.util.AndroidSdkVersion;
20 |
21 | /** Constants used by the V3 Signature Scheme signing and verification. */
22 | public class V3SchemeConstants {
23 | private V3SchemeConstants() {}
24 |
25 | public static final int APK_SIGNATURE_SCHEME_V3_BLOCK_ID = 0xf05368c0;
26 | public static final int APK_SIGNATURE_SCHEME_V31_BLOCK_ID = 0x1b93ad61;
27 | public static final int PROOF_OF_ROTATION_ATTR_ID = 0x3ba06f8c;
28 |
29 | public static final int MIN_SDK_WITH_V3_SUPPORT = AndroidSdkVersion.P;
30 | public static final int MIN_SDK_WITH_V31_SUPPORT = AndroidSdkVersion.T;
31 | /**
32 | * By default, APK signing key rotation will target T, but packages that have previously
33 | * rotated can continue rotating on pre-T by specifying an SDK version <= 32 as the
34 | * --rotation-min-sdk-version parameter when using apksigner or when invoking
35 | * {@link com.android.apksig.ApkSigner.Builder#setMinSdkVersionForRotation(int)}.
36 | */
37 | public static final int DEFAULT_ROTATION_MIN_SDK_VERSION = AndroidSdkVersion.T;
38 |
39 | /**
40 | * This attribute is intended to be written to the V3.0 signer block as an additional attribute
41 | * whose value is the minimum SDK version supported for rotation by the V3.1 signing block. If
42 | * this value is set to X and a v3.1 signing block does not exist, or the minimum SDK version
43 | * for rotation in the v3.1 signing block is not X, then the APK should be rejected.
44 | */
45 | public static final int ROTATION_MIN_SDK_VERSION_ATTR_ID = 0x559f8b02;
46 |
47 | /**
48 | * This attribute is written to the V3.1 signer block as an additional attribute to signify that
49 | * the rotation-min-sdk-version is targeting a development release. This is required to support
50 | * testing rotation on new development releases as the previous platform release SDK version
51 | * is used as the development release SDK version until the development release SDK is
52 | * finalized.
53 | */
54 | public static final int ROTATION_ON_DEV_RELEASE_ATTR_ID = 0xc2a6b3ba;
55 | }
56 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/asn1/Asn1Class.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.internal.asn1;
18 |
19 | import java.lang.annotation.ElementType;
20 | import java.lang.annotation.Retention;
21 | import java.lang.annotation.RetentionPolicy;
22 | import java.lang.annotation.Target;
23 |
24 | @Target({ElementType.TYPE})
25 | @Retention(RetentionPolicy.RUNTIME)
26 | public @interface Asn1Class {
27 | public Asn1Type type();
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/asn1/Asn1DecodingException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.internal.asn1;
18 |
19 | /**
20 | * Indicates that input could not be decoded into intended ASN.1 structure.
21 | */
22 | public class Asn1DecodingException extends Exception {
23 | private static final long serialVersionUID = 1L;
24 |
25 | public Asn1DecodingException(String message) {
26 | super(message);
27 | }
28 |
29 | public Asn1DecodingException(String message, Throwable cause) {
30 | super(message, cause);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/asn1/Asn1EncodingException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.internal.asn1;
18 |
19 | /**
20 | * Indicates that an ASN.1 structure could not be encoded.
21 | */
22 | public class Asn1EncodingException extends Exception {
23 | private static final long serialVersionUID = 1L;
24 |
25 | public Asn1EncodingException(String message) {
26 | super(message);
27 | }
28 |
29 | public Asn1EncodingException(String message, Throwable cause) {
30 | super(message, cause);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/asn1/Asn1Field.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.internal.asn1;
18 |
19 | import java.lang.annotation.ElementType;
20 | import java.lang.annotation.Retention;
21 | import java.lang.annotation.RetentionPolicy;
22 | import java.lang.annotation.Target;
23 |
24 | @Target({ElementType.FIELD})
25 | @Retention(RetentionPolicy.RUNTIME)
26 | public @interface Asn1Field {
27 | /** Index used to order fields in a container. Required for fields of SEQUENCE containers. */
28 | public int index() default 0;
29 |
30 | public Asn1TagClass cls() default Asn1TagClass.AUTOMATIC;
31 |
32 | public Asn1Type type();
33 |
34 | /** Tagging mode. Default: NORMAL. */
35 | public Asn1Tagging tagging() default Asn1Tagging.NORMAL;
36 |
37 | /** Tag number. Required when IMPLICIT and EXPLICIT tagging mode is used.*/
38 | public int tagNumber() default -1;
39 |
40 | /** {@code true} if this field is optional. Ignored for fields of CHOICE containers. */
41 | public boolean optional() default false;
42 |
43 | /** Type of elements. Used only for SET_OF or SEQUENCE_OF. */
44 | public Asn1Type elementType() default Asn1Type.ANY;
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/asn1/Asn1OpaqueObject.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.internal.asn1;
18 |
19 | import java.nio.ByteBuffer;
20 |
21 | /**
22 | * Opaque holder of encoded ASN.1 stuff.
23 | */
24 | public class Asn1OpaqueObject {
25 | private final ByteBuffer mEncoded;
26 |
27 | public Asn1OpaqueObject(ByteBuffer encoded) {
28 | mEncoded = encoded.slice();
29 | }
30 |
31 | public Asn1OpaqueObject(byte[] encoded) {
32 | mEncoded = ByteBuffer.wrap(encoded);
33 | }
34 |
35 | public ByteBuffer getEncoded() {
36 | return mEncoded.slice();
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/asn1/Asn1TagClass.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.internal.asn1;
18 |
19 | public enum Asn1TagClass {
20 | UNIVERSAL,
21 | APPLICATION,
22 | CONTEXT_SPECIFIC,
23 | PRIVATE,
24 |
25 | /**
26 | * Not really an actual tag class: decoder/encoder will attempt to deduce the correct tag class
27 | * automatically.
28 | */
29 | AUTOMATIC,
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/asn1/Asn1Tagging.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.internal.asn1;
18 |
19 | public enum Asn1Tagging {
20 | NORMAL,
21 | EXPLICIT,
22 | IMPLICIT,
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/asn1/Asn1Type.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.internal.asn1;
18 |
19 | public enum Asn1Type {
20 | ANY,
21 | CHOICE,
22 | INTEGER,
23 | OBJECT_IDENTIFIER,
24 | OCTET_STRING,
25 | SEQUENCE,
26 | SEQUENCE_OF,
27 | SET_OF,
28 | BIT_STRING,
29 | UTC_TIME,
30 | GENERALIZED_TIME,
31 | BOOLEAN,
32 | // This type can be used to annotate classes that encapsulate ASN.1 structures that are not
33 | // classified as a SEQUENCE or SET.
34 | UNENCODED_CONTAINER
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/asn1/ber/BerDataValueFormatException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.internal.asn1.ber;
18 |
19 | /**
20 | * Indicates that an ASN.1 data value being read could not be decoded using
21 | * Basic Encoding Rules (BER).
22 | */
23 | public class BerDataValueFormatException extends Exception {
24 |
25 | private static final long serialVersionUID = 1L;
26 |
27 | public BerDataValueFormatException(String message) {
28 | super(message);
29 | }
30 |
31 | public BerDataValueFormatException(String message, Throwable cause) {
32 | super(message, cause);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/asn1/ber/BerDataValueReader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.apksig.internal.asn1.ber;
18 |
19 | /**
20 | * Reader of ASN.1 Basic Encoding Rules (BER) data values.
21 | *
22 | *
This is a functional interface
12 | * whose functional method is {@link #accept(int)}.
13 | *
14 | * @see Consumer
15 | */
16 | @FunctionalInterface
17 | public interface IntConsumerCompat {
18 |
19 | /**
20 | * Performs this operation on the given argument.
21 | *
22 | * @param value the input argument
23 | */
24 | void accept(int value);
25 |
26 | /**
27 | * Returns a composed {@code IntConsumerCompat} that performs, in sequence, this
28 | * operation followed by the {@code after} operation. If performing either
29 | * operation throws an exception, it is relayed to the caller of the
30 | * composed operation. If performing this operation throws an exception,
31 | * the {@code after} operation will not be performed.
32 | *
33 | * @param after the operation to perform after this operation
34 | * @return a composed {@code IntConsumerCompat} that performs in sequence this
35 | * operation followed by the {@code after} operation
36 | * @throws NullPointerException if {@code after} is null
37 | */
38 | default IntConsumerCompat andThen(IntConsumerCompat after) {
39 | Objects.requireNonNull(after);
40 | return (int t) -> { accept(t); after.accept(t); };
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/compat/IntSupplierCompat.java:
--------------------------------------------------------------------------------
1 | package com.android.apksig.internal.compat;
2 |
3 | /**
4 | * Represents a supplier of {@code int}-valued results. This is the
5 | * {@code int}-producing primitive specialization of {@link SupplierCompat}.
6 | *
7 | *
There is no requirement that a distinct result be returned each
8 | * time the supplier is invoked.
9 | *
10 | * @see SupplierCompat
11 | */
12 | @FunctionalInterface
13 | public interface IntSupplierCompat {
14 |
15 | /**
16 | * Gets a result.
17 | *
18 | * @return a result
19 | */
20 | int getAsInt();
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/apksig/internal/compat/SupplierCompat.java:
--------------------------------------------------------------------------------
1 | package com.android.apksig.internal.compat;
2 |
3 | /**
4 | * Represents a supplier of results.
5 | *
6 | *