Skip to content

Instantly share code, notes, and snippets.

@psenger
Last active February 22, 2022 07:39
Show Gist options
  • Select an option

  • Save psenger/6367ac804d040b6bbf5e07db7d202065 to your computer and use it in GitHub Desktop.

Select an option

Save psenger/6367ac804d040b6bbf5e07db7d202065 to your computer and use it in GitHub Desktop.
[Working with OpenPGP, Example] #PGP

get past an error if you use GPG to sign your git commits

If you get an error like this.

$ gpg --recipient "Mr Monkey Go Boom Boom" --armor --encrypt foo.txt 
gpg: 85A71139B659E03A: There is no assurance this key belongs to the named user
gpg: Sorry, no terminal at all requested - can't get input
$

then remove or comment out the line no-tty from the ~/.gnupg/gpg.conf

How to encrypt a message to someone

$ gpg --recipient "Mr Monkey Go Boom Boom" --armor --encrypt foo.txt

This generates foo.txt.asc

-----BEGIN PGP MESSAGE-----

......

-----END PGP MESSAGE-----

Optionally you can add --sign to the options to sign it... but that means it needs to know what your private keys are.

const openpgp = require('openpgp');
const co = require('co');
const fs = require('fs').promises;
const path = require('path');
/**
* ---------------------
* Note:
* This is just another test of decrypting a message with verification
* ---------------------
*/
(async () => {
const privateKeyAsc = await fs.readFile(path.join(__dirname,'../src/main/resources/keys/private.asc'), {encoding: 'utf8'});
const publicKeyAsc = await fs.readFile(path.join(__dirname,'../src/main/resources/keys/public.asc'), {encoding: 'utf8'});
const passphrase = '*************';
// in this example, I have a text file UTF-8, that has a Base64 encoded string in it.
const sampleBase64EncodedMessage = await fs.readFile(path.join(__dirname,'../src/main/resources/keys/sample_message.txt'), {encoding: 'utf8'});
co(function* () {
const decrypted = yield co(function* () {
const message = yield openpgp.readMessage({
armoredMessage: Buffer.from(sampleBase64EncodedMessage,'base64').toString('utf8')
});
const PublicKey = yield openpgp.readKey({ armoredKey: publicKeyAsc });
const PrivateKey = yield openpgp.decryptKey({
privateKey: yield openpgp.readPrivateKey({ armoredKey: privateKeyAsc }),
passphrase
});
const { data: decrypted } = yield openpgp.decrypt({
message,
verificationKeys: PublicKey, // optional
decryptionKeys: PrivateKey,
format: 'utf8'
});
console.log('decrypted=', JSON.stringify(decrypted, null, 4));
});
console.log(JSON.stringify(decrypted, null, 4));
});
})();
const openpgp = require('openpgp');
const co = require('co');
const {
randomBytes,
} = require('crypto');
const originalMessage = require('../../__mock__/originalMessage');
/**
* ---------------------
* Note:
* PGP is POST signage verification, not Pre Decryption
* This could be an issue for DDOS attacks.
* ---------------------
*/
(async () => {
// 32 Bytes = 256 bits
const SenderPassphrase = randomBytes(32).toString('hex');
const ReceiverPassphrase = randomBytes(32).toString('hex');
// this is how to make a RSA key ( OpenPGP has many types of keys )
const SenderKey = await openpgp.generateKey({
userIds: [{ name: 'Jon Smith', email: '[email protected]' }], // you can pass multiple user IDs
rsaBits: 4096,
passphrase: SenderPassphrase,
});
const ReceiverKey = await openpgp.generateKey({
userIds: [{ name: 'Jon Smith', email: '[email protected]' }], // you can pass multiple user IDs
rsaBits: 4096,
passphrase: ReceiverPassphrase,
});
// Simple encryption and decryption, with signing and integrated verification
co(function* () {
const encrypted = yield co(function* () {
const { keys: [privateKey] } = yield openpgp.key.readArmored(SenderKey.privateKeyArmored);
yield privateKey.decrypt(SenderPassphrase);
const { keys } = yield openpgp.key.readArmored(ReceiverKey.publicKeyArmored);
const { data: encryptedResults } = yield openpgp.encrypt({
message: openpgp.message.fromText(JSON.stringify(originalMessage)),
publicKeys: keys,
privateKeys: [privateKey],
});
return encryptedResults;
});
console.log(encrypted);
/**
* ---------------------
* Note:
* when Private keys are provided during encryption, the content is signed.
* ---------------------
*/
const decrypted = yield co(function* () {
const { keys: [privateKey] } = yield openpgp.key.readArmored(ReceiverKey.privateKeyArmored);
yield privateKey.decrypt(ReceiverPassphrase);
const message = yield openpgp.message.readArmored(encrypted); // parse armored message
const { keys: publicKeys } = yield openpgp.key.readArmored(SenderKey.publicKeyArmored);
const decryptedResults = yield openpgp.decrypt({
message,
publicKeys, // for signature validation
privateKeys: [privateKey], // for decryption
streaming: false, // when false, valid becomes present on all the signatures
});
if (decryptedResults.signatures.length === 0) {
throw new Error('Missing Signature');
}
if ((decryptedResults.signatures || []).some(({ valid }) => valid === false)) {
throw new Error('Invalid Signature');
}
return JSON.parse(decryptedResults.data);
});
console.log(JSON.stringify(decrypted, null, 4));
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment