shwenzhang/AndResGuard · error · RuntimeException

No key passwords

Error message

No key passwords

What it means

getKeyStoreKey retrieves the private key for an alias, trying each candidate key password. If the password list is empty, lastFailure remains null and a RuntimeException "No key passwords" is thrown. It means no key password candidates were supplied at all, as opposed to all candidates being wrong (which would rethrow the UnrecoverableKeyException).

Solutions

  1. Supply the key password with --key-pass pass:<password> when invoking sign.
  2. If the key password equals the keystore password, provide the same spec for --key-pass (many keystore types still require it).
  3. Check the password spec source (env var, file) is non-empty and correctly formatted.
  4. If using the API directly, pass a non-empty passwords list to getKeyStoreKey.

Example fix

// before
apksigner sign --ks release.jks --ks-pass pass:storePw --out app.apk app.apk.idsig
// after
apksigner sign --ks release.jks --ks-pass pass:storePw --key-pass pass:keyPw --out app.apk app.apk.idsig
Defensive patterns

Strategy: validation

Validate before calling

java
if (keyPassword == null || keyPassword.length == 0) {
    throw new IllegalArgumentException("Key password must be provided (--key-pass)");
}

Try / catch

java
try {
    signerBuilder.build().sign(outputFile);
} catch (RuntimeException e) {
    if ("No key passwords".equals(e.getMessage())) {
        System.err.println("Supply --key-pass pass:<password> for the keystore key.");
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Signing with a keystore-based signer where the key password spec (--key-pass) is omitted or expands to an empty list, causing loadPrivateKeyAndCertsFromKeyStore to call getKeyStoreKey with zero passwords.

Common situations: Omitting --key-pass when the key password differs from the keystore password; assuming key password defaults are applied; passing an empty value via an env var or password file.

Related errors


AI-assisted analysis of shwenzhang/AndResGuard@e4df245d82 (2026-09-12). Data as JSON: /api/errors/2fd055eb0fc5e1c7. Report an issue: GitHub.

Appendix: source

Thrown at AndResGuard-core/src/main/java/apksigner/ApkSignerTool.java:565

      if (lastFailure == null) {
        throw new RuntimeException("No keystore passwords");
      } else {
        throw lastFailure;
      }
    }

    private static Key getKeyStoreKey(KeyStore ks, String keyAlias, List<char[]> passwords)
        throws UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException {
      UnrecoverableKeyException lastFailure = null;
      for (char[] password : passwords) {
        try {
          return ks.getKey(keyAlias, password);
        } catch (UnrecoverableKeyException e) {
          lastFailure = e;
        }
      }
      if (lastFailure == null) {
        throw new RuntimeException("No key passwords");
      } else {
        throw lastFailure;
      }
    }

    private static PKCS8EncodedKeySpec decryptPkcs8EncodedKey(
        EncryptedPrivateKeyInfo encryptedPrivateKeyInfo, List<char[]> passwords)
        throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
      SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(encryptedPrivateKeyInfo.getAlgName());
      InvalidKeySpecException lastKeySpecException = null;
      InvalidKeyException lastKeyException = null;
      for (char[] password : passwords) {
        PBEKeySpec decryptionKeySpec = new PBEKeySpec(password);
        try {
          SecretKey decryptionKey = keyFactory.generateSecret(decryptionKeySpec);
          return encryptedPrivateKeyInfo.getKeySpec(decryptionKey);
        } catch (InvalidKeySpecException e) {
          lastKeySpecException = e;

View on GitHub (pinned to e4df245d82)