Node openpgp error when encrypting: Could not find valid key packet for encryption in key - node.js

I have a error when trying to encrypt a string with a pgp public key:
'Could not find valid key packet for encryption in key 9ae788ff8eec0b31'
This error doesn't appear with every key but with most of them. Here one of the keys that errors:
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: BCPG v1.43
mI0EXQJU0gEEAKZKsTmlR71mPgzQR6hyGJXR4tuoH/RgJPnZGCKPlJqCj8GCvlTa
Jqy5gUZQJItwS4ssFU56+fI1a47oe08covHWgLAsGRWCxsD/oneFhddPhhZkHOui
s1CW3CNDQ8hhl/DykhUoegKCmvNDzRVsD4y7ueLkzAisu3MH3ShQWDB/ABEBAAG0
CUxJTlhPIFNBU4icBBABAgAGBQJdAlTSAAoJEPa8OTh7Vcnz4kID/0KL7RBA5Z83
WuirfaVXF+Kqi4QXQO4EBUUknSbO+igRSJ/MLV4NROuhn2AZ3YWXK9B8rLsaZy9Q
49/rr1lPn648Wq2lAoN7uLwtycspFQscjLT76hDMnoOvJGzjrpi+xC7n0W7ggLRN
TkCUB8b+OBvwPhptny8kS6DASwew0Fp7
=2Sis
-----END PGP PUBLIC KEY BLOCK-----
Here is the function im using to encrypt
const openpgp = require('openpgp')
async function pgpEncrypt(pubkey, message) {
await openpgp.initWorker({ path: 'openpgp.worker.js' })
const options = {
message: await openpgp.message.fromText(message), // input as Message object
publicKeys: (await openpgp.key.readArmored(pubkey)).keys, // for encryption
armor: false
}
const cipherText = await openpgp.encrypt(options)
return cipherText.data
}
What's wrong with this? how can i ensure the key works with this library?

It is a version issue. Try the 4.10.8 version of openpgp. Use the following lines for the dependencies.
"dependencies": {
"openpgp": "^4.10.8"
}

Related

Node Openpgp encrypt can not find valide key

When I try use Openpgp#5.5.0 to encrypt my string
get error Could not find valid encryption key packet in key 637691f642a09df8
, how can i fix this issue ?
my public key
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGNJlV4BEACw+tHTiJJ9METBa6+ZjF3SEPsidcsPv6osFQJREoVUmwhKBdwN
6YLr05Gkd+FYzUYU6STKtH9bBBoXjTY1qBMHZVFZvKWV8IJ680+xzz5JvgVyhu4c
EvWowpOSJTDl0sP06n2kItGqPFo+kHSinoA/OmZha7p0ljOMiMqbL0ysQ3LbrZmb
NLQysFTsKzgynKa40z5SjamWx8iLsa28mXZbLMsdY67f0Du9wAmwa036RIm5CNSO
vw6mzN1BzQVYR5IxwajxodTWXjmRG9jk4/F+FxCin5YObVRQuj28ggWboPRhcGJi
vap4ew+DbdwWSYzLNJIHocpRHNCtVOgPl/I35N6CHuxf7/c+428iNBxdN3ICyadC
y853OnusB9DDVjhVgpnbJ4b+L5pYYToQrISUQo0r3YCJyPSMfMo96tmh58Gv70oC
oMxFgafjuSyD7GvCupGCh3yuAtqLYuMVmS3OQZWAqcwsJQYNxURTfppn0Jl4MVRU
M/2vmjR7dqX+vdGtwK3Xu844w2QTzGPzPqHrXRNDm2evkHc7YI3hsOw2mRgPSzqn
aiyXXS4Q1IMSeIIXUOL19S5dfNMKeNO2tAfobqwkXbN4TwGfHlj72Bx8UPJHvThI
5Fzv+jtRb/kcr+QTRHUmzOuhftOb76RXhfjqTiad2/b2n2mJWZsv4YchgQARAQAB
tDVLYW8gRHJhZ29uIChVUFMgU21hcnRWaWV3IGRhdGEga2V5KSA8a2RyYWdvbkB1
cHMuY29tPokCTgQTAQgAOBYhBFFqZd3nc1CngvkZm2N2kfZCoJ34BQJjSZVeAhsD
BQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEGN2kfZCoJ344H8P/Aij5JhKGOAG
rmRoHkRpuVdJYGXpJxUAjjah6Z5j6qRC+/FIdrAYxGoLDgshDEqJPMRddAT/xepF
QDtD/noqFyd8JJUSkzH/zrUcohs3oG9Rd5WybYu85AHQutBHGG5H/ghuJ3s1zXfR
fFe34j3SzhCcXg67Tqipl2t+ap8lQkWEpJ//CHknsHt91B5khx9Xv4QQOLzuCz56
rLDf5GqghAwHpA3BfuUnAmuw8wFTymdlR4KSIh5ttwG/GT5A6L8MGydI4y4dUSHt
umsn1JwvHMaXvwGy4ReJK6Z8o4H022Qmmz8pnVjGNz1CLzupcKGEPbN9mO4/wv/k
tzU4qPbKxoCu5UewMvqpeXLvlpn2DlTR8NivQ3847xokhfR+UlEnIEbcwcWdvJc2
mL8xKhvFh0sBQK3OyyXJzL0pw9eLAdj5i5sUO+hl6Dy2eo8QxfNw7zaw8L72fk3n
HIJFTB6RpCHXUw6Jb4K5NODVuKJ4z9r5okqzHA7gaALEcT/q9CQ3p044vLbrPxMD
s/+RX6pJn1c3azpMLhSQFH/C3gZySoPujLqcNDvjkluI1ErPD9dR7OX0Od345kkp
DZykeb1DbaO+OR3At1fEBJ1S8d3xngrpuVjSSsXOWWNd14nw9T0ZIcxkISDHyllz
M7QEGBSUvOR14CWnx9uAHVLNyruaKBix
=n4J7
-----END PGP PUBLIC KEY BLOCK-----
const publicKeyArmored = ``;
console.log('Get Keys')
const publicKey = await openpgp.readKey({armoredKey: publicKeyArmored})
const encrypted = await openpgp.encrypt({
message: await openpgp.createMessage({ text: 'Hello, World!' }),
encryptionKeys: publicKey
});
})();```

nodejs openpgp hashing algorithm to SHA256

I managed to sign message with OpenPGP sign() function,but how can I change the hashing algorithm to SHA256?
async function pgpSignMessage(privateKey,messageToSign,callback) {
const unsignedMessage = await openpgp.createCleartextMessage({ text: messageToSign });
const cleartextMessage = await openpgp.sign({
message: unsignedMessage,
signingKeys: privateKey,
});
console.log("pgpSignMessage cleartextMessage ",cleartextMessage );
return callback(cleartextMessage );
);
ouput :
pgpSignMessage cleartextMessage
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
This is a testing message
-----BEGIN PGP SIGNATURE-----
wsBzBAEBCgAGBQJjTOMPACEJEPjzUwweaxTJFiEEcJyNNiL/3PuC/Rze+PNT
DB5rFMnA2wf+OQV8+S1o12hrHgIOy362xHk7jk+bhUf2DzosyMIb5/FaP58a
Y2VxZUOMkYPFJeiJ9dO7z+25QjbUgbZz5ikExdPIIwmfY1BPX8jgWEQAniOD
ZZVg+pG2hALuZwzBchw+onvoPyyZLSNajkY4rA/wXexuAljWqWTpypoN51iQ
O/E4TN2FbAIQOq89tzS5MXhEAZe4bYHH4cUwsQiaIjA+2OjrspPJt+3/nosP
1f6k6wgZKuPDbyK6KKSqtb0tzFmIVkF+4+VF+vQFi7kx5utWn/nXOWO78tUV
s6dn23+GdJ5sLaFUT5vPDKux3dddErPOKEam/hJUe5VoO2LzeNO5Ww==
=KsDz
-----END PGP SIGNATURE-----
Having access to the openpgp.js sources (in this case it is latest master commit), and going down through the sign() function code, you'll occasionally get to this:
export async function getPreferredHashAlgo(key, keyPacket, date = new Date(), userID = {}, config) {
let hashAlgo = config.preferredHashAlgorithm;
let prefAlgo = hashAlgo;
if (key) {
const primaryUser = await key.getPrimaryUser(date, userID, config);
if (primaryUser.selfCertification.preferredHashAlgorithms) {
[prefAlgo] = primaryUser.selfCertification.preferredHashAlgorithms;
hashAlgo = crypto.hash.getHashByteLength(hashAlgo) <= crypto.hash.getHashByteLength(prefAlgo) ?
prefAlgo : hashAlgo;
}
}
...
So, it would first pick value from the config.preferredHashAlgorithm. Then, if primary user's id certification contains preferred hash algorithms subpacket, and first value's hash length is longer then config's one, it will pick it up.
You may get more information about your key via gpg --list-packets command.

NOdeJs Rest API response encoded with private key

I have been supplied with a public and private key to call a restAPI in nodejs.
Both keys are in clear ASCII format.
I use the following code to encript my message:
(async () => {
// put keys in backtick (``) to avoid errors caused by spaces or tabs
// ENCRYPT
const publicKeyArmored = fs.readFileSync(publicKeyFile, {
encoding: 'utf8',
flag: 'r'
});
const publicKey = await openpgp.readKey({ armoredKey: publicKeyArmored });
const encrypted = await openpgp.encrypt({
message: await openpgp.createMessage({ text: 'Hello, World!' })
, encryptionKeys: publicKey
// , signingKeys: privateKey // optional
});
console.log("Encrypted:", encrypted); // '-----BEGIN PGP MESSAGE ... END PGP MESSAGE-----'
}
However when I try to decrypt the response, all the code examples I have found seem to require a passphrase to use the private key supplied, but this is not encoded in any way, it's again plain ascii, begining with :
-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v2.0.22 (GNU/Linux)
lQO+BGHApmABCAC70QG0T3bh1MVRGKmY9cOM2NFEie2KXCLGXUPa+2B5JOnDypGX
msoLau8FtKIqvAVAYSsONlE4P4RcltyrOTHLMvWhu73ZTJIBu6GGkgM6bKOtu2Rp
/VbPylPIXrkA3A4s0089VGgmFqJul04lit2svLwxD31ZEIY3Ke3kd0dV0nM4npRO
EZUPR5Qr6KCwBsL+ZHbDuG2YrC7oKcnJTXcdszrF7+FLAwI8viZhJOXyagJRioXd
/H/IpauXyvejN22/eRjch9IRMSz+qh0avj9tcuuJ1k4sBQQukeoIoPwFe9Rb9TY2 .....
the following code suggests I need a passphrase, but this key does not appear to require one:
async function decrypt() {
const privateKey = (await openpgp.key.readArmored([privateKeyArmored])).keys[0];
await privateKey.decrypt(passphrase);
const encryptedData = fs.readFileSync("encrypted-secrets.txt");
const decrypted = await openpgp.decrypt({
message: await openpgp.message.readArmored(encryptedData),
privateKeys: [privateKey],
});
console.log(decrypted.data);
}
SO how do I use it without a passphrase?
Thank you in advance for your xmas spirit and any help!
Your private key is ASCII armored, so it is possible to transfer it in text representation. After calling gpg --dearmor on it you'll get the binary data. Also private key may be stored using the password encryption, or not encrypted at all (in the second case you will not need to call privateKey.decrypt()). To check this you may use the command gpg --list-packets keyfile.asc.

Get public key from certificate in nodejs

I need to get a server's public key from its SSL cert. I'm getting the cert as follows:
https.request(options, res => {
const cert = res.connection.getPeerCertificate();
const publicKey = cert.????()
}
I can't find a way to get the public key from the certificate though. Are there any libraries that can do this?
I'm looking to use the public key to encrypt some data:
const encryptedBuffer = crypto.publicEncrypt({
key: publicKey,
padding: crypto.constants.RSA_PKCS1_PADDING
}, utf8Payload)
I see that the certificate has a "raw" buffer, but using that as the publicKey fails.
-----BEGIN CERTIFICATE-----
MIID3DCCAsSgAwIBAgIUOaZ5jqRgBz4HjwilIbDz5+Polh0wDQYJKoZIhvcNAQEL
BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
.....
C1c3RqArBaz/c4SqHhyKaHRFinDs5kjnAz+H4+QvQAH0UXgHG050YEZjeZPXMRJB
4I0fzGC++82WXhcwSPaX+BJZuv2bEIfxbyxdVanGmIJdYsGFwSc9sIf2j1cK22A5
vdboEXXkQnqF552iNy9HGRubNQ1VkqITELToRcqcvAo=
-----END CERTIFICATE-----
If the format of the certificate is as above, it can be done with crypto module. No dependency on other packages.
crypto.createPublicKey(cert).export({type:'spki', format:'pem'})
output format:
-----BEGIN PUBLIC KEY-----
..........................
-----END PUBLIC KEY-----
or
crypto.createPublicKey(cert).export({type:'pkcs1', format:'pem'})
output format:
-----BEGIN RSA PUBLIC KEY-----
..............................
-----END RSA PUBLIC KEY-----
see more on the document
I see that the certificate has a "raw" buffer, but using that as the
publicKey fails.
Note that the raw buffer is DER encoded, and from crypto.publicEncrypt needs a PEM encoded key. So, you just need to do the conversion. I've used node-openssl-wrapper in the example below, but there are other libraries that also convert DER to PEM,
const ossl = require('openssl-wrapper')
const https = require("https");
https.request(options, res => {
const certificate = res.connection.getPeerCertificate();
const rawDer = certificate.raw;
ossl.exec('x509', rawDer, { inform: 'der', outform: 'pem' }, (err, buffer) => {
const publicKey = buffer.toString('utf8'); // PEM encoded public key safe to use now
// crypto.publicEncrypt({ key: publicKey, ...
})
});

Encrypting a file with Nodejs (Crypto) throw an error: bad base64 decode

Hello and sorry if my question is stupid, I'm just beginning on nodejs and bring a heavy luggage from PHP world.
I'm trying to encrypt a file using a public key generated through linux command line using the GnuPG command.
On my app I use Express, fs and Crypto to create a buffer from the file and get the public key content and then use publicEncrypt to get the encrypted data.
When I do so the application stops and throw an error complaining about the PEM format: bad base64 decode.
Error: error:0906D064:PEM routines:PEM_read_bio:bad base64 decode
Here you have the main parts of this code:
var encryptStringWithRsaPublicKey = function(toEncrypt, relativeOrAbsolutePathToPublicKey) {
var absolutePath = path.resolve(relativeOrAbsolutePathToPublicKey);
var publicKey = fs.readFileSync(absolutePath, "utf8");
if(typeof toEncrypt !=='object') return false;
var buffer = new Buffer(toEncrypt);
console.log(publicKey);
var encrypted = crypto.publicEncrypt(publicKey, buffer);
return encrypted.toString("base64");
};
fs.readFile(req.files[0].path, function (err, data){
var encrypted = encryptStringWithRsaPublicKey(data, '/home/app/data/pub_key.txt');
if(!encrypted) {
fs.writeFile("/home/app/data/uploads/enc1/test.pdf", encrypted, function(err) {
if(err) {
return console.log(err);
}
console.log("The file was saved!");
res.end(req.files[0].filename);
});
}
else {
res.end({error:'encryption failed. all data deleted.'});
}
});
Maybe the Public Key has some end of line bad characters somewhere or maybe Crypto requires a very special format?
This is the content of the pub key:
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1
mQENBFiFz2ABCADGk6E2IgbaGYIHO7EVNotxiDjB4k5UZJ4xx41RwY9LeG0c+SLW
rC/ijPFJZ/kN3nrpvTAZEYpnK51olqvw/OOgt5p3k32mW47HALx91vU9WRrykt2Y
DMj+aeMDi5QZnda8qTnWCW3E+OBg4W0ZdpwPs+eOyHWRjp6zuBFxZfrtKQuFlzHs
6KKczdGidemUQCZL7ve34EQmgeh4rDJ1oNC8QzSFOYZHiSVQDXGvZSFirc3OMZus
JiflY1Al3Y0fJj2m8catu/i9bKfAPA+YE+yU86BrgV05Skn82px2K3coiI/+eSjp
j/ROxijvwzLf/F98B3/AiMJjx8pD/9APmnSbABEBAAG0MVBheSBGaWxlIChDdWJl
IEluc3BpcmUpIDxwYXlmaWxlQGN1YmVpbnNwaXJlLmNvbT6JATgEEwECACIFAliF
z2ACGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEBeEp+MzfXEgefgH/0bJ
Oug/m66vlENqR+y6Z+mbC7RzFnhvojJ51EB6JlJe9EJ2VwtcirxorY5zL9DjTyB2
ys/kzdeN0+FmuIIO0To7ksB1ASZ5jsg1UdQEvLuLeSZSJRzbmz9M7jvxEfR+vz0h
RJPqs6EfgAOtRyDs8C/IXyWTrhu1wI+09CChjBH0/tCJ2sO074f4xMY1IYzf8nm7
ohuiGpN1egHOVjIjIajpmb94dGBXnbGNq/tzNwGZu9GUtaeTs3+kuqqy0+eIQDvR
7AU4Gt43etwpFz4dbWVDd77OxKUFshilaChIAwGmngfFn3ksnrl/AZVsGIJrxmy0
ja5t+yZOwl7KdC82SOa5AQ0EWIXPYAEIAOHRdsrEm/WFG3Fps++Mo6xUf/CFTyz3
WQr2nkOoBxAzcHPQd/3muDNKUblRhxZMrwuVZcnOZVOOz9rMqaM5kYSAB84PpVpG
26QcYFUn5WCmR3KSn9MiKqtSFJDn695ysaCdzzEW5Y/eKgxydG4rhFOy07VcKTev
dBC19XcukjxAbzmnZ7qUFhaRrS2u11mA+s0FmRz+EVOd0uxQdJq/Lps1nMvZ3UfL
saHJuBDgX+gCarbt+7uSx3aC/jBDzrq63Ry7nqN5mypSMRBeEAmi7kKToIRDj0Uj
xwqCgU4NVj8zCG2iBlOzrfKPk9oMLgHBvMPQYDW9wLz5rQnoVr4RkrUAEQEAAYkB
HwQYAQIACQUCWIXPYAIbDAAKCRAXhKfjM31xIBDYB/0VTjC/zvFHJwD5t+8DzHjN
UqPg7Mk0kYbu6dyPYb0/S2G5uZa3LoJ99EgOhgFlfUHM9k0GBC0OTxKiUEqKtENH
+W/wBouTltqGGyzDit+KlqzKz9gsyWF/HO3GTg1Df9D8o3MhUHRGjEeuik0BbJyd
Hy4YfDk5a4qUYtFztbmUSxVqdLlFBZ7oMn3n+A25HaDtohv9g1ZC3gTLD+yTTMsG
ruOEs6ZMIOENn6pgsjFdMIUmJVP3tt9n538jVfbVf7EgTrPt+JKjoQF3EfTysTnO
Y0IuotQuA83+5Fa6IY+iFLLvkNABr1WACVOKMUzBJJJG7EnlvgPufZL3eJE4LUZ9
=rpky
-----END PGP PUBLIC KEY BLOCK-----
I've found the solution to my problem.
In fact the method publicEncrypt is a wrapper of OpenSSL and then it expect a public/private key on that format. A key from GPG won't do it.
By generating the private and public keys with the following command the code work as expected:
$ openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
$ openssl rsa -pubout -in private_key.pem -out public_key.pem

Resources