siglock
v0.2.0
Published
Lock your Android signing key. Verify APK/AAB signatures against your production keystore before uploading to Google Play — catch wrong-keystore mistakes in seconds, not hours.
Maintainers
Readme
siglock
Lock your Android signing key. Catch wrong-keystore mistakes before you upload to Google Play — in seconds, not hours.
The problem
Google Play requires every release of your app to be signed with the same key. If you upload an .apk/.aab signed with the wrong keystore — the debug key, a teammate's local key, a regenerated key — Google Play only tells you at submission time:
"Your Android App Bundle is signed with the wrong key."
By then you've already waited for the build, downloaded the artifact, and gone through the Play Console upload flow. On CI-driven workflows (EAS, Bitrise, custom runners) this mistake can easily cost hours.
siglock verifies the signature locally in ~2 seconds, using keytool from the JDK you already have installed as an Android developer.
Installation
# One-off (no install)
npx siglock check app-release.aab
# Or install globally
npm install -g siglock
# Or as a dev dependency in your project
npm install --save-dev siglockRequirement: a JDK on your PATH (siglock shells out to keytool). Android development already requires this — if keytool is missing, siglock prints a clear error telling you to install a JDK.
Usage
1. Lock your signature once
Point siglock init at a known-good artifact (one that Google Play already accepted) or directly at your release keystore:
# From a known-good APK / AAB
siglock init path/to/app-release.aab
# Or directly from your release keystore
siglock init path/to/release.jks --alias upload --storepass mypassword
# (you can also set the password via the SIGLOCK_STOREPASS env var)This writes a .siglock.json file to the current directory:
{
"version": 1,
"sha1": "AA:BB:CC:...",
"sha256": "11:22:33:...",
"owner": "CN=My Company, O=My Company, C=US",
"source": "app-release.aab",
"createdAt": "2026-07-22T10:00:00.000Z"
}2. Check every build before uploading
siglock check app-release.aab- ✅ Match → green
✓ Signature matches, ready to upload.and exit code0 - ❌ Mismatch → red
✗ Signature mismatch!with expected vs. found fingerprints and exit code1(perfect for failing CI jobs) - ⚠️ Debug keystore detected (
CN=Android Debug) → explicit warning that the build cannot be used for production
3. Check against a fingerprint from Play Console
No lock file needed — paste the SHA-1 or SHA-256 straight from Play Console → Setup → App signing → Upload key certificate:
siglock check app-release.aab --expect "AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD"Colons and letter case don't matter; both AA:BB:... and aabb... work.
Should I commit .siglock.json?
Yes, commit it. It contains only public certificate fingerprints (the same ones shown in Play Console) — no keys, no passwords. Committing it means every teammate and every CI run verifies against the same locked fingerprint. The generated .gitignore in this repo deliberately does not ignore it.
CI integration
GitHub Actions
- name: Verify release signature
run: npx siglock check android/app/build/outputs/bundle/release/app-release.aabThe non-zero exit code on mismatch fails the job before anything reaches Google Play.
EAS Build (Expo)
Add a post-build hook to package.json:
{
"scripts": {
"eas-build-post-install": "echo 'build hook ready'",
"verify:signature": "siglock check ./app-release.aab"
}
}Or verify a finished EAS build locally before submitting:
eas build --platform android --profile production --local
npx siglock check ./build-*.aab
eas submit --platform androidFastlane
lane :release do
gradle(task: "bundleRelease")
sh("npx siglock check ../app/build/outputs/bundle/release/app-release.aab")
upload_to_play_store(aab: "app/build/outputs/bundle/release/app-release.aab")
endsh raises on non-zero exit, so a wrong signature stops the lane before upload_to_play_store.
Command reference
| Command | Description |
|---|---|
| siglock init <file> | Extract the fingerprint from an .apk/.aab/.jks/.keystore and save .siglock.json |
| siglock init <ks> --alias <a> --storepass <p> | Init from a keystore (alias required; password via flag or SIGLOCK_STOREPASS) |
| siglock check <file> | Compare an .apk/.aab against .siglock.json (exit 0 = match, 1 = mismatch) |
| siglock check <file> --expect <fp> | Compare against an explicit SHA-1/SHA-256 fingerprint (no lock file needed) |
How it works
siglock shells out to the JDK's keytool:
keytool -printcert -jarfile <file>— reads the signing certificate from an.apkor.aabkeytool -list -v -keystore <file> -alias <alias>— reads the certificate straight from a keystore
v2/v3-only APKs: modern APKs are often signed only with APK Signature Scheme v2/v3 (no legacy v1/JAR signature), which keytool cannot read. When that happens, siglock automatically falls back to apksigner verify --print-certs from the Android SDK build-tools (found via PATH, ANDROID_HOME, ANDROID_SDK_ROOT, or the default SDK locations). AABs always carry a JAR signature, so they never need the fallback.
It parses the SHA-1/SHA-256 fingerprints and the certificate owner, then compares them (colon/case-insensitively) against your locked values. No network, no uploaded artifacts, no secrets stored.
License
MIT © Ebubekir Bingologlu
