MuntashirAkon/AppManager · error · CryptoException

No KeyPair with alias ${RSA_KEY_ALIAS}

Error message

No KeyPair with alias ${RSA_KEY_ALIAS}

What it means

RSACrypto.decryptAesKey retrieves the RSA KeyPair under RSA_KEY_ALIAS from KeyStoreManager to unwrap the AES key. If no KeyPair exists under that alias (or KeyStoreManager throws), a CryptoException is raised and decryption cannot continue.

Source

Thrown at app/src/main/java/io/github/muntashirakon/AppManager/crypto/RSACrypto.java:60

    @NonNull
    static SecretKey generateAesKey() {
        SecureRandom random = new SecureRandom();
        byte[] key = new byte[AES_KEY_SIZE_BITS/8];
        random.nextBytes(key);
        return new SecretKeySpec(key, "AES");
    }

    @NonNull
    static SecretKey decryptAesKey(@NonNull byte[] encryptedAesKey) throws CryptoException {
        // We only have 32/64 bytes AES key with either 256 or 512 bytes minus 42 bytes of data,
        // so it should work without issues
        KeyPair keyPair;
        try {
            KeyStoreManager keyStoreManager = KeyStoreManager.getInstance();
            keyPair = keyStoreManager.getKeyPair(RSA_KEY_ALIAS);
            if (keyPair == null) {
                throw new CryptoException("No KeyPair with alias " + RSA_KEY_ALIAS);
            }
        } catch (Exception e) {
            throw new CryptoException(e);
        }
        try {
            Cipher cipher = Cipher.getInstance(RSA_CIPHER_TYPE);
            cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivateKey());
            return new SecretKeySpec(cipher.doFinal(encryptedAesKey), "AES");
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | BadPaddingException
                | IllegalBlockSizeException e) {
            throw new CryptoException(e);
        }
    }

    @NonNull
    static byte[] encryptAesKey(@NonNull SecretKey key) throws CryptoException {
        // We only have 32/64 bytes AES key with either 256 or 512 bytes minus 42 bytes of data,
        // so it should work without issues

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Generate the RSA key pair under RSA_KEY_ALIAS on this device before decrypting — if data came from elsewhere, use that original device
  2. Re-run encryption on this device after key generation so future decryptions work
  3. If the original keys are gone, the data is unrecoverable; restore from another backup source

Example fix

// before
SecretKey key = RSACrypto.decryptAesKey(encryptedKey); // throws: no RSA keypair
// after
if (KeyStoreManager.getInstance().getKeyPair(RSA_KEY_ALIAS) == null) {
    KeyStoreManager.getInstance().generateKeyPair(RSA_KEY_ALIAS); // then re-encrypt, old data is lost
}
SecretKey key = RSACrypto.decryptAesKey(encryptedKey);
Defensive patterns

Strategy: try-catch

Validate before calling

KeyPair kp = KeyStoreManager.getInstance().getKeyPair(RSA_KEY_ALIAS);
if (kp == null) {
    throw new IllegalStateException("RSA key pair missing; encrypted data cannot be decrypted on this device");
}

Try / catch

try {
    SecretKey key = RSACrypto.decryptAesKey(encryptedKey);
} catch (CryptoException e) {
    if (e.getMessage() != null && e.getMessage().contains("No KeyPair")) {
        // the data is from a different install; cannot decrypt here
    }
}

Prevention

When it happens

Trigger: Calling decryptAesKey (or decrypt via AESCrypto in RSA mode) when the AndroidKeyStore has no entry for RSA_KEY_ALIAS; or getKeyPair throws (keystore inaccessible).

Common situations: Decrypting on a device other than the one that encrypted (keystore keys are hardware-bound and non-exportable); app data cleared/reinstalled; restoring backups on a fresh device; Android version upgrade invalidating keystore entries.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12). Data as JSON: /api/errors/cc96c37dff504fb2. Report an issue: GitHub.