shwenzhang/AndResGuard · error · java.lang.RuntimeException

private key is not a DSA or RSA key

Error message

private key is not a DSA or RSA key

What it means

This RuntimeException is thrown by getSignatureAlgorithm when the private key loaded from the keystore has an algorithm other than DSA, RSA, or EC. The library builds a jarsigner signature algorithm string (e.g. 'SHA1withRSA') from the key algorithm and only supports those three; any other key type (or an unrecognizable algorithm name) makes it impossible to construct a valid v1 signing algorithm, so it fails fast.

Solutions

  1. Regenerate or export the signing key as RSA (keytool -genkeypair -keyalg RSA) and update the keystore used by AndResGuard
  2. Switch to v2/v3 signing (buildApkWithV2V3Sign path), which uses apksigner and does not depend on this algorithm whitelist
  3. Check the actual algorithm of the alias with keytool -list -keystore your.keystore and confirm it is RSA/DSA/EC
  4. If the key is EC but reported under another name, patch/rebuild with support for that algorithm string

Example fix

// before: EC key named 'ECDSA' or Ed25519 key in keystore
// after: regenerate an RSA key
keytool -genkeypair -v -keystore release.keystore -alias appkey \
  -keyalg RSA -keysize 2048 -validity 10000
Defensive patterns

Strategy: validation

Validate before calling

KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
try (FileInputStream in = new FileInputStream(sigFile)) { ks.load(in, storePass.toCharArray()); }
Key key = ks.getKey(alias, keyPass.toCharArray());
String alg = key == null ? null : key.getAlgorithm();
boolean ok = alg != null && (alg.equalsIgnoreCase("RSA") || alg.equalsIgnoreCase("DSA") || alg.equalsIgnoreCase("EC"));
if (!ok) throw new IllegalStateException("Keystore alias '" + alias + "' key algorithm not supported for v1 signing: " + alg);

Type guard

boolean isSupportedSigningKey(java.security.Key k) {
  if (k == null) return false;
  String a = k.getAlgorithm();
  return "RSA".equalsIgnoreCase(a) || "DSA".equalsIgnoreCase(a) || "EC".equalsIgnoreCase(a);
}

Prevention

When it happens

Trigger: Calling buildApkWithV1sign with a keystore whose alias resolves to a private key whose getAlgorithm() is not DSA/RSA/EC — e.g. an Elliptic Curve key stored under a non-standard name, a HSM/PKCS11 key, or a key with an unusual algorithm identifier.

Common situations: Signing with a modern keystore generated with exotic key algorithms (e.g. Ed25519, X25519, or P-384 keys reported under names other than 'EC'); using a hardware-backed or PKCS12 entry whose algorithm string differs from what the JCE reports; switching to a new release keystore that is not RSA.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at AndResGuard-core/src/main/java/com/tencent/mm/androlib/ResourceApkBuilder.java:186

  private String getSignatureAlgorithm(String hash) throws Exception {
    String signatureAlgorithm;
    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    FileInputStream fileIn = new FileInputStream(config.mSignatureFile);
    keyStore.load(fileIn, config.mStorePass.toCharArray());
    Key key = keyStore.getKey(config.mStoreAlias, config.mKeyPass.toCharArray());
    if (key == null) {
      throw new RuntimeException("Can't get private key, please check if storepass storealias and keypass are correct");
    }
    String keyAlgorithm = key.getAlgorithm();
    hash = formatHashAlgorithName(hash);
    if (keyAlgorithm.equalsIgnoreCase("DSA")) {
      keyAlgorithm = "DSA";
    } else if (keyAlgorithm.equalsIgnoreCase("RSA")) {
      keyAlgorithm = "RSA";
    } else if (keyAlgorithm.equalsIgnoreCase("EC")) {
      keyAlgorithm = "ECDSA";
    } else {
      throw new RuntimeException("private key is not a DSA or RSA key");
    }
    signatureAlgorithm = String.format("%swith%s", hash, keyAlgorithm);
    return signatureAlgorithm;
  }

  private String formatHashAlgorithName(String hash) {
    return hash.replace("-", "");
  }

  private void signApkV1(File unSignedApk, File signedApk) throws IOException, InterruptedException {
    if (config.mUseSignAPK) {
      System.out.printf("signing apk: %s\n", signedApk.getName());
      if (signedApk.exists()) {
        signedApk.delete();
      }
      signWithV1sign(unSignedApk, signedApk);
      if (!signedApk.exists()) {
        throw new IOException("Can't Generate signed APK. Plz check your v1sign info is correct.");

View on GitHub (pinned to e4df245d82)