shwenzhang/AndResGuard · error · ParameterException
Certificate file (--cert) must be specified
Error message
Certificate file (--cert) must be specified
What it means
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.
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.
Example fix
// before apksigner sign --key private_key.pk8 --out signed.apk unsigned.apk // after apksigner sign --key private_key.pk8 --cert cert.pem --out signed.apk unsigned.apk
Defensive patterns
Strategy: validation
Validate before calling
File certFile = new File(certPath);
if (certPath == null || certPath.isEmpty() || !certFile.isFile()) {
throw new IllegalArgumentException("--cert must point to an existing X.509 certificate file");
} Try / catch
try {
signerParams.loadPrivateKeyAndCerts(passwordRetriever);
} catch (ParameterException e) {
if (e.getMessage() != null && e.getMessage().contains("--cert) must be specified")) {
throw new IllegalArgumentException("Provide --cert <certificate file> alongside --key for file-based signing", e);
} throw e;
} Prevention
- 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.
When it happens
Trigger: Invoking file-based signing with --key supplied but no --cert; constructing SignerParams with keyFile set while certFile remains null.
Common situations: 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.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Private key file (--key) must be specified
- At least one signer must be specified
- Failed to obtain key with alias
- entry " " does not contain certificates
- Failed to parse encrypted private key blob
AI-assisted analysis of shwenzhang/AndResGuard@e4df245d82 (2026-09-12).
Data as JSON: /api/errors/e754f69f613be430.
Report an issue: GitHub.
Appendix: source
Thrown at AndResGuard-core/src/main/java/apksigner/ApkSignerTool.java:782
+ ". Wrong password?", e);
}
this.privateKey = key;
Certificate[] certChain = ks.getCertificateChain(keyAlias);
if ((certChain == null) || (certChain.length == 0)) {
throw new ParameterException(keystoreFile + " entry \"" + keyAlias + "\" does not contain certificates");
}
this.certs = new ArrayList<>(certChain.length);
for (Certificate cert : certChain) {
this.certs.add((X509Certificate) cert);
}
}
private void loadPrivateKeyAndCertsFromFiles(PasswordRetriever passwordRetriver) throws Exception {
if (keyFile == null) {
throw new ParameterException("Private key file (--key) must be specified");
}
if (certFile == null) {
throw new ParameterException("Certificate file (--cert) must be specified");
}
byte[] privateKeyBlob = readFully(new File(keyFile));
PKCS8EncodedKeySpec keySpec;
// Potentially encrypted key blob
try {
EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = new EncryptedPrivateKeyInfo(privateKeyBlob);
// The blob is indeed an encrypted private key blob
String passwordSpec = (keyPasswordSpec != null) ? keyPasswordSpec : PasswordRetriever.SPEC_STDIN;
List<char[]> keyPasswords = passwordRetriver.getPasswords(passwordSpec, "Private key password for " + name);
keySpec = decryptPkcs8EncodedKey(encryptedPrivateKeyInfo, keyPasswords);
} catch (IOException e) {
// The blob is not an encrypted private key blob
if (keyPasswordSpec == null) {
// Given that no password was specified, assume the blob is an unencrypted
// private key blob
keySpec = new PKCS8EncodedKeySpec(privateKeyBlob);View on GitHub (pinned to e4df245d82)