{"record":{"id":"22857bd329b7ddfb","repo":"shwenzhang/AndResGuard","slug":"keystorefile-entry-keyalias-does-not-contain-a-private-key","errorCode":null,"errorMessage":"<keystoreFile> entry \"<keyAlias>\" does not contain a private key. It contains a key of algorithm: <entryKey.getAlgorithm()>","messagePattern":"<keystoreFile> entry \"<keyAlias>\" does not contain a private key\\. It contains a key of algorithm: <entryKey\\.getAlgorithm\\(\\)>","errorType":"validation","errorClass":"ParameterException","httpStatus":null,"severity":"error","filePath":"AndResGuard-core/src/main/java/apksigner/ApkSignerTool.java","lineNumber":751,"sourceCode":"        } else {\n          // Key password spec is not specified. This means we should assume that key\n          // password is the same as the keystore password and that, if this assumption is\n          // wrong, we should prompt for key password and retry loading the key using that\n          // password.\n          try {\n            entryKey = getKeyStoreKey(ks, keyAlias, keystorePasswords);\n          } catch (UnrecoverableKeyException expected) {\n            List<char[]> keyPasswords = passwordRetriever.getPasswords(PasswordRetriever.SPEC_STDIN,\n                \"Key \\\"\" + keyAlias + \"\\\" password for \" + name\n            );\n            entryKey = getKeyStoreKey(ks, keyAlias, keyPasswords);\n          }\n        }\n\n        if (entryKey == null) {\n          throw new ParameterException(keystoreFile + \" entry \\\"\" + keyAlias + \"\\\" does not contain a key\");\n        } else if (!(entryKey instanceof PrivateKey)) {\n          throw new ParameterException(keystoreFile\n                                       + \" entry \\\"\"\n                                       + keyAlias\n                                       + \"\\\" does not contain a private\"\n                                       + \" key. It contains a key of algorithm: \"\n                                       + entryKey.getAlgorithm());\n        }\n        key = (PrivateKey) entryKey;\n      } catch (UnrecoverableKeyException e) {\n        throw new IOException(\"Failed to obtain key with alias \\\"\"\n                              + keyAlias\n                              + \"\\\" from \"\n                              + keystoreFile\n                              + \". Wrong password?\", e);\n      }\n      this.privateKey = key;\n      Certificate[] certChain = ks.getCertificateChain(keyAlias);\n      if ((certChain == null) || (certChain.length == 0)) {\n        throw new ParameterException(keystoreFile + \" entry \\\"\" + keyAlias + \"\\\" does not contain certificates\");","sourceCodeStart":733,"sourceCodeEnd":769,"githubUrl":"https://github.com/shwenzhang/AndResGuard/blob/e4df245d82f27d9a2d0dd108260a3510cbaba849/AndResGuard-core/src/main/java/apksigner/ApkSignerTool.java#L733-L769","documentation":"The entry's key was retrieved successfully but is not an instance of java.security.PrivateKey (e.g. it is a SecretKey or other Key type). APK signing requires an asymmetric private key, so apksigner throws this ParameterException and reports the key's actual algorithm.","triggerScenarios":"--ks-key-alias resolves to a secret-key entry (isKeyEntry true, getKey succeeds) whose Key fails the (entryKey instanceof PrivateKey) check — e.g. a symmetric AES key stored in the keystore, or a hardware-backed/software keystore type that returns non-PrivateKey Key implementations.","commonSituations":"Developers accidentally import a symmetric key (keytool -genseckey or JCEKS store) and try to sign with it; custom/sandboxed KeyStore providers returning wrapper Key objects not implementing PrivateKey; wrong --ks-type (JCEKS vs PKCS12) exposing secret-key entries.","solutions":["Point --ks-key-alias at the asymmetric signing key entry (RSA/EC PrivateKeyEntry), per keytool -list -v output.","If the store is JCEKS holding only secret keys, generate/import a proper signing keypair (keytool -genkeypair) and sign with that.","Check --ks-type: use the type matching the file (PKCS12 for .p12/.pfx) so entries load with the intended provider.","In code, verify entry instanceof PrivateKey and its algorithm (RSA/EC) before invoking the signer."],"exampleFix":"// before (alias points at an AES secret key)\n--ks-key-alias aes-key\n// after\n--ks-key-alias release  // RSA PrivateKeyEntry","handlingStrategy":"type-guard","validationCode":"Key entryKey = ks.getKey(alias, keyPassword);\nif (!(entryKey instanceof java.security.PrivateKey))\n    throw new IllegalArgumentException(\"Alias '\" + alias + \"' holds a \" + (entryKey == null ? \"null\" : entryKey.getAlgorithm()) + \" key, not a PrivateKey; APK signing needs RSA/EC/DSA private key.\");","typeGuard":"static boolean isSigningKey(java.security.Key k) {\n    return k instanceof java.security.PrivateKey\n        && (\"RSA\".equals(k.getAlgorithm()) || \"EC\".equals(k.getAlgorithm()) || \"DSA\".equals(k.getAlgorithm()));\n}","tryCatchPattern":null,"preventionTips":["Never use keystores created with keytool -genseckey (symmetric keys) for APK signing","Confirm the entry type is PrivateKeyEntry with keytool -list -v before configuring the signer","Match --ks-type to the file format so the right provider loads entries","Keep separate keystores: symmetric keys for data encryption, asymmetric keypairs for signing"],"tags":["keystore","apksigner","type-mismatch","android-signing"],"backgroundTag":"type-mismatch","analyzedSha":"e4df245d82f27d9a2d0dd108260a3510cbaba849","analyzedAt":"2026-09-12T17:49:07.798Z","contentChangedAt":"2026-09-12T17:49:07.798Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}