{"record":{"id":"a018c1574afb65b3","repo":"MuntashirAkon/AppManager","slug":"stream-does-not-appear-to-be-a-properly-formatted-dsa-key","errorCode":null,"errorMessage":"Stream does not appear to be a properly formatted DSA key","messagePattern":"Stream does not appear to be a properly formatted DSA key","errorType":"exception","errorClass":"InvalidKeyException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/crypto/ks/KeyStoreUtils.java","lineNumber":274,"sourceCode":"                    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\");\n                }\n                BigInteger privateExponent = dsaIntegers.get(1);\n                BigInteger publicExponent = dsaIntegers.get(2);\n                BigInteger P = dsaIntegers.get(3);\n                BigInteger Q = dsaIntegers.get(4);\n                BigInteger G = dsaIntegers.get(5);\n                spec = new DSAPrivateKeySpec(privateExponent, P, Q, G);\n            } else {\n                throw new NoSuchAlgorithmException(\"Couldn't find any suitable algorithm\");\n            }\n            return kf.generatePrivate(spec);\n        }\n    }\n\n    public static byte[] getPemCertificate(@NonNull Certificate certificate)\n            throws CertificateEncodingException, IOException {\n        BASE64Encoder encoder = new BASE64Encoder();\n        try (ByteArrayOutputStream os = new ByteArrayOutputStream(X509Factory.BEGIN_CERT.length() +","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/crypto/ks/KeyStoreUtils.java#L256-L292","documentation":"generatePrivateKey recognized DSA format and ASN.1-parsed the key, but fewer than 5 integers were recovered (a DSA private key needs version, x, p, q, g), so it throws InvalidKeyException \"Stream does not appear to be a properly formatted DSA key\".","triggerScenarios":"Calling generatePrivateKey with truncated/malformed DSA ASN.1 data, or a non-DSA key (RSA/EC) routed into the DSA parsing branch, or corrupted base64 decoding of the DER body.","commonSituations":"Corrupted or truncated DSA key export; wrong header markers (e.g. BEGIN DSA PRIVATE KEY containing RSA content); copy/paste losing base64 lines; obsolete DSA keys rejected by newer openssl exports.","solutions":["Validate the key: openssl dsa -in dsa.pem -check -noout; re-export if corrupt.","Convert to PKCS#8 PEM so the RSA/PKCS#8 path handles it: openssl pkcs8 -topk8 -nocrypt -in dsa.pem -out dsa_pkcs8.pem.","Confirm the file actually contains a DSA key (openssl pkey -in key.pem -text -noout) and matches its header.","Re-copy the key file without line-wrapping or whitespace corruption."],"exampleFix":"// before\nPrivateKey pk = KeyStoreUtils.generatePrivateKey(cr.openInputStream(truncatedDsaKeyUri));\n// after\n// validate/regenerate first: openssl dsa -in dsa.pem -check -noout\nPrivateKey pk = KeyStoreUtils.generatePrivateKey(cr.openInputStream(validDsaKeyUri));","handlingStrategy":"validation","validationCode":"// confirm DSA content matches the DSA header before parsing\nString pem = readAll(is);\nif (!pem.contains(\"-----BEGIN DSA PRIVATE KEY-----\")) {\n    throw new IllegalArgumentException(\"Expected DSA PEM input\");\n}\n// validate with: openssl dsa -in dsa.pem -check -noout  (must succeed)","typeGuard":null,"tryCatchPattern":"// try\ntry {\n    PrivateKey pk = KeyStoreUtils.generatePrivateKey(dsaKeyIs);\n} catch (InvalidKeyException e) {\n    if (e.getMessage().contains(\"properly formatted DSA key\")) {\n        // truncated/mislabeled DSA data: re-export the key and retry\n        retryWithReExportedKey();\n    }\n}","preventionTips":["Validate DSA keys with `openssl dsa -check` before import.","Re-export DSA keys to a fresh PEM rather than editing/copying by hand.","Ensure the DER body is intact — truncation is the main cause of <5 parsed integers.","Consider converting to PKCS#8 PEM to use the more robust generic path."],"tags":["keystore","dsa","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"}