{"record":{"id":"e754f69f613be430","repo":"shwenzhang/AndResGuard","slug":"certificate-file-cert-must-be-specified","errorCode":null,"errorMessage":"Certificate file (--cert) must be specified","messagePattern":"Certificate file \\(--cert\\) must be specified","errorType":"validation","errorClass":"ParameterException","httpStatus":null,"severity":"error","filePath":"AndResGuard-core/src/main/java/apksigner/ApkSignerTool.java","lineNumber":782,"sourceCode":"                              + \". Wrong password?\", e);\n      }\n      this.privateKey = key;\n      Certificate[] certChain = ks.getCertificateChain(keyAlias);\n      if ((certChain == null) || (certChain.length == 0)) {\n        throw new ParameterException(keystoreFile + \" entry \\\"\" + keyAlias + \"\\\" does not contain certificates\");\n      }\n      this.certs = new ArrayList<>(certChain.length);\n      for (Certificate cert : certChain) {\n        this.certs.add((X509Certificate) cert);\n      }\n    }\n\n    private void loadPrivateKeyAndCertsFromFiles(PasswordRetriever passwordRetriver) throws Exception {\n      if (keyFile == null) {\n        throw new ParameterException(\"Private key file (--key) must be specified\");\n      }\n      if (certFile == null) {\n        throw new ParameterException(\"Certificate file (--cert) must be specified\");\n      }\n      byte[] privateKeyBlob = readFully(new File(keyFile));\n\n      PKCS8EncodedKeySpec keySpec;\n      // Potentially encrypted key blob\n      try {\n        EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = new EncryptedPrivateKeyInfo(privateKeyBlob);\n\n        // The blob is indeed an encrypted private key blob\n        String passwordSpec = (keyPasswordSpec != null) ? keyPasswordSpec : PasswordRetriever.SPEC_STDIN;\n        List<char[]> keyPasswords = passwordRetriver.getPasswords(passwordSpec, \"Private key password for \" + name);\n        keySpec = decryptPkcs8EncodedKey(encryptedPrivateKeyInfo, keyPasswords);\n      } catch (IOException e) {\n        // The blob is not an encrypted private key blob\n        if (keyPasswordSpec == null) {\n          // Given that no password was specified, assume the blob is an unencrypted\n          // private key blob\n          keySpec = new PKCS8EncodedKeySpec(privateKeyBlob);","sourceCodeStart":764,"sourceCodeEnd":800,"githubUrl":"https://github.com/shwenzhang/AndResGuard/blob/e4df245d82f27d9a2d0dd108260a3510cbaba849/AndResGuard-core/src/main/java/apksigner/ApkSignerTool.java#L764-L800","documentation":"This ParameterException is thrown by loadPrivateKeyAndCertsFromFiles when the certificate file path (--cert) was not provided. In file-based signing the X.509 certificate chain file is mandatory to embed the signer identity into the APK signature.","triggerScenarios":"Invoking file-based signing with --key supplied but no --cert; constructing SignerParams with keyFile set while certFile remains null.","commonSituations":"Scripts that pass the key path but forget the matching .pem/.crt; wrong assumption that the certificate is embedded in the .pk8 file (PKCS#8 keys contain no certificates); copying command lines from keystore-based examples.","solutions":["Pass the certificate: add --cert /path/to/cert.pem (or .crt/.der) matching the private key.","If the certificate does not exist yet, generate it: 'openssl req -x509 -key private_key.pem -out cert.pem'.","If you intended keystore signing, switch to --ks <keystore> where the cert chain lives inside the keystore."],"exampleFix":"// before\napksigner sign --key private_key.pk8 --out signed.apk unsigned.apk\n// after\napksigner sign --key private_key.pk8 --cert cert.pem --out signed.apk unsigned.apk","handlingStrategy":"validation","validationCode":"File certFile = new File(certPath);\nif (certPath == null || certPath.isEmpty() || !certFile.isFile()) {\n  throw new IllegalArgumentException(\"--cert must point to an existing X.509 certificate file\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  signerParams.loadPrivateKeyAndCerts(passwordRetriever);\n} catch (ParameterException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"--cert) must be specified\")) {\n    throw new IllegalArgumentException(\"Provide --cert <certificate file> alongside --key for file-based signing\", e);\n  } throw e;\n}","preventionTips":["Always pass --key and --cert together; wrap them in a single script function.","Remember PKCS#8 .pk8 files do not embed certificates - keep the .pem/.crt next to the key.","Validate that cert and key match (compare public keys) before signing."],"tags":["signing","cli-argument","missing-argument","android"],"backgroundTag":"missing-required-argument","analyzedSha":"e4df245d82f27d9a2d0dd108260a3510cbaba849","analyzedAt":"2026-09-12T17:49:07.798Z","contentChangedAt":"2026-09-12T17:49:07.798Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}