{"record":{"id":"9d15913b7111271c","repo":"MuntashirAkon/AppManager","slug":"stream-does-not-appear-to-be-a-properly-formatted-rsa-key","errorCode":null,"errorMessage":"Stream does not appear to be a properly formatted RSA key.","messagePattern":"Stream does not appear to be a properly formatted RSA key\\.","errorType":"exception","errorClass":"InvalidKeyException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/crypto/ks/KeyStoreUtils.java","lineNumber":256,"sourceCode":"            if (base64EncodedKey.length() == 0) {\n                throw new IOException(\"Stream does not contain an unencrypted private key.\");\n            }\n\n            BASE64Decoder decoder = new BASE64Decoder();\n            byte[] bytes = decoder.decodeBuffer(base64EncodedKey.toString());\n\n            KeyFactory kf;\n            KeySpec spec;\n            if (pkcs8Format) {\n                kf = KeyFactory.getInstance(\"RSA\");\n                spec = new PKCS8EncodedKeySpec(bytes);\n            } else if (rsaFormat) {\n                // PKCS#1 format\n                kf = KeyFactory.getInstance(\"RSA\");\n                List<BigInteger> rsaIntegers = new ArrayList<>();\n                ASN1Parse(bytes, rsaIntegers);\n                if (rsaIntegers.size() < 8) {\n                    throw new InvalidKeyException(\"Stream does not appear to be a properly formatted RSA key.\");\n                }\n                BigInteger publicExponent = rsaIntegers.get(2);\n                BigInteger privateExponent = rsaIntegers.get(3);\n                BigInteger modulus = rsaIntegers.get(1);\n                BigInteger primeP = rsaIntegers.get(4);\n                BigInteger primeQ = rsaIntegers.get(5);\n                BigInteger primeExponentP = rsaIntegers.get(6);\n                BigInteger primeExponentQ = rsaIntegers.get(7);\n                BigInteger crtCoefficient = rsaIntegers.get(8);\n                //spec = new RSAPrivateKeySpec(modulus, privateExponent);\n                spec = new RSAPrivateCrtKeySpec(modulus, publicExponent, privateExponent,\n                        primeP, primeQ, primeExponentP, primeExponentQ, crtCoefficient);\n            } else if (dsaFormat) {\n                kf = KeyFactory.getInstance(\"DSA\");\n                List<BigInteger> dsaIntegers = new ArrayList<>();\n                ASN1Parse(bytes, dsaIntegers);\n                if (dsaIntegers.size() < 5) {\n                    throw new InvalidKeyException(\"Stream does not appear to be a properly formatted DSA key\");","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/crypto/ks/KeyStoreUtils.java#L238-L274","documentation":"generatePrivateKey recognized PKCS#1 \"RSA PRIVATE KEY\" format and ASN.1-parsed the bytes, but fewer than 8 integers were recovered (an RSA private key needs version, modulus, public/private exponents, primes, exponents, coefficient), so it throws InvalidKeyException \"Stream does not appear to be a properly formatted RSA key.\"","triggerScenarios":"Calling generatePrivateKey with data whose RSA PKCS#1 ASN.1 structure is truncated, malformed, or not actually an RSA key — e.g. an EC or DSA key mislabeled as RSA, or corrupted base64 decoding.","commonSituations":"Truncated key file from a bad copy/paste; key file with wrong extension fed as RSA; OpenSSH-format keys (openssh-key-v1) instead of PKCS#1 PEM; line-wrapping corruption stripping base64 characters.","solutions":["Validate the key: openssl rsa -in key.pem -check -noout; regenerate/export the key if corrupt.","Convert the key to proper PKCS#8/PKCS#1 PEM: openssl pkcs8 -topk8 -nocrypt -in key.pem -out key_pkcs8.pem.","Ensure the file is complete and unmodified — re-copy without altering whitespace/line breaks.","If the key is OpenSSH format, convert it: ssh-keygen -p -m PEM -f key."],"exampleFix":"// before\nPrivateKey pk = KeyStoreUtils.generatePrivateKey(cr.openInputStream(id_rsa_openssh_uri));\n// after\n// convert first: ssh-keygen -p -m PEM -f id_rsa\nPrivateKey pk = KeyStoreUtils.generatePrivateKey(cr.openInputStream(id_rsa_pem_uri));","handlingStrategy":"validation","validationCode":"// verify the RSA key parses correctly (e.g. via openssl in the export pipeline) and file is complete\nString pem = readAll(is);\nif (!pem.contains(\"-----BEGIN RSA PRIVATE KEY-----\")) {\n    throw new IllegalArgumentException(\"Expected PKCS#1 RSA PEM input\");\n}\nif (pem.replace(\"\\n\", \"\").length() < 800) { // rough sanity size for 2048-bit RSA\n    throw new IllegalArgumentException(\"Key file looks truncated\");\n}","typeGuard":null,"tryCatchPattern":"// try\ntry {\n    PrivateKey pk = KeyStoreUtils.generatePrivateKey(rsaKeyIs);\n} catch (InvalidKeyException e) {\n    if (e.getMessage().contains(\"properly formatted RSA key\")) {\n        // corrupt or wrong-format key: re-export via openssl and retry once\n        retryWithReExportedKey();\n    }\n}","preventionTips":["Validate keys with `openssl rsa -check` before importing.","Convert OpenSSH-format keys with `ssh-keygen -p -m PEM` — the new OpenSSH format isn't PKCS#1.","Copy key files intact — avoid paste/edit operations that drop base64 lines or whitespace.","Match the key type to its header (RSA content under BEGIN RSA PRIVATE KEY)."],"tags":["keystore","rsa","asn1","invalid-key"],"backgroundTag":"invalid-argument-format","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"}