Inside Code Transparency: The Verification Process
A week ago, I looked at the contents of the JWT file created by the code transparency process. Today, let’s peek at how that gets verified.
bundletool
Commands
Last week, when I showed you a bundletool
command to add code transparency, I used
a command that used a Java keystore directly. That does not seem to be an option for
the verification step. For that (or for adding code transparency), you need an
actual certificate file. You can obtain one from your keystore using keytool
:
keytool -export \
-alias WhateverAliasYouUsed \
-keystore /path/to/your/keystore.jks \
-rfc \
-file /path/to/your/exported.cert
You can then use the check-transparency
command to verify the contents of… something.
The --mode
option indicates what the “something” is. --mode=bundle
says that you
are verifying an App Bundle, such as one created by you or your CI server:
bundletool check-transparency \
--mode=bundle \
--bundle=/path/to/your/AppBundleWithCT.aab \
--transparency-key-certificate=/path/to/your/exported.cert
If you leave off the --transparency-key-certificate
option, bundletool
will
print the SHA-256 fingerprint of the certificate:
No APK present. APK signature was not checked.
Code transparency signature is valid. SHA-256 fingerprint of the code transparency key certificate (must be compared with the developer's public key manually): 25 98 AA 59 62 BA 4C C0 7B 40 74 F4 19 09 02 A0 2A CD F1 1B 1F 42 84 92 93 23 8B 6F 87 E5 42 B4
Code transparency verified: code related file contents match the code transparency file.
This should match the one you get from keytool
:
keytool -list \
-alias WhateverAliasYouUsed \
-keystore /path/to/your/keystore.jks
Alternatively, you can have bundletool
verify the code transparency for an installed app,
via --mode=connected_device
:
bundletool check-transparency \
--mode=connected_device \
--package-name=com.commonsware.scrap
As before, if you include --transparency-key-certificate
, bundletool
will check
against it; otherwise it will print the SHA-256 fingerprint.
bundletool
Implementation
Much of the code for code transparency support in bundletool
resides in
the com.android.tools.build.bundletool.transparency
package.
The core “driver” of the verification resides in a set of static
methods
on ApkTransparencyCheckUtils
. This code works off of a list of filesystem paths
to the APKs to check. Where those APKs come from depends on your --mode
. Of
particular note, for --mode=connected_device
, bundletool
uses adb shell
commands
to copy the APKs to a temporary directory for analysis – the verification is
not performed in situ on the device.
The code uses this JSON Web Toolkit library, which seems to be actively maintained, which is nice.
Unfortunately, the code for bundletool
seems to be fairly monolithic. It does not appear to be organized
as a library with a first-class API that also happens to have a CLI — it looks like it is
just a CLI. And, since bundletool
historically has only been needed for development
machines and CI servers, in many places it seems to assume that environment. Getting verification logic
that can run on-device will require reverse-engineering a spec from the implementation and creating a separate
library, unless Google has interest in a significant reworking of bundletool
.