shwenzhang/AndResGuard · error · InvalidKeySpecException

Failed to parse encrypted private key blob

Error message

Failed to parse encrypted private key blob <keyFile>

What it means

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).

Solutions

  1. Omit --key-pass if the key file is unencrypted, letting the library parse it as plain PKCS#8.
  2. Convert the key to PKCS#8: 'openssl pkcs8 -topk8 -in key.pem -out key.pk8' (add -v2 des3 for encryption).
  3. 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).
  4. Re-download/regenerate the key file if it is truncated or corrupted, and confirm the password is correct.

Example fix

// before: PEM RSA key + password flag
apksigner sign --key rsa_key.pem --key-pass pass:secret --cert cert.pem ...
// after: convert to PKCS#8 first, then sign without unneeded password
openssl pkcs8 -topk8 -nocrypt -in rsa_key.pem -out key.pk8
apksigner sign --key key.pk8 --cert cert.pem ...
Defensive patterns

Strategy: validation

Validate before calling

// Verify key format before signing
String head = new String(java.nio.file.Files.readAllBytes(Paths.get(keyPath)), 0, 40);
boolean isPem = head.contains("PRIVATE KEY");
boolean isPkcs1 = head.contains("BEGIN RSA PRIVATE KEY");
if (isPkcs1) throw new IllegalArgumentException("PKCS#1 key detected; convert with: openssl pkcs8 -topk8 -in key.pem -out key.pk8");
if (keyPassSpecified && head.contains("BEGIN PRIVATE KEY") && !head.contains("BEGIN ENCRYPTED")) {
  throw new IllegalArgumentException("Key is unencrypted; remove --key-pass");
}

Try / catch

try {
  signerParams.loadPrivateKeyAndCerts(passwordRetriever);
} catch (InvalidKeySpecException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Failed to parse encrypted private key blob")) {
    // convert to PKCS#8 or drop --key-pass, then retry
  } throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


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

Appendix: source

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

      byte[] privateKeyBlob = readFully(new File(keyFile));

      PKCS8EncodedKeySpec keySpec;
      // Potentially encrypted key blob
      try {
        EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = new EncryptedPrivateKeyInfo(privateKeyBlob);

        // The blob is indeed an encrypted private key blob
        String passwordSpec = (keyPasswordSpec != null) ? keyPasswordSpec : PasswordRetriever.SPEC_STDIN;
        List<char[]> keyPasswords = passwordRetriver.getPasswords(passwordSpec, "Private key password for " + name);
        keySpec = decryptPkcs8EncodedKey(encryptedPrivateKeyInfo, keyPasswords);
      } catch (IOException e) {
        // The blob is not an encrypted private key blob
        if (keyPasswordSpec == null) {
          // Given that no password was specified, assume the blob is an unencrypted
          // private key blob
          keySpec = new PKCS8EncodedKeySpec(privateKeyBlob);
        } else {
          throw new InvalidKeySpecException("Failed to parse encrypted private key blob " + keyFile, e);
        }
      }

      // Load the private key from its PKCS #8 encoded form.
      try {
        privateKey = loadPkcs8EncodedPrivateKey(keySpec);
      } catch (InvalidKeySpecException e) {
        throw new InvalidKeySpecException("Failed to load PKCS #8 encoded private key from " + keyFile, e);
      }

      // Load certificates
      Collection<? extends Certificate> certs;
      try (FileInputStream in = new FileInputStream(certFile)) {
        certs = CertificateFactory.getInstance("X.509").generateCertificates(in);
      }
      List<X509Certificate> certList = new ArrayList<>(certs.size());
      for (Certificate cert : certs) {
        certList.add((X509Certificate) cert);

View on GitHub (pinned to e4df245d82)