• Stars
    star
    142
  • Rank 250,850 (Top 6 %)
  • Language
    Python
  • License
    GNU General Publi...
  • Created about 3 years ago
  • Updated 10 days ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

apksigcopier - copy/extract/patch android apk signatures & compare apks

GitHub Release PyPI Version Python Versions CI GPLv3+

Packaging status Packaging status

apksigcopier

copy/extract/patch android apk signatures & compare apks

apksigcopier is a tool that enables using an android APK signature as a build input (by copying it from a signed APK to an unsigned one), making it possible to create a (bit-by-bit identical) reproducible build from the source code without having access to the private key used to create the signature. It can also be used to verify that two APKs with different signatures are otherwise identical. Its command-line tool offers four operations:

  • copy signatures directly from a signed to an unsigned APK
  • extract signatures from a signed APK to a directory
  • patch previously extracted signatures onto an unsigned APK
  • compare two APKs with different signatures

Extract

$ mkdir meta
$ apksigcopier extract signed.apk meta
$ ls -1 meta
8BEA2A77.RSA
8BEA2A77.SF
APKSigningBlock
APKSigningBlockOffset
MANIFEST.MF

Patch

$ apksigcopier patch meta unsigned.apk out.apk

Copy (Extract & Patch)

$ apksigcopier copy signed.apk unsigned.apk out.apk

Compare (Copy & Verify)

Compare two APKs by copying the signature from the first to a copy of the second and checking if the resulting APK verifies.

This command requires apksigner.

$ apksigcopier compare foo-from-fdroid.apk foo-built-locally.apk
$ apksigcopier compare --unsigned foo.apk foo-unsigned.apk

NB: copying from an APK v1-signed with signflinger to an APK signed with apksigner works, whereas the reverse fails; see the FAQ.

Help

$ apksigcopier --help
$ apksigcopier copy --help      # extract --help, patch --help, etc.

$ man apksigcopier              # requires the man page to be installed

Environment Variables

The following environment variables can be set to 1, yes, or true to override the default behaviour:

  • set APKSIGCOPIER_EXCLUDE_ALL_META=1 to exclude all metadata files
  • set APKSIGCOPIER_COPY_EXTRA_BYTES=1 to copy extra bytes after data (e.g. a v2 sig)
  • set APKSIGCOPIER_SKIP_REALIGNMENT=1 to skip realignment of ZIP entries

Python API

>>> from apksigcopier import do_extract, do_patch, do_copy, do_compare
>>> do_extract(signed_apk, output_dir, v1_only=NO)
>>> do_patch(metadata_dir, unsigned_apk, output_apk, v1_only=NO)
>>> do_copy(signed_apk, unsigned_apk, output_apk, v1_only=NO)
>>> do_compare(first_apk, second_apk, unsigned=False)

You can use False, None, and True instead of NO, AUTO, and YES respectively.

The following global variables (which default to False), can be set to override the default behaviour:

  • set exclude_all_meta=True to exclude all metadata files
  • set copy_extra_bytes=True to copy extra bytes after data (e.g. a v2 sig)
  • set skip_realignment=True to skip realignment of ZIP entries

FAQ

What kind of signatures does apksigcopier support?

It currently supports v1 + v2 + v3 (which is a variant of v2).

It should also support v4, since these are stored in a separate file (and require a complementary v2/v3 signature).

When using the extract command, the v2/v3 signature is saved as APKSigningBlock + APKSigningBlockOffset.

How does patching work?

First it copies the APK exactly like apksigner would when signing it, including re-aligning ZIP entries and skipping existing v1 signature files.

Then it adds the extracted v1 signature files (.SF, .RSA/.DSA/.EC, MANIFEST.MF) to the APK, using the correct ZIP metadata (either the same metadata as apksigner would, or from differences.json).

And lastly it inserts the extracted APK Signing Block at the correct offset (adding zero padding if needed) and updates the central directory (CD) offset in the end of central directory (EOCD) record.

For more information about the ZIP file format, see e.g. the Wikipedia article.

What does the "APK Signing Block offset < central directory offset" error mean?

It means that apksigcopier can't insert the APK Signing Block at the required location, since that offset is in the middle of the ZIP data (instead of right after the data, before the central directory).

In other words: the APK you are trying to copy the signature to is larger than the one the signature was copied from. Thus the signature cannot be copied (and could never have been valid for the APK you are trying to copy it to).

In the context of verifying reproducible builds, getting this error almost certainly means the build was not reproducible.

What about APKs signed by gradle/zipflinger/signflinger instead of apksigner?

Compared to APKs signed by apksigner, APKs signed with a v1 signature by zipflinger/signflinger (e.g. using gradle) have different ZIP metadata -- create_system, create_version, external_attr, extract_version, flag_bits -- and compresslevel for the v1 signature files (.SF, .RSA/.DSA/.EC, MANIFEST.MF); they also usually have a 132-byte virtual entry at the start as well.

Recent versions of apksigcopier will detect these ZIP metadata differences and the virtual entry (if any); extract will save them in a differences.json file (if they exist), which patch will read (if it exists); copy and compare simply pass the same information along internally.

CAVEAT for compare

NB: because compare copies from the first APK to the second, it will fail when only the second APK is v1-signed with zipflinger/signflinger; e.g.

$ compare foo-signflinger.apk foo-apksigner.apk   # copies virtual entry; works
$ compare foo-apksigner.apk foo-signflinger.apk   # only 2nd APK has virtual entry
DOES NOT VERIFY
[...]
Error: failed to verify /tmp/.../output.apk.

What are these virtual entries?

A virtual entry is a ZIP entry with an empty filename, an extra field filled with zero bytes, and no corresponding central directory entry (so it should be effectively invisible to most ZIP tools).

When zipflinger deletes an entry it leaves a "hole" in the archive when there remain non-deleted entries after it. It later fills these "holes" with virtual entries.

There is usually a 132-byte virtual entry at the start of an APK signed with a v1 signature by signflinger/zipflinger; almost certainly this is a default manifest ZIP entry created at initialisation, deleted (from the central directory but not from the file) during v1 signing, and eventually replaced by a virtual entry.

Depending on what value of Created-By and Built-By were used for the default manifest, this virtual entry may be a different size; apksigcopier supports any size between 30 and 4096 bytes.

Installing

Debian

Official packages are available in Debian and Ubuntu.

$ apt install apksigcopier

You can also manually build a Debian package using the debian/sid branch, or download a pre-built .deb via GitHub releases.

NixOS & Arch Linux

Official packages are also available in nixpkgs and Arch Linux (and derivatives).

Using pip

$ pip install apksigcopier

NB: depending on your system you may need to use e.g. pip3 --user instead of just pip.

From git

NB: this installs the latest development version, not the latest release.

$ git clone https://github.com/obfusk/apksigcopier.git
$ cd apksigcopier
$ pip install -e .

NB: you may need to add e.g. ~/.local/bin to your $PATH in order to run apksigcopier.

To update to the latest development version:

$ cd apksigcopier
$ git pull --rebase

Dependencies

  • Python >= 3.7 + click.
  • The compare command also requires apksigner.

Debian/Ubuntu

$ apt install python3-click
$ apt install apksigner         # only needed for the compare command

License

GPLv3+

More Repositories

1

jiten

jiten - japanese android/cli/web dictionary based on jmdict/kanjidic — 日本語 辞典 和英辞典 漢英字典 和独辞典 和蘭辞典
Python
97
star
2

reproducible-apk-tools

reproducible-apk-tools - scripts to make android apks reproducible
Python
45
star
3

autossh-init

autossh-init - AutoSSH init script
39
star
4

apksigtool

apksigtool - parse/verify/clean/sign android apk (signing block)
Python
32
star
5

koneko

koneko - a concatenative not-quite-lisp for kittens
Haskell
19
star
6

fdroid-fakesigner-poc

F-Droid Fake Signer PoC
Python
17
star
7

kanjidraw

kanjidraw - handwritten kanji recognition library + gui
Python
15
star
8

netcat.py

netcat.py - python (2+3) netcat
Python
11
star
9

sokobang

sokobang - sokoban puzzle w/ bigbang.coffee
HTML
11
star
10

sigblock-code-poc

android apk signing block payload poc
Kotlin
8
star
11

bash-cheatsheet

bash cheat sheet
8
star
12

active-dump

active-dump - dump and restore activerecord from/to yaml
Ruby
8
star
13

apkrepotool

apkrepotool - manage APK repos
Python
8
star
14

eft

eft - ruby + whiptail
Ruby
7
star
15

rbtlog

Reproducible Builds Transparency Log for Android APKs
Python
7
star
16

gitbak

UNMAINTAINED & REPLACED BY https://github.com/obfusk/ghbak !!! [gitbak - bitbucket/github/gist backup]
Ruby
6
star
17

fdroid-misc-scripts

fdroid-misc-scripts - miscellaneous scripts to analyse f-droid app data
Python
6
star
18

trstools.py

trstools.py - python (2+3) term rewriting tools
Python
5
star
19

m

m - minimalistic media manager
Python
5
star
20

mgit

mgit - multi-dir git wrapper
Shell
5
star
21

taskmaster

taskmaster - manage tasks using a Taskfile
Shell
5
star
22

achatwithsinatra

achatwithsinatra - a simple sinatra chat app
Ruby
4
star
23

open_uri_w_redirect_to_https

open_uri_w_redirect_to_https - open-uri HTTP to HTTPS redirect support patch
Ruby
4
star
24

jiten-nonfree-data

jiten - japanese android/cli/web dictionary based on jmdict/kanjidic - non-free data
Python
4
star
25

fdroid-release-redirector

fdroid-release-redirector - redirector for code forges that don't have stable URLs for release assets
Python
4
star
26

webrtc-xftv

webrtc-xftv - record video+audio with webrtc/xftv/recorderjs
Ruby
4
star
27

nix-vault-with-ui

nix(os) vault package w/ ui (using nix-npm-buildpackage)
Nix
4
star
28

bigbang.coffee

bigbang.coffee - graphical/evented functional programming for js/coffee
CoffeeScript
3
star
29

eft.sh

eft.sh - bash + whiptail
Shell
3
star
30

2des-attack

Python
3
star
31

napp-hello-ncat

napp-hello-ncat - hello world w/ ncat
Shell
3
star
32

m-gui

m - minimalistic media manager - GUI
Python
3
star
33

fnjs

[TODO, ONHOLD] fnjs - functional javascript
Clojure
3
star
34

convert-to-requests

convert-to-requests - convert curl/fetch command to python requests
Python
3
star
35

cryptoparty-privacycafe-menu

cryptoparty/privacycafe menu
Makefile
3
star
36

rb-localconfig

[rb-]localconfig - local configuration for ruby (web) apps
Ruby
3
star
37

proudcat-rust

proudcat-rust - cat + 🌈
Rust
3
star
38

kanji-strokes

REPLACED BY https://github.com/obfusk/jiten [kanji-strokes - 漢字と仮名の筆順 - stroke order for japanese text]
HTML
3
star
39

keep-it-private

[TODO] keep-it-private - privacy/crypto presentations
CSS
3
star
40

pypride

pypride - python (2+3) PRIDE cipher implementation
Python
2
star
41

proudcat

proudcat - cat + 🌈
Python
2
star
42

gpg

gpg key + fingerprint + HOWTO
2
star
43

baktogit

baktogit - backup w/ git
Shell
2
star
44

mail-config

my mutt + isync config
2
star
45

cahpy

cahpy - capybaras against humanity
Python
2
star
46

nametag

nametag - set audio file tags based on file name
Ruby
2
star
47

test-apks

test APKs for apksigcopier & apksigtool
2
star
48

aruba-obfusk

aruba-obfusk - aruba extensions
Ruby
2
star
49

simple-stack-exploit

simple-stack-exploit - a simple demo exploit
C
2
star
50

bash-presentation

bash presentation
2
star
51

st

[FORK] st - simple terminal
C
2
star
52

algorithms.py

algorithms.py - python (2+3) implementations of standard algorithms
Python
2
star
53

buffer-overflows-101

buffer overflows presentation
HTML
2
star
54

jiten-webview

jiten-webview - android webview wrapper for jiten.obfusk.dev
Kotlin
2
star
55

siresta

[TODO] siRESTa - declarative REST APIs
Ruby
2
star
56

algorithms.cpp

algorithms.cpp - implementations of standard algorithms in C++
C++
2
star
57

bigbang-examples

bigbang-examples - bigbang.coffee examples
CoffeeScript
2
star
58

bundler-fu

bundler-fu - tools for bundler
Ruby
2
star
59

shtst

shtst - simple cli testing
Python
2
star
60

ci-pr-conflict-test

Python
2
star
61

checkupdates

Python
2
star
62

dotfiles

some of my dotfiles
Shell
2
star
63

belasting-vm

[DO NOT USE] belasting-vm - scripts for aangifte inkomstenbelasting VM
Shell
2
star
64

clj-obfusk-data

[clj-]obfusk-data - data validation combinator library for clojure
Clojure
2
star
65

nametag.py

nametag - set audio file tags based on file name
Python
2
star
66

awesome-config

my awesome config
Lua
2
star
67

clmn

Python
2
star
68

bigbang-snake

bigbang-snake - snake game w/ bigbang.coffee
HTML
2
star
69

ghbak

ghbak - github backup
Python
2
star
70

sniffer.py

sniffer.py - python (2+3) network sniffer
Python
2
star
71

map.sh

map.sh - map/filter for bash
Shell
2
star
72

eftcmdr

eftcmdr - yaml + ruby + whiptail
Ruby
2
star
73

flx-docs

[OLD] miscellaneous docs: unix/git/...
2
star
74

gradle-wrapper-verify

gradle-wrapper-verify - verify gradle-wrapper.jar sha256sum against published releases
Shell
2
star
75

play-galgje

JavaScript
1
star
76

obfusk.coffee

[TODO] obfusk.coffee - functional programming library for js/coffee
CoffeeScript
1
star
77

git-boot

[OLD] git-boot - git meta-projects
Shell
1
star
78

kivy-android-hello-world

Python
1
star
79

obfusk.github.io-OLD

[OLD]
Ruby
1
star
80

misc

miscellaneous stuff
1
star
81

napp-hello-express

napp-hello-express - hello world w/ express
CoffeeScript
1
star
82

gh.py

Python
1
star
83

pp-meta

[TODO, ONHOLD] pp-meta - pp-* puppet meta project
Ruby
1
star
84

nap-puppet

[TODO, ONHOLD] nap-puppet - puppet configuration for nap server
Puppet
1
star
85

dev-misc

scripts + *rc
Vim Script
1
star
86

stsffap

C
1
star
87

iot-tdose

my IoT presentation for T-DOSE
1
star
88

pp-misc

[TODO, ONHOLD] pp-misc - miscellaneous puppet modules
Puppet
1
star
89

playing-with-haskell

Haskell
1
star
90

manifest-dl

manifest-dl - download extra files for your ruby app
Ruby
1
star
91

obfusk.rb

obfusk.rb - functional programming library for ruby
Ruby
1
star
92

hs-flx

[TODO] hs-flx - miscellaneous haskell modules
Haskell
1
star
93

dlthing

dlthing.py - youtube-dl in your browser
Python
1
star
94

napp-hello-compojure

napp-hello-compojure - hello world w/ compojure
Clojure
1
star
95

play-cryptanalysis

JavaScript
1
star
96

xuggle-frames-to-video

xuggle-frames-to-video (xftv) - turn a stream of frame+timestamp into a video - useful for webrtc
Clojure
1
star
97

fsfe-blog

fsfe-blog - data from my fsfe blog
1
star
98

phonegap-android-coffee-haml

phonegap-android-coffee-haml - use coffeescript and haml to build phonegap apps on android
Ruby
1
star
99

__test-cljs-2

Clojure
1
star
100

fnxnl

[TODO] fnxnl - ...
Ruby
1
star