{"record":{"id":"cc96c37dff504fb2","repo":"MuntashirAkon/AppManager","slug":"no-keypair-with-alias-rsa-key-alias","errorCode":null,"errorMessage":"No KeyPair with alias ${RSA_KEY_ALIAS}","messagePattern":"No KeyPair with alias (.+?)","errorType":"exception","errorClass":"CryptoException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/crypto/RSACrypto.java","lineNumber":60,"sourceCode":"\n    @NonNull\n    static SecretKey generateAesKey() {\n        SecureRandom random = new SecureRandom();\n        byte[] key = new byte[AES_KEY_SIZE_BITS/8];\n        random.nextBytes(key);\n        return new SecretKeySpec(key, \"AES\");\n    }\n\n    @NonNull\n    static SecretKey decryptAesKey(@NonNull byte[] encryptedAesKey) throws CryptoException {\n        // We only have 32/64 bytes AES key with either 256 or 512 bytes minus 42 bytes of data,\n        // so it should work without issues\n        KeyPair keyPair;\n        try {\n            KeyStoreManager keyStoreManager = KeyStoreManager.getInstance();\n            keyPair = keyStoreManager.getKeyPair(RSA_KEY_ALIAS);\n            if (keyPair == null) {\n                throw new CryptoException(\"No KeyPair with alias \" + RSA_KEY_ALIAS);\n            }\n        } catch (Exception e) {\n            throw new CryptoException(e);\n        }\n        try {\n            Cipher cipher = Cipher.getInstance(RSA_CIPHER_TYPE);\n            cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivateKey());\n            return new SecretKeySpec(cipher.doFinal(encryptedAesKey), \"AES\");\n        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | BadPaddingException\n                | IllegalBlockSizeException e) {\n            throw new CryptoException(e);\n        }\n    }\n\n    @NonNull\n    static byte[] encryptAesKey(@NonNull SecretKey key) throws CryptoException {\n        // We only have 32/64 bytes AES key with either 256 or 512 bytes minus 42 bytes of data,\n        // so it should work without issues","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/crypto/RSACrypto.java#L42-L78","documentation":"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.","triggerScenarios":"Calling decryptAesKey (or decrypt via AESCrypto in RSA mode) when the AndroidKeyStore has no entry for RSA_KEY_ALIAS; or getKeyPair throws (keystore inaccessible).","commonSituations":"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.","solutions":["Generate the RSA key pair under RSA_KEY_ALIAS on this device before decrypting — if data came from elsewhere, use that original device","Re-run encryption on this device after key generation so future decryptions work","If the original keys are gone, the data is unrecoverable; restore from another backup source"],"exampleFix":"// before\nSecretKey key = RSACrypto.decryptAesKey(encryptedKey); // throws: no RSA keypair\n// after\nif (KeyStoreManager.getInstance().getKeyPair(RSA_KEY_ALIAS) == null) {\n    KeyStoreManager.getInstance().generateKeyPair(RSA_KEY_ALIAS); // then re-encrypt, old data is lost\n}\nSecretKey key = RSACrypto.decryptAesKey(encryptedKey);","handlingStrategy":"try-catch","validationCode":"KeyPair kp = KeyStoreManager.getInstance().getKeyPair(RSA_KEY_ALIAS);\nif (kp == null) {\n    throw new IllegalStateException(\"RSA key pair missing; encrypted data cannot be decrypted on this device\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    SecretKey key = RSACrypto.decryptAesKey(encryptedKey);\n} catch (CryptoException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"No KeyPair\")) {\n        // the data is from a different install; cannot decrypt here\n    }\n}","preventionTips":["Encrypt and decrypt on the same device/install — AndroidKeyStore keys are non-exportable","Generate RSA keys before any encryption flow","Detect key absence early and disable decryption UI"],"tags":["crypto","android","keystore","rsa","missing-key"],"backgroundTag":"resource-not-found","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}