quarkusio/quarkus · error · IllegalArgumentException
Invalid public key
Error message
Invalid public key
What it means
During fromRequiredPersistedData, the stored X.509-encoded public key cannot be rebuilt: KeyFactory.generatePublic throws InvalidKeySpecException (corrupted/wrong-format key bytes or key does not match the algorithm) or NoSuchAlgorithmException (required KeyFactory, e.g. 'EdDSA', is unavailable). It is rethrown as IllegalArgumentException('Invalid public key').
Source
Thrown at extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnCredentialRecord.java:140
case EC2:
coseKey = EC2COSEKey.create((ECPublicKey) KeyFactory.getInstance("EC").generatePublic(x509EncodedKeySpec),
coseAlgorithm);
break;
case OKP:
coseKey = EdDSACOSEKey
.create((EdECPublicKey) KeyFactory.getInstance("EdDSA").generatePublic(x509EncodedKeySpec),
coseAlgorithm);
break;
case RSA:
coseKey = RSACOSEKey
.create((RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(x509EncodedKeySpec),
coseAlgorithm);
break;
default:
throw new IllegalArgumentException("Invalid cose algorithm: " + coseAlgorithm);
}
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
throw new IllegalArgumentException("Invalid public key", e);
}
byte[] credentialId = base64UrlDecode(persistedData.credentialId());
AAGUID aaguid = new AAGUID(persistedData.aaguid());
AttestedCredentialData attestedCredentialData = new AttestedCredentialData(aaguid, credentialId, coseKey);
return new WebAuthnCredentialRecord(persistedData.username(), counter, attestedCredentialData);
}
/**
* Record holding all the required persistent fields for logging back someone over WebAuthn.
*/
public record RequiredPersistedData(
/**
* The user name. A single user name may be associated with multiple WebAuthn credentials.
*/
String username,
/**
* The credential ID. This must be unique. See https://w3c.github.io/webauthn/#credential-idView on GitHub (pinned to e1c734241f)
Solutions
- Re-register the WebAuthn credential so a fresh valid public key is persisted.
- Verify publicKey is stored/loaded losslessly (BLOB/bytea, not a fixed-length string column) and the base64 encoding round-trips.
- For EdDSA credentials, run on JDK 15+ (or with an EdDSA JCA provider installed).
- Check the cause chain (getCause()) of the IllegalArgumentException to distinguish InvalidKeySpecException from NoSuchAlgorithmException.
Example fix
// before: storing key as VARCHAR(64) -> truncated @Column(length = 64) public String publicKey; // after: lossless storage @Column(columnDefinition = "bytea") public byte[] publicKey;
Defensive patterns
Strategy: try-catch
Validate before calling
// sanity-check before deserialization: non-empty, X.509 DER starts with 0x30
byte[] pk = persistedData.publicKey();
if (pk == null || pk.length == 0 || (pk[0] & 0xff) != 0x30)
throw new IllegalStateException("Persisted public key is missing or not X.509 encoded"); Try / catch
try {
record = WebAuthnCredentialRecord.fromRequiredPersistedData(persistedData);
} catch (IllegalArgumentException e) {
log.error("Stored public key unusable (cause: " + e.getCause() + "), re-registration required", e);
throw new WebAuthnCredentialStorageException(e);
} Prevention
- Store publicKey as a lossless binary column (BLOB/bytea), not a truncated VARCHAR.
- Run JDK 15+ (or install an EdDSA provider) for EdDSA/OKP credentials.
- Base64-url encode only for transport; decode fully before persisting.
- Inspect e.getCause() to distinguish key-format vs missing-algorithm problems.
When it happens
Trigger: Calling WebAuthnCredentialRecord.fromRequiredPersistedData with a RequiredPersistedData whose publicKey byte[] is corrupted, truncated, not a valid X.509 SubjectPublicKeyInfo, or whose algorithm requires an unavailable JCA provider (e.g. EdDSA on a JDK without Ed25519 support).
Common situations: Database blob/column mangled by manual edits or migration; key bytes re-encoded (e.g. base64 round trip done wrong) between persist and load; running EdDSA credentials (-8) on an old JDK (<15) lacking 'EdDSA' KeyFactory; byte[] truncated by a fixed-size column.
Related errors
- Invalid cose algorithm: ${coseAlgorithm}
- No datasource named '<dataSourceName>' exists
- 'public-key' property can only be used with the 'service' ap
- Not implemented yet
- Proxy configuration with name ${key} was requested but quark
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/40b19bbd27bc0507.
Report an issue: GitHub.