passbolt/passbolt_api · error · CustomValidationException
The OpenPGP key can not be used to encrypt.
Error message
The OpenPGP key can not be used to encrypt.
What it means
Thrown in buildPublicKeyEntityFromDataOrFail when the submitted OpenPGP public key passes armor parsing but PublicKeyCanEncryptCheckService determines it cannot actually be used for encryption (e.g. key usage flags or algorithm/capability problems). It is immediately re-wrapped as 'Could not validate policy data.' with a canEncrypt error on armored_key.
Solutions
- Generate a fresh RSA (or other supported) key pair usable for encryption, e.g. `gpg --quick-generate-key "passbolt recovery" rsa3072 encr`
- Export and submit the public key in ASCII armor via armored_key with the matching fingerprint
- Check that the key is not revoked or expired before upload
- Look at the wrapped 'Could not validate policy data.' errors for the canEncrypt entry confirming the diagnosis
Example fix
// before gpg --quick-generate-key "recovery" rsa3072 sign // sign-only // after gpg --quick-generate-key "recovery" rsa3072 encr // encryption-capable
Defensive patterns
Strategy: validation
Validate before calling
// Pre-check the key is encryption-capable before upload
import { readKey } from 'openpgp';
const key = await readKey({ armoredKey: armored_key });
const canEncrypt = await key.getEncryptionKey();
if (!canEncrypt) throw new Error('Key cannot encrypt'); Type guard
function isEncryptCapableKeyPacket(key) {
return key && typeof key.getEncryptionKey === 'function' && !key.isRevoked();
} Try / catch
try {
await api.setOrganizationPolicy({policy, armored_key, fingerprint});
} catch (e) {
if (e.body?.errors?.account_recovery_organization_public_key?.armored_key?.canEncrypt) {
// regenerate an encryption-capable key and retry
}
} Prevention
- Generate organization keys explicitly with encryption usage (e.g. `gpg --quick-generate-key name rsa3072 encr`)
- Never reuse a signing-only key for the recovery organization key
- Check key is not expired/revoked before uploading
When it happens
Trigger: Enabling or setting account recovery organization policy (POST /account-recovery/organization-policies) with an organization public key that is valid armor but not encryption-capable — e.g. a sign-only key, a revoked key, or a key with unsuitable cipher support.
Common situations: Admin uploads a dedicated signing key instead of an encryption key; key generated with usage restrictions; old GnuPG key formats; key whose subkeys lack encryption capability while the primary key is sign-only.
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
- Could not save the account recovery private key.
- Could not validate key revocation.
- Could not validate metadata key data.
- Could not validate policy data.
- Could not validate public key data.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/6c57a564e3acaa52.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/AccountRecovery/src/Service/AccountRecoveryOrganizationPolicies/AbstractAccountRecoveryOrganizationPolicySetService.php:271
public function buildPublicKeyEntityFromDataOrFail(UserAccessControl $uac): AccountRecoveryOrganizationPublicKey
{
try {
$data = $this->getData('account_recovery_organization_public_key');
$entity = $this->AccountRecoveryOrganizationPublicKeys->buildAndValidateEntity($uac, $data);
// Check key can be parsed
PublicKeyValidationService::parseAndValidatePublicKey(
$entity->armored_key,
PublicKeyValidationService::getStrictRules()
);
// Prevent key reuse
$this->assertPublicKeyModelRules($entity);
// Make sure key can be used to encrypt - ref. PBL-07-002
if (!PublicKeyCanEncryptCheckService::check($entity->armored_key, $entity->fingerprint)) {
$msg = __('The OpenPGP key can not be used to encrypt.');
throw new CustomValidationException($msg, ['armored_key' => ['canEncrypt' => $msg]]);
}
} catch (ValidationException | CustomValidationException $exception) {
throw new CustomValidationException(__('Could not validate policy data.'), [
'account_recovery_organization_public_key' => $exception->getErrors(),
]);
} catch (Exception $exception) {
throw new CustomValidationException(__('Could not validate policy data.'), [
'account_recovery_organization_public_key' => [
'armored_key' => [
'invalidArmoredKey' => $exception->getMessage(),
],
],
]);
}
return $entity;
}
View on GitHub (pinned to 31c1bbc10f)