App Signature Registration


The KLP Android SDK uses a challenge / verify flow before loyalty APIs can be used. On every challenge and verify request, the SDK sends your app’s package name and signing-certificate SHA-256. The backend accepts the request only if that pair is registered for your organization.


What you must submit

FieldDescriptionExample
Package nameApplication ID (applicationId / namespace)com.example.loyaltyapp
Signature (SHA-256)SHA-256 of the app signing certificate, lowercase hex, no colons, no sha256: prefix4c821267ac26cfc1fd4a5479c9ac2249a3248114cbcd40d554bfe624b86360d0

Submit one row per signing identity you will use against the registered backend (for example debug for internal QA and release / Play for production).

Required format

RuleCorrectIncorrect
EncodingLowercase hexadecimalUppercase only, Base64
SeparatorsNoneAA:BB:CC:...
PrefixNonesha256:, sha256/
Length64 charactersTruncated or padded values
SourceSigning certificate of the APK/AAB that runs on the deviceFirebase “SHA-1”, OkHttp pin (sha256/...=), upload-key when Play re-signs

This is not:

  • A device fingerprint
  • An SSL / certificate-pinning pin
  • The Google Services / Firebase SHA-1 or colon-separated SHA-256 string (unless you strip colons and lower-case it from the same signing cert)

How the SDK computes the value

At runtime the SDK:

  1. Reads the app’s signing certificate via PackageManager
  2. Computes SHA-256 over the certificate bytes
  3. Formats the digest as lowercase hex without separators
  4. Sends it as the signature field together with packageId

The value you register must match exactly what the installed build sends. Prefer extracting it from the same build type / signing config you ship to testers or to Play.


Recommended methods

Use whichever method matches your release process. All of them must produce the same 64-character hex string for a given certificate.

Method 1 — From the SDK (most reliable)

After KLP.initialize(...), log the hash from a build signed the way you will distribute it:

import android.util.Log
import com.klp.sdk.KLP

val packageId = packageName
val signature = KLP.getInstance().getCurrentAppSignatureHash()

Log.d("KLP", "packageId = $packageId")
Log.d("KLP", "signature = $signature")

Send both log lines to Kaizen. This value is identical to what challenge / verify will send.

Use a release (or Play-distributed) build for production registration. A debug build reports the debug certificate, which will not match production.


Method 2 — From a signed APK or AAB (apksigner)

If you have the artifact that will be installed on devices (or the AAB you upload, after you understand Play re-signing — see below), you do not need the keystore password:

# APK
apksigner verify --print-certs app-release.apk \
  | awk '/SHA-256 digest:/{print $NF}'

# Or with a full build-tools path on macOS, for example:
# ~/Library/Android/sdk/build-tools/<version>/apksigner verify --print-certs app-release.apk

Look for:

Signer #1 certificate SHA-256 digest: <64-char-hex>

That digest is already in the format the backend expects.

For an AAB, build a universal or device APK with bundletool, or use Play Console (App signing) as described below. Do not assume the upload keystore hash is what devices will see when Play App Signing is enabled.


Method 3 — From your keystore (keytool)

Use this when you sign the app yourself and the same certificate is what ends up on the device (local release, sideload, or Play without Google Play App Signing — uncommon for new apps).

# List aliases
keytool -list \
  -keystore /path/to/your.keystore \
  -storepass 'YOUR_STORE_PASSWORD'

# Print SHA-256 in SDK format (replace ALIAS and password)
keytool -list -v \
  -keystore /path/to/your.keystore \
  -alias 'YOUR_ALIAS' \
  -storepass 'YOUR_STORE_PASSWORD' \
  | awk -F'SHA256: ' '/SHA256:/{print tolower($2)}' \
  | tr -d ':'

Replace YOUR_ALIAS and YOUR_STORE_PASSWORD with real values. Leaving the placeholders unchanged produces empty or failed output.

Debug keystore (local debug builds only):

keytool -list -v \
  -keystore ~/.android/debug.keystore \
  -alias androiddebugkey \
  -storepass android \
  -keypass android \
  | awk -F'SHA256: ' '/SHA256:/{print tolower($2)}' \
  | tr -d ':'

Method 4 — Gradle signingReport

./gradlew signingReport

Under the relevant variant (for example release), find SHA-256, remove all :, and convert to lowercase.


Google Play App Signing (required reading)

Most Play apps use Play App Signing. In that model:

KeyWho holds itUsed for
Upload keyYou (local keystore)Signing the AAB you upload to Play Console
App signing keyGoogle PlayRe-signing what users download from Play

On a device installed from the Play Store (or an internal testing track that serves Play-signed artifacts), PackageManager sees Google’s app signing certificate, not your upload keystore.

What to register for production / Play testing

  1. Open Google Play Console
  2. Select your app → Setup (or Release) → App integrity / App signing
  3. Under App signing key certificate, copy SHA-256 certificate fingerprint
  4. Remove colons and lower-case the string so it matches the SDK format
  5. Submit that value with your package name

Registering only the upload key SHA-256 while users install Play-signed builds will cause challenge verification to fail in production.

When the upload key is correct

  • You install a locally signed APK/AAB that was not re-signed by Play (direct install, some CI artifacts, older apps that do not use Play App Signing)
  • You are registering a debug or internal certificate for non-Play builds

If unsure, install the build the way end users will, then use Method 1 (getCurrentAppSignatureHash()) on that install — that is the source of truth.

Internal testing / closed tracks

Artifacts delivered through Play’s testing tracks are typically still signed with the app signing key. Prefer the Play Console app signing SHA-256 (or Method 1 on a Play-installed build) rather than the upload keystore.


Multiple environments

Register every certificate that will call the backend you care about:

BuildTypical certificateRegister?
Local debugDebug keystoreYes, if QA uses debug against a shared/staging backend
Local release / CI APKYour release / upload keystoreYes, if those APKs talk to the backend outside Play
Play production / Play testingApp signing key (Play Console)Always for store-distributed apps

You may register multiple signatures for the same package name (for example debug + Play app signing key). Confirm with Kaizen how many entries your panel supports.

Changing package name or rotating the app signing key requires a new registration.


Checklist before you send values to Kaizen

  • Package name matches the shipped applicationId exactly
  • Signature is 64-character lowercase hex with no colons
  • Production / Play builds use the App signing key SHA-256 from Play Console (not only the upload key)
  • Debug and release hashes are listed separately if both will be used
  • You verified with at least one of: SDK getCurrentAppSignatureHash(), apksigner on the installed artifact, or Play Console app signing certificate
  • You noted the environment (debug / staging / production) for each hash

Suggested message to Kaizen

Package name: com.example.loyaltyapp

Production (Play App Signing key) SHA-256:
4c821267ac26cfc1fd4a5479c9ac2249a3248114cbcd40d554bfe624b86360d0

Optional — debug SHA-256 (local QA only):
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Common mistakes

MistakeResult
Submitting colon-separated Firebase-style fingerprint without stripping :Backend mismatch
Registering upload key while users install from PlayChallenge fails on real devices
Registering only debug hashRelease / Play builds fail
Wrong package name (flavor / applicationIdSuffix)Challenge fails even with correct hash
Using SSL pin format (sha256/Base64...)Not accepted
Reading hash from a different keystore than the one that signed the installed appMismatch

Troubleshooting

Challenge / verify fails with a signature-related error after integration

  1. On the failing install, log getCurrentAppSignatureHash() and compare to what was registered.
  2. Confirm whether the install came from Play, sideload, or debug.
  3. If from Play, re-check App signing key certificate in Play Console.
  4. Confirm packageName has no unexpected suffix for that flavor.

keytool prints nothing when piped through awk

Usually the keystore password or alias is wrong, and the error was swallowed by the pipe. Run keytool -list -v ... without the pipe first, fix credentials, then re-apply formatting.

Hash from keystore ≠ hash from SDK on a Play install

Expected when Play App Signing is on: devices use Google’s app signing cert. Register the Play Console value (or the SDK value from a Play install).


Related SDK API

APIPurpose
KLP.getInstance().getCurrentAppSignatureHash()Returns the current install’s signing-certificate SHA-256 (SDK format)

Summary

  1. Backend trusts package name + signing-certificate SHA-256.
  2. Format: 64-character lowercase hex, no colons.
  3. Best check: call getCurrentAppSignatureHash() on the same build users will run.
  4. With Google Play App Signing, always register the App signing key from Play Console for store builds — not only your upload keystore.


Did this page help you?