Unable to decrypt an unarmored pgp file with OpenPGP.js: Session key decryption failed

2.6k views Asked by At

I have a CSV file that has been encrypted and is now an unarmored PGP file.

I'm trying to decrypt it using OpenPGP.js 5.0.0 and Node.js 14.17.5 but keep hitting a wall.

At first, I tried the following code, as per the project examples:

const passphrase = 'pass';
    
const publicKeyArmored = '... public ...';
const publicKey = await openpgp.readKey({ armoredKey: publicKeyArmored });
    
const privateKeyArmored = '... private ...';
const privateKey = await openpgp.decryptKey({
  privateKey: await openpgp.readPrivateKey({ armoredKey: privateKeyArmored }),
  passphrase,
});
    
const binaryMessage = fs.createReadStream('/path/to/file.csv.pgp');
const message = await openpgp.readMessage({
  binaryMessage,
});
    
const { data: decrypted, signatures } = await openpgp.decrypt({
  message,
  verificationKeys: publicKey,
  decryptionKeys: privateKey,
});

But the decrypt function throws: Error: Error decrypting message: Session key decryption failed.

I then tried to add code to manually decrypt the session key:

const sessionKey = await openpgp.decryptSessionKeys({
  decryptionKeys: privateKey,
  message,
});

But the decryptSessionKeys function throws: Error: Error decrypting session keys: Session key decryption failed.

I suspected that the file may have been encrypted symmetrically by mistake, so I've tried to modify the call to decrypt as:

const { data: decrypted, signatures } = await openpgp.decrypt({
  message,
  passwords: passphrase,
});

But the decrypt function throws: Error: Error decrypting message: No symmetrically encrypted session key packet found.

As a sanity test, I've decided to try and decrypt the file using the gpg CLI.

I've imported the armored key pair using:

gpg --import key.public.pgp
gpg --allow-secret-key-import --import key.private.pgp

And then decrypted the file using:

gpg --show-session-key /path/to/file.csv.pgp

After being prompted for the private key passphrase, the file was successfully decrypted with the following output:

gpg: WARNING: no command supplied.  Trying to guess what you mean ...
gpg: encrypted with rsa4096 key, ID <redacted>, created 2021-09-02
      "<redacted> (<redacted>) <redacted>"
gpg: used key is not marked for encryption use.
gpg: session key: '<redacted>'

What am I doing wrong? Why is decryption failing with OpenPGP.js but succeeding with GnuPG?

1

There are 1 answers

0
noamt On BEST ANSWER

It seems like the message was encrypted with the primary key, which is marked as sign-only.

Setting the allowInsecureDecryptionWithSigningKeys decryption configuration to true solves this issue:

const { data: decrypted } = await openpgp.decrypt({
  message,
  config: {
    allowInsecureDecryptionWithSigningKeys: true,
  },
  verificationKeys: publicKey,
  decryptionKeys: privateKey,
});