shwenzhang/AndResGuard · error · ParameterException
Keystore Provider class
Error message
Keystore Provider class <keystoreProviderClass> not subclass of java.security.Provider
What it means
When --ks-provider-class is given, ApkSignerTool loads the class reflectively and verifies it extends java.security.Provider. If the named class is not a Provider subclass it throws this ParameterException, since only a Provider can back KeyStore.getInstance(ksType, provider).
Solutions
- Pass the actual JCE Provider class, e.g. --ks-provider-class org.bouncycastle.jce.provider.BouncyCastleProvider.
- Check the provider jar's documentation for the class that extends java.security.Provider.
- If the provider is already installed in the JVM, drop --ks-provider-class and use --ks-provider-name instead.
- Ensure the provider jar is on the classpath and Class.forName resolves the intended class.
Example fix
// before --ks-provider-class org.bouncycastle.jce.BouncyCastle // after --ks-provider-class org.bouncycastle.jce.provider.BouncyCastleProvider
Defensive patterns
Strategy: validation
Validate before calling
// Java pre-check
Class<?> c = Class.forName(providerClassName);
if (!java.security.Provider.class.isAssignableFrom(c)) {
throw new IllegalArgumentException(providerClassName + " is not a java.security.Provider");
} Type guard
boolean isJceProvider(String name) {
try { return java.security.Provider.class.isAssignableFrom(Class.forName(name)); }
catch (ClassNotFoundException e) { return false; }
} Prevention
- Copy the provider class FQN from the provider jar's docs/services file, not from memory.
- Test the sign command once locally with the same provider flags used in CI.
- Prefer --ks-provider-name when the provider is already installed in the JVM.
When it happens
Trigger: Passing --ks-provider-class pointing to a class that exists but does not extend java.security.Provider (e.g. a JCE provider's factory/helper class, or a typo to a random class in the classpath).
Common situations: Using Bouncy Castle or a hardware-security provider and naming the wrong entry class; class loaded from an unrelated jar with the same package name; provider shipped in an old jar whose classes were repackaged.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Missing APK
- Unexpected parameter(s) after APK (<params[1]>)
- --ks and --key may not be specified at the same time
- --ks and --cert may not be specified at the same time
- KeyStore (--ks) or private key file (--key) must be…
AI-assisted analysis of shwenzhang/AndResGuard@e4df245d82 (2026-09-12).
Data as JSON: /api/errors/3631c0ec34b82205.
Report an issue: GitHub.
Appendix: source
Thrown at AndResGuard-core/src/main/java/apksigner/ApkSignerTool.java:661
}
}
private void loadPrivateKeyAndCertsFromKeyStore(PasswordRetriever passwordRetriever) throws Exception {
if (keystoreFile == null) {
throw new ParameterException("KeyStore (--ks) must be specified");
}
// 1. Obtain a KeyStore implementation
String ksType = (keystoreType != null) ? keystoreType : KeyStore.getDefaultType();
KeyStore ks;
if (keystoreProviderName != null) {
// Use a named Provider (assumes the provider is already installed)
ks = KeyStore.getInstance(ksType, keystoreProviderName);
} else if (keystoreProviderClass != null) {
// Use a new Provider instance (does not require the provider to be installed)
Class<?> ksProviderClass = Class.forName(keystoreProviderClass);
if (!Provider.class.isAssignableFrom(ksProviderClass)) {
throw new ParameterException("Keystore Provider class "
+ keystoreProviderClass
+ " not subclass of "
+ Provider.class.getName());
}
Provider ksProvider;
if (keystoreProviderArg != null) {
// Single-arg Provider constructor
ksProvider = (Provider) ksProviderClass.getConstructor(String.class).newInstance(keystoreProviderArg);
} else {
// No-arg Provider constructor
ksProvider = (Provider) ksProviderClass.getConstructor().newInstance();
}
ks = KeyStore.getInstance(ksType, ksProvider);
} else {
// Use the highest-priority Provider which offers the requested KeyStore type
ks = KeyStore.getInstance(ksType);
}
View on GitHub (pinned to e4df245d82)