shwenzhang/AndResGuard · error · InvalidKeySpecException

Not an RSA, EC, or DSA private key

Error message

Not an RSA, EC, or DSA private key

What it means

loadPkcs8EncodedPrivateKey tries to parse a decrypted PKCS#8 key spec using the RSA, EC, and DSA KeyFactory implementations in turn. If all three reject the spec with InvalidKeySpecException, it throws InvalidKeySpecException "Not an RSA, EC, or DSA private key". The decrypted key material is not a supported private-key algorithm for APK signing.

Solutions

  1. Regenerate or export the signing key as RSA, EC, or DSA PKCS#8 (e.g. openssl pkcs8 -topk8 -nocrypt -in key.pem -out key.pk8).
  2. Verify the key file is a PRIVATE KEY (PKCS#8), not a public key or certificate: openssl pkey -in key.pk8 -noout -text.
  3. Confirm the key was fully decrypted (not still encrypted); check with `openssl pkcs8 -in key.pk8 -passin pass:...`.
  4. Re-download/re-export the key if the file may be corrupted or truncated.
  5. Switch to keystore-based signing (--ks) if the key algorithm cannot be converted.

Example fix

// before
apksigner sign --key ed25519.key.pk8 --cert cert.x509.pem --out app.apk app-unsigned.apk
// after
openssl pkcs8 -topk8 -nocrypt -in rsa_key.pem -out rsa_key.pk8
apksigner sign --key rsa_key.pk8 --cert cert.x509.pem --out app.apk app-unsigned.apk
Defensive patterns

Strategy: validation

Validate before calling

java
// Verify the key parses with a supported algorithm before signing
byte[] encoded = readFully(new File(keyFile));
try {
    java.security.KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(encoded));
} catch (Exception e) {
    throw new IllegalArgumentException("Key must be an RSA, EC, or DSA PKCS#8 private key", e);
}

Type guard

java
boolean isSupportedPrivateKey(PrivateKey k) {
    String alg = k.getAlgorithm();
    return "RSA".equals(alg) || "EC".equals(alg) || "DSA".equals(alg);
}

Try / catch

java
try {
    signerBuilder.build().sign(outputFile);
} catch (InvalidKeySpecException e) {
    if (e.getMessage() != null && e.getMessage().contains("Not an RSA, EC, or DSA")) {
        System.err.println("Key file is not an RSA/EC/DSA PKCS#8 private key; re-export it.");
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Passing a --key file whose decrypted PKCS#8 content encodes an unsupported algorithm (e.g. Ed25519, or garbage/incorrect padding after a wrong decryption) so all three KeyFactory.generatePrivate calls fail.

Common situations: Using a modern key type like Ed25519 unsupported by the signer; providing a corrupted or truncated key file; supplying an RSA public key or certificate instead of a private key; a bad PKCS#8 conversion via openssl that produced a public key structure.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

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

        throw lastKeySpecException;
      }
    }

    private static PrivateKey loadPkcs8EncodedPrivateKey(PKCS8EncodedKeySpec spec)
        throws InvalidKeySpecException, NoSuchAlgorithmException {
      try {
        return KeyFactory.getInstance("RSA").generatePrivate(spec);
      } catch (InvalidKeySpecException expected) {
      }
      try {
        return KeyFactory.getInstance("EC").generatePrivate(spec);
      } catch (InvalidKeySpecException expected) {
      }
      try {
        return KeyFactory.getInstance("DSA").generatePrivate(spec);
      } catch (InvalidKeySpecException expected) {
      }
      throw new InvalidKeySpecException("Not an RSA, EC, or DSA private key");
    }

    private boolean isEmpty() {
      return (name == null)
             && (keystoreFile == null)
             && (keystoreKeyAlias == null)
             && (keystorePasswordSpec == null)
             && (keyPasswordSpec == null)
             && (keystoreType == null)
             && (keystoreProviderName == null)
             && (keystoreProviderClass == null)
             && (keystoreProviderArg == null)
             && (keyFile == null)
             && (certFile == null)
             && (v1SigFileBasename == null)
             && (privateKey == null)
             && (certs == null);
    }

View on GitHub (pinned to e4df245d82)