Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decrypt Non-Armored PGP Files With OpenPGP.js

I am working on a Node application into which I have built a decrypter function, and have used the Openpgp.js npm module to make this work. I take in various submitted PGP client files made with our public key, decrypt them using our private key as they come in, and place the decrypted versions in a folder for me to access, and all seems to be well....as long as the files are armored. Here are some sample lines of the code showing the order of events:

const encryptedData = fs.readFileSync(encryptedFilePath, 'utf8')
openpgp.decrypt({
        message: openpgp.message.readArmored(encryptedData),
        publicKeys,
        privateKey
}).then( (decrypted) => { fs.writeFile(decryptedFilePath, decrypted.data } )

When an armored file comes through, all is well and I get the decrypted file in the specified folder. These files when opened in a text editor are formatted like this:

-----BEGIN PGP MESSAGE-----
WBh2X7KwfEBDx0LEE1FzlnvxZs44o62FclpTazJpcl9J7DjwVfg9cHCID0TAN6Y6
B3b5bCQQFe1wTgpIkVtd0mFGQx7KGHj4FGte53qseVxC2bfq9PGKRIAUg6olr+82

However, we have clients that encrypt files with the armored option off, so they come in a hexidecimal-type format when opened in a text editor....

7403 436d e6c0 f941 daac 945b 9a81 f066
6cd2 0032 5df0 9ca2 23a0 6eec a7bb f24c
a941 99a8 1053 ae23 f88b 245c f709 c2b2

.....or as encoded text files, which look like this:

DµÉ‰í+�3K€Ð�˜PªeZ_|Ò®ó0��ãZqRµ3!ŒpuÉW�NZrìÚk´
Aˆ›œiêø8�Ú�ól:äΟ”�6‡)
w�¬ÌŒWÝÚ¢�Q��œ�œ?�H¨¿�œ//�ÃBA�´>(%°�e�

(These last two resemble what I see when I console log "encryptedData" above in my code example.)

Whenever any non-armored files come in, the process fails and I initially got a couple different errors depending on the type shown above. I took away the 'utf8' encoding on the fs.readFileSync and put "fromBinary" in place of "readArmored" to work with the data as binary thinking that might work, but then I get errors about "Invalid session key for decryption". So then I tried using the "decryptSessionKey" function before the main decrypt as it shows in the docs, and this gets me an undefined key and an error about "No symmetrically encrypted session key packet found". Besides, I'm probably barking up the wrong tree, as using binary with Openpgp.js seems to require a password, which I'm thinking is different than the passphrase that unlocks my private key, which is the only password I have.

I have searched all through the Openpgp.js documentation and Googled like crazy, but can't seem to find a solid procedure on how to amend my code which works for ASCII armored files to decrypt files that are not armored. (Every single file that comes in, however, decrypts quickly and without error when using a desktop decrypting program like PGP Desktop, so I can't figure out where my discrepancy is and why the solution isn't obvious.) Anyone have any experience with this or a possible solution?

like image 437
threepears Avatar asked Feb 16 '17 06:02

threepears


1 Answers

The non-armored version of openpgp.message.readArmored() is openpgp.message.read()

So something like this should work:

const encryptedData = fs.readFileSync(encryptedFilePath, 'utf8')

if encryptedData.startsWith('-----BEGIN PGP MESSAGE-----')
    encryptedMessage = openpgp.message.readArmored(encryptedData)
else
    var TextEncoder = require('text-encoding').TextEncoder;
    var encryptedUint8 = new TextEncoder().encode(encryptedData);
    encryptedMessage = openpgp.message.read(encryptedUint8)

openpgp.decrypt({
    message: encryptedMessage,
    publicKeys,
    privateKey
}).then( (decrypted) => { fs.writeFile(decryptedFilePath, decrypted.data } )

(The var TextEncoder line is not required here if you load TextEncoder earlier in your code)

like image 70
Stobor Avatar answered Nov 01 '22 23:11

Stobor