{"record":{"id":"4c1d02ee4d677d47","repo":"shwenzhang/AndResGuard","slug":"failed-to-parse-encrypted-private-key-blob-keyfile","errorCode":null,"errorMessage":"Failed to parse encrypted private key blob <keyFile>","messagePattern":"Failed to parse encrypted private key blob <keyFile>","errorType":"exception","errorClass":"InvalidKeySpecException","httpStatus":null,"severity":"error","filePath":"AndResGuard-core/src/main/java/apksigner/ApkSignerTool.java","lineNumber":802,"sourceCode":"      byte[] privateKeyBlob = readFully(new File(keyFile));\n\n      PKCS8EncodedKeySpec keySpec;\n      // Potentially encrypted key blob\n      try {\n        EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = new EncryptedPrivateKeyInfo(privateKeyBlob);\n\n        // The blob is indeed an encrypted private key blob\n        String passwordSpec = (keyPasswordSpec != null) ? keyPasswordSpec : PasswordRetriever.SPEC_STDIN;\n        List<char[]> keyPasswords = passwordRetriver.getPasswords(passwordSpec, \"Private key password for \" + name);\n        keySpec = decryptPkcs8EncodedKey(encryptedPrivateKeyInfo, keyPasswords);\n      } catch (IOException e) {\n        // The blob is not an encrypted private key blob\n        if (keyPasswordSpec == null) {\n          // Given that no password was specified, assume the blob is an unencrypted\n          // private key blob\n          keySpec = new PKCS8EncodedKeySpec(privateKeyBlob);\n        } else {\n          throw new InvalidKeySpecException(\"Failed to parse encrypted private key blob \" + keyFile, e);\n        }\n      }\n\n      // Load the private key from its PKCS #8 encoded form.\n      try {\n        privateKey = loadPkcs8EncodedPrivateKey(keySpec);\n      } catch (InvalidKeySpecException e) {\n        throw new InvalidKeySpecException(\"Failed to load PKCS #8 encoded private key from \" + keyFile, e);\n      }\n\n      // Load certificates\n      Collection<? extends Certificate> certs;\n      try (FileInputStream in = new FileInputStream(certFile)) {\n        certs = CertificateFactory.getInstance(\"X.509\").generateCertificates(in);\n      }\n      List<X509Certificate> certList = new ArrayList<>(certs.size());\n      for (Certificate cert : certs) {\n        certList.add((X509Certificate) cert);","sourceCodeStart":784,"sourceCodeEnd":820,"githubUrl":"https://github.com/shwenzhang/AndResGuard/blob/e4df245d82f27d9a2d0dd108260a3510cbaba849/AndResGuard-core/src/main/java/apksigner/ApkSignerTool.java#L784-L820","documentation":"This InvalidKeySpecException is thrown when readEncryptedPkcs8PrivateKey fails to parse the key blob as an encrypted PKCS#8 structure AND a key password was actually specified (keyPasswordSpec != null). The library interprets the parse failure as: you gave a password, so the blob should be encrypted, but it is not valid encrypted-PKCS#8 data (or the password is wrong).","triggerScenarios":"loadPrivateKeyAndCertsFromFiles reads --key, the blob does not parse as encrypted PKCS#8 (EncryptionAlgorithmException / ASN.1 failure), and --key-pass was supplied, so the fallback to unencrypted PKCS#8 is refused.","commonSituations":"Passing a PEM private key (Base64, unencrypted) while also supplying --key-pass, so it cannot be an 'encrypted blob'; feeding a PKCS#1 ('RSA PRIVATE KEY') file instead of PKCS#8; truncated or corrupted key files; wrong password for a genuinely encrypted key.","solutions":["Omit --key-pass if the key file is unencrypted, letting the library parse it as plain PKCS#8.","Convert the key to PKCS#8: 'openssl pkcs8 -topk8 -in key.pem -out key.pk8' (add -v2 des3 for encryption).","Verify the file is a valid PKCS#8 blob: 'openssl asn1parse -in keyfile' and check the header (BEGIN PRIVATE KEY / BEGIN ENCRYPTED PRIVATE KEY, not BEGIN RSA PRIVATE KEY).","Re-download/regenerate the key file if it is truncated or corrupted, and confirm the password is correct."],"exampleFix":"// before: PEM RSA key + password flag\napksigner sign --key rsa_key.pem --key-pass pass:secret --cert cert.pem ...\n// after: convert to PKCS#8 first, then sign without unneeded password\nopenssl pkcs8 -topk8 -nocrypt -in rsa_key.pem -out key.pk8\napksigner sign --key key.pk8 --cert cert.pem ...","handlingStrategy":"validation","validationCode":"// Verify key format before signing\nString head = new String(java.nio.file.Files.readAllBytes(Paths.get(keyPath)), 0, 40);\nboolean isPem = head.contains(\"PRIVATE KEY\");\nboolean isPkcs1 = head.contains(\"BEGIN RSA PRIVATE KEY\");\nif (isPkcs1) throw new IllegalArgumentException(\"PKCS#1 key detected; convert with: openssl pkcs8 -topk8 -in key.pem -out key.pk8\");\nif (keyPassSpecified && head.contains(\"BEGIN PRIVATE KEY\") && !head.contains(\"BEGIN ENCRYPTED\")) {\n  throw new IllegalArgumentException(\"Key is unencrypted; remove --key-pass\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  signerParams.loadPrivateKeyAndCerts(passwordRetriever);\n} catch (InvalidKeySpecException e) {\n  if (e.getMessage() != null && e.getMessage().startsWith(\"Failed to parse encrypted private key blob\")) {\n    // convert to PKCS#8 or drop --key-pass, then retry\n  } throw e;\n}","preventionTips":["Standardize on PKCS#8 keys (openssl pkcs8 -topk8) for file-based signing.","Only supply --key-pass when the key file is genuinely encrypted (BEGIN ENCRYPTED PRIVATE KEY).","Validate key files with 'openssl asn1parse' or 'openssl pkey -check' before running CI signing jobs."],"tags":["signing","private-key","pkcs8","key-format","android"],"backgroundTag":"invalid-key-format","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"}