Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# ApkGolf
This repository hosts the smallest Android APK in the world. The current size of the APK is *678 bytes*.
This repository hosts the smallest Android APK in the world. The current size of the APK is *677 bytes*.

To learn more about how this was achieved, please read the [blog post](https://fractalwrench.co.uk/posts/playing-apk-golf-how-low-can-an-android-app-go/).

Expand Down Expand Up @@ -34,8 +34,8 @@ Further byte-level optimisation of what remains of the manifest.

Contributed by [Madis Pink](https://github.com/madisp) in this [Pull Request](https://github.com/fractalwrench/ApkGolf/pull/6)

## Minimising APK Signing Certificate (678 bytes, 18% reduction)
Manual removal of unnecessary fields present in the certificate used to sign the APK.
## Minimising APK Signing Certificate (677 bytes, 18% reduction)
Remove unnecessary fields present in the certificate used to sign the APK.

Contributed by [klyubin](https://github.com/klyubin) in this [Pull Request](https://github.com/fractalwrench/ApkGolf/pull/15)

Automated by [Adam Yi](https://github.com/adamyi)
39 changes: 36 additions & 3 deletions build.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#!/usr/bin/env bash

set -e

rm -rf build
mkdir -p build/apk

Expand All @@ -18,6 +16,41 @@ recompress() {

set -x

echo "Compiling certificate generation program"

success=0

gcc -o build/generate_cert generate_cert.c -lssl -lcrypto -ldl

if [ $? -eq 0 ]; then
echo "Generating cert"
cd build
./generate_cert
if [ $? -eq 0 ]; then
cd ..
openssl x509 -in build/cert.pem -noout -text
if [ $? -eq 0 ]; then
openssl pkcs8 -topk8 -in build/key.pem -out build/key.pk8 -outform DER -nocrypt
if [ $? -eq 0 ]; then
echo "Success"
success=1
fi
fi
else
cd ..
fi
fi

if [ $success -eq 0 ]; then
echo "Failed to generate cert. Using pre-generated cert."
rm build/cert.pem
rm build/key.pk8
cp cert.pem build/
cp key.pk8 build/
fi

set -e

echo "Creating base apk"
cp app/AndroidManifest.xml build/apk/

Expand All @@ -27,7 +60,7 @@ zip -j -r build/app-unsigned.apk build/apk
recompress build/app-unsigned.apk

echo "Signing archive"
$ANDROID_HOME/build-tools/26.0.2/apksigner sign --v1-signing-enabled false --key key.pk8 --cert key.x509.pem --in build/app-unsigned.apk --out build/signed-release.apk --min-sdk-version 24
$ANDROID_HOME/build-tools/26.0.2/apksigner sign --v1-signing-enabled false --key build/key.pk8 --cert build/cert.pem --in build/app-unsigned.apk --out build/signed-release.apk --min-sdk-version 24

set +x

Expand Down
6 changes: 6 additions & 0 deletions cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-----BEGIN CERTIFICATE-----
MIGgMIGVAgEBMAMGAQAwCTEHMAUGAQATADAaFwswMDAxMDEwMDAwWhcLMDAwMTAx
MDAwMFowCTEHMAUGAQATADBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOYMo2Ld
mbwCoefiz7NRQ+du9obnpJNhRK11XPZHhk6jSRdFiOkqMhko2YI/XWlq6BkC3OPS
r3QkiEeT3i+EXj8wAwYBAAMBAA==
-----END CERTIFICATE-----
91 changes: 91 additions & 0 deletions generate_cert.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Generate minimal ECC cert
// Required OpenSSL version < 1.0.1i
// author: Adam Yi <[email protected]>

#include <stdio.h>

#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/asn1.h>

EVP_PKEY * generate_key_ecc()
{
BIO *outbio = NULL;

int eccgrp = OBJ_txt2nid("prime256v1");
EC_KEY *myecc = EC_KEY_new_by_curve_name(eccgrp);

//EC_KEY_set_asn1_flag(myecc, OPENSSL_EC_NAMED_CURVE);
EC_KEY_set_asn1_flag(myecc, 1);

if (! (EC_KEY_generate_key(myecc)))
BIO_printf(outbio, "Error generating the ECC key.");

EVP_PKEY *pkey = EVP_PKEY_new();
if (!EVP_PKEY_assign_EC_KEY(pkey, myecc))
BIO_printf(outbio, "Error assigning ECC key to EVP_PKEY structure.");

return pkey;
}

X509 * generate_x509(EVP_PKEY * pkey)
{
X509 * x509 = X509_new();

ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);

ASN1_TIME_set_string(X509_get_notBefore(x509), "0001010000Z");
ASN1_TIME_set_string(X509_get_notAfter(x509), "0001010000Z");

X509_set_pubkey(x509, pkey);

// X509v1 cannot have empty issuer & subject DN
X509_NAME * name = X509_get_subject_name(x509);

X509_NAME_add_entry_by_NID(name, 0, V_ASN1_APP_CHOOSE, "", 0, 0, 0);

X509_set_issuer_name(x509, name);

return x509;
}

void write_to_disk(EVP_PKEY * pkey, X509 * x509)
{
FILE * pkey_file = fopen("key.pem", "wb");

PEM_write_PKCS8PrivateKey(pkey_file, pkey, NULL, NULL, 0, NULL, NULL);
fclose(pkey_file);

FILE * x509_file = fopen("cert.pem", "wb");

PEM_write_X509(x509_file, x509);
fclose(x509_file);

return;
}

int main(int argc, char ** argv)
{
printf("Generating ECC key...\n");

EVP_PKEY * pkey = generate_key_ecc();
if(!pkey)
return 1;

printf("Generating X509 cert...\n");

X509 * x509 = generate_x509(pkey);
if(!x509)
{
EVP_PKEY_free(pkey);
return 1;
}

printf("Writting files....\n");

write_to_disk(pkey, x509);
EVP_PKEY_free(pkey);
X509_free(x509);

printf("Done!\n");
}
Binary file modified key.pk8
Binary file not shown.
6 changes: 0 additions & 6 deletions key.x509.pem

This file was deleted.

Binary file modified signed-release.apk
Binary file not shown.