passbolt/passbolt_api · error · InternalErrorException

Could not import the user OpenPGP key.

Error message

Could not import the user OpenPGP key.

What it means

Thrown by GpgAuthenticator::_initUserKey() when the client's OpenPGP public key cannot be loaded into the server keyring for encryption. setEncryptKeyFromFingerprint() failed, and the fallback re-import of the user's armored key from the database (user.gpgkey.armored_key) also failed. Reported as InternalErrorException (HTTP 500) with the underlying exception attached.

Solutions

  1. Inspect the wrapped exception to see the gnupg import/encrypt failure reason.
  2. Ask the user to re-upload/re-register a valid, unrevoked OpenPGP key; verify the armored_key column contains a full '-----BEGIN PGP PUBLIC KEY BLOCK-----' blob.
  3. Check server GnuPG health: writable homedir, sufficient keyring permissions, gpg binary working (gpg --version); clear stale keyring entries for that fingerprint and retry.
  4. If the key is revoked/expired in the DB, remove it and let the user re-register or update the key via the profile UI.

Example fix

// before: trusting whatever armored key is stored
$this->_gpg->importKeyIntoKeyring($this->_user->gpgkey->armored_key);

// after: validate the armored key before import
if (!PublicKeyValidationService::isValidArmoredKey($this->_user->gpgkey->armored_key)) {
    throw new BadRequestException(__('The user OpenPGP key is invalid.'));
}
$this->_gpg->importKeyIntoKeyring($this->_user->gpgkey->armored_key);
Defensive patterns

Strategy: try-catch

Validate before calling

if (!PublicKeyValidationService::isValidArmoredKey($user->gpgkey->armored_key)) {
    // reject at registration/upload time, before auth needs to encrypt to it
}

Type guard

function hasUsableArmoredKey(?User $user): bool {
    return $user !== null
        && $user->gpgkey !== null
        && is_string($user->gpgkey->armored_key)
        && str_contains($user->gpgkey->armored_key, 'BEGIN PGP PUBLIC KEY BLOCK');
}

Try / catch

try {
    $gpg->importKeyIntoKeyring($armoredKey);
    $gpg->setEncryptKeyFromFingerprint($fingerprint);
} catch (Exception $e) {
    // surface 500, log $e, prompt user to re-upload a valid key
}

Prevention

When it happens

Trigger: During GPGAuth stage1, when encrypting the server verify token to the user's key fails because the key is not in the keyring, and importKeyIntoKeyring($this->_user->gpgkey->armored_key) throws (malformed armored key, revoked/expired key material stored in DB, gnupg import error).

Common situations: User registered with a corrupted or non-armored key blob in the gpgkeys table; key revoked or with unusable subkeys after a version change; GnuPG keyring on the server full/broken or homedir permissions wrong so imports silently fail; old keys imported under a different homedir after server migration.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/af8c845acdddcff3. Report an issue: GitHub.

Appendix: source

Thrown at src/Authenticator/GpgAuthenticator.php:372

    /**
     * Set user key for encryption and import it in the keyring if needed
     *
     * @param string $fingerprint fingerprint
     * @throws \Cake\Http\Exception\InternalErrorException when the key is not valid
     * @return void
     */
    private function _initUserKey(string $fingerprint): void
    {
        try {
            $this->_gpg->setEncryptKeyFromFingerprint($fingerprint);
        } catch (Exception $exception) {
            // Try to import the key in keyring again
            try {
                $this->_gpg->importKeyIntoKeyring($this->_user->gpgkey->armored_key);
                $this->_gpg->setEncryptKeyFromFingerprint($fingerprint);
            } catch (Exception $exception) {
                $msg = __('Could not import the user OpenPGP key.');
                throw new InternalErrorException($msg, 500, $exception);
            }
        }
    }

    /**
     * Find a user record from a public key fingerprint
     *
     * @return \App\Model\Entity\User|null
     */
    private function _identifyUserWithFingerprint(): ?User
    {
        // First we check if we can get the user with the key fingerprint
        if (!isset($this->_data['keyid']) || !is_string($this->_data['keyid'])) {
            $this->_debug('No key id set.');

            return null;
        }

View on GitHub (pinned to 31c1bbc10f)