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

  1. Generate a fresh RSA (or other supported) key pair usable for encryption, e.g. `gpg --quick-generate-key "passbolt recovery" rsa3072 encr`
  2. Export and submit the public key in ASCII armor via armored_key with the matching fingerprint
  3. Check that the key is not revoked or expired before upload
  4. 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

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


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)