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
- Inspect the wrapped exception to see the gnupg import/encrypt failure reason.
- 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.
- Check server GnuPG health: writable homedir, sufficient keyring permissions, gpg binary working (gpg --version); clear stale keyring entries for that fingerprint and retry.
- 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
- Validate armored keys at registration and profile-update time with PublicKeyValidationService.
- Reject revoked/expired keys on upload so unusable keys never reach auth.
- After server migrations, warm the keyring or rely on import fallback; keep GNUPGHOME persistent.
- Alert on repeated import failures per user (indicates bad key data in DB).
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
- The OpenPGP server key defined in the config cannot be used…
- The user identifier should be a valid UUID.
- Could not import the user OpenPGP key.
- Could not import the user OpenPGP key.
- Could not use the key to encrypt.
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)