GPG can decrypt, cannot verify

Checklist
[x] I have read intro post: About the Installation Issues category
[x] I have read the tutorials, help and searched for similar issues
[x] I provide relevant information about my server (component names and versions, etc.)
[x] I provide a copy of my logs and healthcheck
[x] I describe the steps I have taken to trouble shoot the problem
[ ] I describe the steps on how to reproduce the issue

I’ve installed Passbolt inside a FreeBSD 12.2 jail following the from-source instructions. After getting nginx and fpm configured, I can go through the process of creating the first user, but actually logging in fails with a 500 server error (exact message and server log below). Running healthcheck highlights three errors: that the server does not have https enabled (correct, I’ll do that once I can confirm it’s otherwise working), and that while the server keys can be used to encrypt and decrypt messages, they cannot be used to verify signatures. Could this verify error and the 500 server error be related?

The server key and subkey are both RSA (Passkey doesn’t support EDDSA, the default on this system), they’re owned by the nginx user (www), and I’ve verified they work for encryption and signing at the CLI. I’ve tried installing the pecl gnupg package via pecl instead of via the system package manager (suggested by eddie4 in '18), but that had no effect. I’ve also searched the forum here, but most of the relevant threads have issues with both decryption and verification.

Is there any way to get more detailed information out of the healthcheck shell? The --verbose flag doesn’t seem to have any effect.

versions:

FreeBSD 12.2 (FreeNAS), iocage jail
nginx/1.20.1
mysql  Ver 15.1 Distrib 10.5.13-MariaDB
PHP 7.4.26
Passbolt 3.4.0-2 (commit 98397bba)
gpg (GnuPG) 2.3.2
libgcrypt 1.9.4

./bin/cake passbolt healthcheck

     ____                  __          ____  
    / __ \____  _____ ____/ /_  ____  / / /_ 
   / /_/ / __ `/ ___/ ___/ __ \/ __ \/ / __/ 
  / ____/ /_/ (__  |__  ) /_/ / /_/ / / /    
 /_/    \__,_/____/____/_.___/\____/_/\__/   

 Open source password manager for teams
-------------------------------------------------------------------------------
 Healthcheck shell        
-------------------------------------------------------------------------------

 Environment

 [PASS] PHP version 7.4.26.
 [PASS] PCRE compiled with unicode support.
 [PASS] The temporary directory and its content are writable and not executable.
 [PASS] The logs directory and its content are writable.
 [PASS] GD or Imagick extension is installed.
 [PASS] Intl extension is installed.
 [PASS] Mbstring extension is installed.

 Config files

 [PASS] The application config file is present
 [PASS] The passbolt config file is present

 Core config

 [PASS] Debug mode is off.
 [PASS] Cache is working.
 [PASS] Unique value set for security.salt
 [PASS] Full base url is set to http://passbolt.thescrapyard.org
 [PASS] App.fullBaseUrl validation OK.
 [PASS] /healthcheck/status is reachable.

 SSL Certificate

 [PASS] SSL peer certificate validates
 [PASS] Hostname is matching in SSL certificate.
 [PASS] Not using a self-signed certificate

 Database

 [PASS] The application is able to connect to the database
 [PASS] 26 tables found
 [PASS] Some default content is present
 [PASS] The database schema up to date.

 GPG Configuration

 [PASS] PHP GPG Module is installed and loaded.
 [PASS] The environment variable GNUPGHOME is set to /home/www/.gnupg.
 [PASS] The directory /home/www/.gnupg containing the keyring is writable by the webserver user.
 [PASS] The server OpenPGP key is not the default one
 [PASS] The public key file is defined in config/passbolt.php and readable.
 [PASS] The private key file is defined in config/passbolt.php and readable.
 [PASS] The server key fingerprint matches the one defined in config/passbolt.php.
 [PASS] The server public key defined in the config/passbolt.php (or environment variables) is in the keyring.
 [PASS] There is a valid email id defined for the server key.
 [PASS] The public key can be used to encrypt a message.
 [PASS] The private key can be used to sign a message.
 [PASS] The public and private keys can be used to encrypt and sign a message.
 [PASS] The private key can be used to decrypt a message.
 [FAIL] The private key cannot be used to decrypt and verify a message
 [FAIL] The public key cannot be used to verify a signature.

 Application configuration

 [PASS] Using latest passbolt version (3.4.0).
 [PASS] Passbolt is configured to force SSL use.
 [FAIL] App.fullBaseUrl is not set to HTTPS.
 [HELP] Check App.fullBaseUrl url scheme in config/passbolt.php.
 [PASS] Selenium API endpoints are disabled.
 [PASS] Search engine robots are told not to index content.
 [PASS] Registration is closed, only administrators can add users.
 [PASS] Serving the compiled version of the javascript app
 [PASS] All email notifications will be sent.

 JWT Authentication

 [WARN] The JWT Authentication plugin is disabled
 [HELP] Set the environment variable PASSBOLT_PLUGINS_JWT_AUTHENTICATION_ENABLED to true

 [FAIL] 3 error(s) found. Hang in there!

login error:

Sorry, you have not been signed in.

Something went wrong, the sign in failed with the following error:

There was a server error. No additional information provided(500

nginx access.log below, with no errors present in error.log.

[05/Jan/2022:16:42:39 -0800] "GET /settings.json?api-version=v2 HTTP/1.1" 200
[05/Jan/2022:16:42:40 -0800] "GET /auth/verify.json?api-version=v2 HTTP/1.1" 200
[05/Jan/2022:16:42:40 -0800] "GET /setup/install/<snip>.json?api-version=v2 HTTP/1.1" 400
[05/Jan/2022:16:42:42 -0800] "GET /setup/install/<snip>?locale=en-UK HTTP/1.1" 200
[05/Jan/2022:16:42:42 -0800] "GET /js/app/stylesheet.js?v=3.4.0 HTTP/1.1" 304
[05/Jan/2022:16:42:42 -0800] "GET /js/app/api-setup.js?v=3.4.0 HTTP/1.1" 304
[05/Jan/2022:16:42:42 -0800] "GET /js/app/api-vendors.js?v=3.4.0 HTTP/1.1" 304
[05/Jan/2022:16:42:42 -0800] "GET /settings.json?api-version=v2 HTTP/1.1" 200
[05/Jan/2022:16:42:42 -0800] "GET /settings.json?api-version=v2 HTTP/1.1" 200
[05/Jan/2022:16:42:42 -0800] "GET /auth/verify.json?api-version=v2 HTTP/1.1" 200
[05/Jan/2022:16:42:42 -0800] "GET /setup/install/<snip>.json?api-version=v2 HTTP/1.1" 400
[05/Jan/2022:16:42:43 -0800] "GET /setup/install/<snip>.json?api-version=v2 HTTP/1.1" 400
[05/Jan/2022:16:42:48 -0800] "GET / HTTP/1.1" 302
[05/Jan/2022:16:42:49 -0800] "GET /auth/login?redirect=%2F HTTP/1.1" 200
[05/Jan/2022:16:42:59 -0800] "GET / HTTP/1.1" 302
[05/Jan/2022:16:42:59 -0800] "GET /auth/login?redirect=%2F HTTP/1.1" 200
[05/Jan/2022:16:43:00 -0800] "GET /js/app/api-triage.js?v=3.4.0 HTTP/1.1" 304
[05/Jan/2022:16:43:00 -0800] "GET /settings.json?api-version=v2 HTTP/1.1" 200
[05/Jan/2022:16:43:00 -0800] "GET /settings.json?api-version=v2 HTTP/1.1" 200
[05/Jan/2022:16:43:00 -0800] "POST /auth/verify.json?api-version=v2 HTTP/1.1" 500
[05/Jan/2022:16:43:00 -0800] "GET /auth/verify.json?api-version=v2 HTTP/1.1" 200
[05/Jan/2022:16:43:01 -0800] "GET /auth/verify.json?api-version=v2 HTTP/1.1" 200
[05/Jan/2022:16:43:04 -0800] "GET /auth/verify.json?api-version=v2 HTTP/1.1" 200
[05/Jan/2022:16:43:04 -0800] "GET /img/avatar/user.png HTTP/1.1" 304
[05/Jan/2022:16:43:10 -0800] "GET /users/csrf-token.json?api-version=v2 HTTP/1.1" 200
[05/Jan/2022:16:43:10 -0800] "POST /auth/login.json?api-version=v2 HTTP/1.1" 500

Hi @jollywaffl :wave: welcome to the passbolt community forum :handshake: and best wishes for this new year :pray:

I noticed that in your report:

You don’t have https configured yet, but your passbolt is configured to force SSL use. Maybe it is the issue ? You can’t force SSL if your base url does not start with https ?

You can temporary disable “force ssl” in your config/passbolt.php file, in the ‘passbolt’ section:

    'passbolt' => [
        'gpg' => [
           (some stuff)
        ],
        'registration' => [
            'public' => false,
        ],
        'ssl' => [
            'force' => false,
        ]
    ],

Best,

Hi @AnatomicJC, thanks and happy new year!

I gave that a shot, but it didn’t have the effect I’d expect it to: “Passbolt is not configured to force”… is now an error, and everything else stayed the same.

I can work on getting SSL up and running, but I’m having a few issues with my certificate server that I need to resolve first. However, given that the demo config in env has SSL off, I suspect that’s not the issue.

 [FAIL] Passbolt is not configured to force SSL use.
 [HELP] Set passbolt.ssl.force to true in config/passbolt.php.
 [FAIL] App.fullBaseUrl is not set to HTTPS.
 [HELP] Check App.fullBaseUrl url scheme in config/passbolt.php.

@jollywaffl we’ve seen the “cannot sign / verify” error can be when there are some issues around keyring permissions (that are too lax to gnupg taste). Can you share the permissions on the content of the keyring folder /home/www/.gnupg to rule that out?

@remy the permissions are as follows:

~/.gnupg $ ls -la
total 43
drwx------  4 www  www    14 Jan  6 07:20 .
drwxr-xr-x  4 www  www    11 Jan  6 07:19 ..
-rw-r--r--  1 www  www    20 Jan  5 16:26 .#lk0x0000000800c14090.passbolt.71641
drwx------  2 www  www     3 Jan  5 15:50 openpgp-revocs.d
drwx------  2 www  www     4 Jan  5 15:50 private-keys-v1.d
-rw-r--r--  1 www  www  1774 Jan  5 15:50 pubring.kbx
-rw-------  1 www  www    32 Jan  5 15:50 pubring.kbx~
-rw-------  1 www  www   600 Jan  6 07:20 random_seed
srwx------  1 www  www     0 Jan  6 07:20 S.gpg-agent
srwx------  1 www  www     0 Jan  6 07:20 S.gpg-agent.browser
srwx------  1 www  www     0 Jan  6 07:20 S.gpg-agent.extra
srwx------  1 www  www     0 Jan  6 07:20 S.gpg-agent.ssh
srwx------  1 www  www     0 Jan  6 07:20 S.scdaemon
-rw-------  1 www  www  1280 Jan  5 15:50 trustdb.gpg

That config looks, fine, so that’s not it. This looks like some issues with gnupg / libgpgme / php-gnupg but it’s hard to tell what. Which versions of php-gnupg are you running?

Do you have any errors in passbolt error.log (not the nginx ones)? If you installed from source it should be in your passbolt directory under /logs/error.log. Just in case the error is something else.

From phpinfo(), I’m using 1.5.1 installed via pecl, and I’ve also tried 1.5.0 via the system package manager.

gnupg support => enabled
GPGme Version => 1.15.1
Extension Version => 1.5.1

The last few errors in error.log are similar to this one (UTC timestamp?):

2022-01-06 00:43:10 Error: [Cake\Http\Exception\InternalErrorException] The authentication failed. in /usr/local/www/passbolt/src/Controller/Auth/AuthLoginController.php on line 93
Request URL: /auth/login.json?api-version=v2
Client IP: 172.22.0.16

Is there a flag or configuration option to make the logs more verbose?

I also have some errors in cli-*.log from an earlier attempt where I’d inadvertently created an incompatible GPG key, and from a run with PGP 8.0, but I’ve reinstalled all packages since then and rerun composer install and passbolt install.

@jollywaffl can you try to add the flag in the passbolt.php to debug

    'debug' => true,
    'passbolt' => [

Then retry to see if there are more information in the logs.

Thanks - gave that a shot, but unfortunately nothing new in error.log. Also doublechecked nginx and php-fpm, nothing useful there.

Is it worth trying to hack some extra verbosity into AuthLoginController.php? My php is very rusty, but I can give it a shot.

2022-01-06 17:19:58 Error: [Cake\Http\Exception\InternalErrorException] The authentication failed. in /usr/local/www/passbolt/src/Controller/Auth/AuthLoginController.php on line 93
Request URL: /auth/login.json?api-version=v2
Client IP: 172.22.0.5


2022-01-06 17:19:59 Error: [Authentication\Authenticator\UnauthenticatedException] Authentication is required to continue in /usr/local/www/passbolt/vendor/cakephp/authentication/src/Controller/Component/AuthenticationComponent.php on line 177
Request URL: /auth/is-authenticated.json
Client IP: 172.22.0.5


2022-01-06 17:20:00 Error: [Authentication\Authenticator\UnauthenticatedException] Authentication is required to continue in /usr/local/www/passbolt/vendor/cakephp/authentication/src/Controller/Component/AuthenticationComponent.php on line 177
Request URL: /auth/is-authenticated.json
Client IP: 172.22.0.5


2022-01-06 17:20:01 Error: [Cake\Http\Exception\InternalErrorException] The authentication failed. in /usr/local/www/passbolt/src/Controller/Auth/AuthLoginController.php on line 93
Request URL: /auth/verify.json?api-version=v2
Client IP: 172.22.0.5

Ok, I can pull out a full backtrace at the point of failure, but it’s huge and not something I understand. I did see that it’s failing at GPGAuth stage 0, if that means anything…

@remy I’ve made some progress, and it’s some kind of a key signature disagreement. If I dig into the healthcheck and print out the exception that occurs inside gpgCanDecryptVerify(), I get the following error:

Cake\Core\Exception\CakeException: Decryption failed. Invalid signature. Expected 9C213977C9C44FBAA4E7BD7B8DCCC57DF1FF2B3F and got 9BD78B0132367C3BD73E150E47EB65A148F5433E. in /usr/local/www/passbolt/src/Utility/OpenPGP/Backends/Gnupg.php:602

The key fingerprint in config/passbolt.php matches the expected value above, and also matches what I get from gpg:

$ gpg --list-secret-keys --keyid-format long
gpg: Warning: using insecure memory!
/home/www/.gnupg/pubring.kbx
----------------------------
sec   rsa2048/8DCCC57DF1FF2B3F 2022-01-05 [SCEA]
      9C213977C9C44FBAA4E7BD7B8DCCC57DF1FF2B3F
uid                 [ultimate] ...
ssb   rsa2048/47EB65A148F5433E 2022-01-05 [SEA]

And, if I extract the encrypted message produced by gpgCanDecryptVerify() and try to decrypt it manually, I see that the message was signed by the subkey, which reportedly has the fingerprint that healthcheck is getting back.

$ gpg2 --decrypt message
gpg: Warning: using insecure memory!
gpg: encrypted with rsa2048 key, ID 47EB65A148F5433E, created 2022-01-05
      "..."
test messagegpg: Signature made Thu Jan  6 11:19:13 2022 PST
gpg:                using RSA key 9BD78B0132367C3BD73E150E47EB65A148F5433E
gpg: Good signature from "..." [ultimate]

If I set the subkey fingerprint in config/passbolt.php instead of the main key fingerprint, healthcheck complains about a mismatched key but the decryption and verify steps pass.

 GPG Configuration

 [PASS] PHP GPG Module is installed and loaded.
 [PASS] The environment variable GNUPGHOME is set to /home/www/.gnupg.
 [PASS] The directory /home/www/.gnupg containing the keyring is writable by the webserver user.
 [PASS] The server OpenPGP key is not the default one
 [PASS] The public key file is defined in config/passbolt.php and readable.
 [PASS] The private key file is defined in config/passbolt.php and readable.
 [FAIL] The server key fingerprint doesn't match the one defined in config/passbolt.php.
 [HELP] Double check the key fingerprint, example:
 [HELP] sudo su -s /bin/bash -c "gpg --list-keys --fingerprint --home /home/www/.gnupg" www | grep -i -B 2 'SERVER_KEY_EMAIL'
 [HELP] SERVER_KEY_EMAIL: The email you used when you generated the server key.
 [HELP] See. https://www.passbolt.com/help/tech/install#toc_gpg
 [PASS] The server public key defined in the config/passbolt.php (or environment variables) is in the keyring.
 [PASS] There is a valid email id defined for the server key.
 [PASS] The public key can be used to encrypt a message.
 [PASS] The private key can be used to sign a message.
 [PASS] The public and private keys can be used to encrypt and sign a message.
 [PASS] The private key can be used to decrypt a message.
 [PASS] The private key can be used to decrypt and verify a message.
 [PASS] The public key can be used to verify a signature.

However, I still get a 500 error when trying to log in after this change. I captured the network traffic and the client successfully GETs from /users/csrf-token.json, but receives a 500 back when POST’ing GPG data to /auth/login.json. The 500 error is generated by AuthLoginController.php, which I guess still can’t decrypt and/or verify the client response.

This key vs subkey discrepancy, maybe it’s a library version issue?