From c99c8efa11be1080933fefe400bce28b7f39b57b Mon Sep 17 00:00:00 2001 From: Logan Date: Sun, 16 Aug 2026 22:26:29 -0400 Subject: [PATCH] ci(android): tell a wrong password apart from a wrong keystore The v1.5.0 run reported that the keystore did not open, and the diagnostics could not say why. They now clear the two causes that look identical to a wrong password. **A password pasted with its shell quotes** is two characters longer than the password and nothing in keytool's error says so. The step retries with the surrounding quotes stripped and, if *that* opens the keystore, says exactly that. It does not strip them and carry on: a password may legitimately contain a quote, so this reports a diagnosis rather than guessing at a fix. **A password that is right for a different keystore** is the other one, and it is the one currently in play -- the secret decodes to a valid 2280-byte PKCS12 and the password is the length the owner expects, which leaves "is this the keystore I have locally?" as the open question. The step prints the decoded file's sha256 so that is answerable by comparing one line against sha256sum. Hashing a certificate store gives nothing away. --- .gitea/workflows/android-apk.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/.gitea/workflows/android-apk.yml b/.gitea/workflows/android-apk.yml index 8fa051d..f91c042 100644 --- a/.gitea/workflows/android-apk.yml +++ b/.gitea/workflows/android-apk.yml @@ -277,6 +277,18 @@ jobs: size=$(stat -c %s "$keystore") magic=$(od -An -N4 -tx1 "$keystore" | tr -s ' ' | sed 's/^ //') echo "keystore: $size bytes, first four bytes: $magic" + + # The fingerprint of the decoded file, so "is the secret the + # keystore I have locally?" is answerable without guessing. + # A hash of a *public* certificate store gives nothing away, + # and the alternative is comparing byte counts by eye. + # + # sha256sum ~/path/to/yellowjacket-release.jks + # + # A password that is right for one keystore and wrong for + # another is indistinguishable from a wrong password, and this + # is the line that distinguishes them. + echo " sha256: $(sha256sum "$keystore" | cut -d' ' -f1)" case "$magic" in "30 82"*) echo " header: PKCS12 (keytool's default since JDK 9)" ;; "fe ed fe ed") echo " header: legacy JKS" ;; @@ -291,6 +303,20 @@ jobs: echo " password length after trimming: ${#pass}" >&2 sed 's/^/ keytool: /' /tmp/ks.err | head -5 >&2 echo >&2 + + # A password pasted *with its shell quotes* is the one + # remaining cause that looks identical to a wrong password: + # the secret is two characters longer than the password and + # nothing in the error says so. Naming it is safe -- + # stripping the quotes and carrying on would not be, since a + # password may legitimately contain them. + unquoted=$(printf '%s' "$pass" | sed "s/^['\"]//;s/['\"]$//") + if [ "$unquoted" != "$pass" ] && + keytool -list -keystore "$keystore" -storepass "$unquoted" >/dev/null 2>&1; then + echo " ** it opens with the surrounding quotes removed. **" >&2 + echo " Re-paste ANDROID_KEYSTORE_PASSWORD without them." >&2 + echo >&2 + fi echo "Check it locally with the same two values:" >&2 echo " printf %s \"\$SECRET_B64\" | base64 -d > /tmp/k.jks" >&2 echo " keytool -list -keystore /tmp/k.jks -storepass ''" >&2