Get public key from certificate in nodejs - node.js

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, ...
})
});

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
});
})();```

Trying to decrypt an private key secure with a passphrase

I try with the crypto nodejs module. But I don't succeed to make it works.
import * as crypto from 'crypto';
import { RsaPrivateKey } from 'crypto';
const privateKey = crypto.privateDecrypt(rsaPrivateKey, Buffer.from('')).toString();
I got a passphrase. I need to do this so I can import my certificate inside AWS. Someone have an idea?
I know that we can do it in golang with
if x509.IsEncryptedPEMBlock(block) {
der, wrongPass := x509.DecryptPEMBlock(block, []byte(o.passphrase))
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,XXXXXXXXX
Decryption is easily possible with the crypto module of NodeJS using the two functions crypto.createPrivateKey() for importing the encrypted key and keyObject.export() for exporting the unencrypted key:
crypto = require('crypto');
encryptedPkcs1 = `-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,B2FBBDCE627586CB04423335D9D4EC59
ekUVpHooHO3d5Ao0gTovipGK9DAP0MBXffEvBrtvcNcxhd9vaE6PsIxQPGwxnc/C
v9Y5RiClNwgZHtRol+i+QeZYLQHUQdOs3toymUgpIcN19IHyxU4C17PCWLZQpuVy
7hcD150dxkGv6Ai53QHIIl4Zybk6neBSbHpJtCnKjRMc6dNONpmFGqO/9SCmH/Bv
lHtPNZ9VsCDI67OO9fMQ3AqfpeGmCwJF8HgXf0nquQH1BJkZsYc4bq/xfGLFII0N
odWD1XEnwL4DWQ1r2wH0IvAXyVQUpwUmDeuDeeslQe9S5IERxovlFKIGsJnIrDLu
j420LLuiMjvj4Cipl91zZjlypsxCXgP7Ta8SDNNWo6yi0qAk1VbMAaeu2GsI6mn5
IUmGr0mkZsSxGFSc9614z+2aJjXEuX1jZ1q83nnZMTz0zEKu/0B6M5h+2B7kG5W1
-----END RSA PRIVATE KEY-----`
encryptedKey = crypto.createPrivateKey({
key: encryptedPkcs1,
passphrase: 'myPassword'})
decryptedKey = encryptedKey.export({
format: 'pem',
type: 'pkcs1',})
Note that in practice nowadays the key should not be smaller than 2048 bits for security reasons. The 512 bit key here is only used for testing.
The output is:
-----BEGIN RSA PRIVATE KEY-----
MIIBPAIBAAJBAL2D8iI9YRKCxsqDrw9WDFddW+xD2FBx383pxiW4el8M2OangbWH
FzOf8Y8ZQiw5tfocUqTvMhOcS1gThT5zUusCAwEAAQJBAJjTO0IzPwF/ZjFPKa9z
U3ZsOcF4IIsWmUTivMAUWNImFS0XiecmhiOpdgjP4LQ5gkphcC7f9VYS6Xw4suen
ZOECIQDp3GtcMdHJzQKn4fDnmTStHeEVDoqvs2tVE/HaWoYhMQIhAM900ZGxJIxK
GYrdkGU2ETvvkyRH7JStGlj3dIJDGE7bAiEAiSIFmpRkLm+XJRbqiwRdzT3+JLjY
Plt5jvQZGC+JA6ECICzJB0TwfPdcN89mrXlsBqRtv9IhRM2D4SA7q4dDfMfpAiEA
s9/2kHpLVmtpEDyw+u4Qrgt6/xUR1B39nceE1bEBo+U=
-----END RSA PRIVATE KEY-----

Reading public and private key from stored files in node js

I wanted to encrypt and decrypt a message in node using public and private keys stored in my system. I was using the following java code to read the file and use the keys.
Java Code:
byte[] keyBytes = Files.readAllBytes(new File(publicKeyFileName).toPath());
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
publicKey=kf.generatePublic(spec);
I am able to use the above java method without any issues to read the public key from file. However, I want to achieve similar functionality in node.
I have tried using crypto for achieving the same but it gives me error while passing the key to publicEncrypt method.
Node:
var encryptStringWithRsaPublicKey = function(toEncrypt, relativeOrAbsolutePathToPublicKey) {
var absolutePath = path.resolve(relativeOrAbsolutePathToPublicKey);
var publicKey = fs.read(absolutepath, "utf-8");
console.log(publicKey);
var buffer = Buffer.from(toEncrypt);
var encrypted = crypto.publicEncrypt(publicKey, buffer);
return encrypted.toString("base64");
};
Error
internal/crypto/cipher.js:43
return method(toBuf(key), buffer, padding, passphrase);
^
Error: error:0906D06C:PEM routines:PEM_read_bio:no start line
Please help. Thanks
Your problem is located in the file format you are actually using with Java. You probably save the
private and the public in encoded ("byte array") to a file and rebuild the keys e.g. with
X509EncodedKeySpec.
This format is not compatible to Node.JS and you have 3 ways to solve it:
a) you write the keys in Java with re neccessary format for usage in Node.JS
b) you write a converter in Node.JS to get the correct format
c) you convert the files with a tool like OPENSSL.
Here I show you the "c-way" as you are handling just one keypair and probably don't need a programatically solution.
Let's say you have two files with the private key ("rsa_privatekey_2048.der") and the public key ("rsa_publickey_2048.der").
In OPENSSL you are using the command line with
openssl rsa -inform der -in rsa_privatekey_2048.der -outform pem -out rsa_privatekey_2048.pem
openssl rsa -inform der -pubin -in rsa_publickey_2048.der -outform pem -RSAPublicKey_out -out rsa_publickey_2048.pem
to convert the files to their PEM-encoded formats.
Below you can find the two sample files I created.
rsa_privatekey_2048.pem:
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAmbeKgSAwVe0nZ84XlbDhMkUDjx1C0duA16MkzHTg1uh9SouO
KK0e3gPtTJ9LssaHlXSYhjpMDMWGO6ujd85XRosI2u9eSMNRYY25AQuBriSTVdi9
BHqWAuWuo6VuvTrkgWTL69vNWvLXTOkTiIyrgnhiavjNvm4UVy2AcO2Y3ER+dKgJ
pQAYlEP1jvuQuf6dfNdSBoN0DZbxZXYbQqoA9R/u0GZHCXY+r8A54RejG34pnnuH
koyROZz5H9LbKGOiaETryornQ1TRvB/p9tgIoCJFI71WsKsqeWQPG3Ymg/FoEWXN
Y0yopZEjpkZa3tU+hrOmAFIRg+/bedKfjYFi/QIDAQABAoIBAD3XZ3N3fbq0BExw
z3A7jv3oYfwrq3w+MOGQEvfmdaZANlfNOU4ICAkNz2QqGgw8bsOj+tDVl070EILl
FIjYjKgmu1NJRcdEPPNgTvOqq2th75xz6+dnYf6cZNwVbC3ZCaE86gVjkoRqek/I
3UDsRvvgbsfWfP+Fzc0c0zWbgQnsK6qivU1uzJX+5xsvgQlZboeZOO2lsdQMgfnu
iGlW1bVVM4Sy7AngqfiKMzihUnYEBIi0Y+mfxAPcBLUW8mrOvIOPPuNNUPxUtkBF
bDEzZ6loXCLLD8UBqXeDbCUPPFdTGcc7INhVgFdl2FL6rHB0+p6eUt8MI/XkZI2d
2AnkBUkCgYEA34cKLs2l5bPjyKybbj6ZG7RhDRsnPypEGU63DMV21twISqt7ZQNv
i3iTP+FYHM3ImECbNRIOZpyLuWLPmh5+5egQH13jRDempoxVSVcghbIserlCz2EU
nD2V6ZKuaDbn395O6Qe/PE/yKHLWbXwJrBBm+o7GGNm/Jd3KJib23PcCgYEAsAxB
esEsxxL8hqg/qf+ij7JJt492svpK/6QXhqeeP/FVOtYSgoNtSrXh9qahGpzMSF0m
FqwIgrOX0RkK3v6ofGVfIKObxOVyhwddS1Ru+SnjBFnTMKS57q0WNrIrBNM6Q0xE
Wd3tiljwmg8xF90U/BXu+m0v5XWKxSn7VLiCBqsCgYEAgl0xtSY/EP6fZJQ2ek+L
4DqNN6WUeCRgXxonbA1mR91AALyOVNVyIreJuYHlb7ccvJ9BZexH9dRrMQ3N4ibS
/6cecAzD1S9XxF6oBwQHdbH6ewC9VFFcQdsxKW5gxWrwRQJUp1fbUoOVyb1gDa5/
vZg7VvoZ0rh74Mu/cAzdgPUCgYEAiNANdwt29AKyUyefykpLGCczGL8aPP88l6z7
R38uAX1Ygg/pdJoUrnHo+FkIbHkcXMRfHFF3j7NoMWynwSLg50OUiPX80SiLN5qm
iytDzskZjsEL2gq6IF1NHRabTfWlmrVDjR9mQhTabq+NtIDwlPOqs9100nrlbFIy
6uU0z18CgYEAkDxQg5UjOzbYIighp/e0LkfKlwUE/cMtISUq1A6Yio9AKZYdBV8p
dd4osUW0gZvDflXlQaBIaNlOwl035lyEZtyuKmFh1oSmoir/TTMbIk0avSgKCLGg
fnhabaQRHl4RdXWcEsioRv3aZUsGkb46Y8xODyAUPRHBPhBsd71gnZ8=
-----END RSA PRIVATE KEY-----
rsa_publickey_2048.pem:
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAmbeKgSAwVe0nZ84XlbDhMkUDjx1C0duA16MkzHTg1uh9SouOKK0e
3gPtTJ9LssaHlXSYhjpMDMWGO6ujd85XRosI2u9eSMNRYY25AQuBriSTVdi9BHqW
AuWuo6VuvTrkgWTL69vNWvLXTOkTiIyrgnhiavjNvm4UVy2AcO2Y3ER+dKgJpQAY
lEP1jvuQuf6dfNdSBoN0DZbxZXYbQqoA9R/u0GZHCXY+r8A54RejG34pnnuHkoyR
OZz5H9LbKGOiaETryornQ1TRvB/p9tgIoCJFI71WsKsqeWQPG3Ymg/FoEWXNY0yo
pZEjpkZa3tU+hrOmAFIRg+/bedKfjYFi/QIDAQAB
-----END RSA PUBLIC KEY-----
There's potentially a few issues with your code or the encryption key you're using:
You're using fs.read incorrectly as Node is asynchronous and it needs a callback function to properly read the file.
The encryption key you're using is formatted incorrectly for crypto.publicEncrypt. You must have the proper RSA headers.
I modified your code to use fs.readFile properly instead in the standard Node callback form, and here's an example encryption key in the correct RSA format to use:
var path = require('path');
var crypto = require('crypto');
var fs = require('fs');
var encryptStringWithRsaPublicKey = function(toEncrypt, relativeOrAbsolutePathToPublicKey, callback) {
var absolutePath = path.resolve(relativeOrAbsolutePathToPublicKey);
fs.readFile(absolutePath, 'utf-8', (err, publicKey) => {
// The value of `publicKey` is in the callback, not the return value
console.log(publicKey);
var buffer = Buffer.from(toEncrypt);
var encrypted = crypto.publicEncrypt(publicKey, buffer);
if (err) {
callback(err);
} else {
callback(null, encrypted.toString("base64"));
}
});
};
encryptStringWithRsaPublicKey('hello world', 'test.pub', (err, encrypted) => {
// If you're using a callback in a function,
// the original function must have a callback as well
console.log(encrypted);
});
Example encryption key at test.pub (must have the RSA headers as shown below):
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA+xGZ/wcz9ugFpP07Nspo6U17l0YhFiFpxxU4pTk3Lifz9R3zsIsu
ERwta7+fWIfxOo208ett/jhskiVodSEt3QBGh4XBipyWopKwZ93HHaDVZAALi/2A
+xTBtWdEo7XGUujKDvC2/aZKukfjpOiUI8AhLAfjmlcD/UZ1QPh0mHsglRNCmpCw
mwSXA9VNmhz+PiB+Dml4WWnKW/VHo2ujTXxq7+efMU4H2fny3Se3KYOsFPFGZ1TN
QSYlFuShWrHPtiLmUdPoP6CV2mML1tk+l7DIIqXrQhLUKDACeM5roMx0kLhUWB8P
+0uj1CNlNN4JRZlC7xFfqiMbFRU9Z4N6YwIDAQAB
-----END RSA PUBLIC KEY-----
As of 2020, there are also other ways of making the code cleaner, such as with using the Promises version of the fs module and async / await, though I wanted to keep this answer as simple as possible for now.

Can I remove all break lines except the first and last one from jwt key

I generated jwt key (RSA Key: private and public) using the following commands
openssl genrsa -out private.key 2048
openssl rsa -in private.key -pubout -out public.key
After that, I created a file called private2.key, I gave it the same private.key content (the only difference is that I removed all break lines except the first and last one)
Also, I created a file called public2.key, I gave it the same public.key content (the only difference is that I removed all break lines except the first and last one)
private.key:
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAy6fZ1JmG4BX02R2Odj/zso7hJwq7qsTZs6SVcNdiHeDxCRT5
UQvTO/qxSIips89iyDTahPjFaquTvmF+oTTOXqA80SYtE8JK2r2/QJ9te5je/7jB
8yxrRsp5heZ4uQv9yThygvOTItuHDN+w4Le2QReegunRDnbfTrsogwUmVAyam4qF
iBDx3zEoTp98H4lRYB4Mpekt0Z2fh8q4g1vBaJLSc+Vc8MXLXsuQTNZ0x61fV7p9
3ewJAHlSxNYRdEFuhNMjU7hp2DR6zQqqyEWslFyq0JW6pd7hHjuCSoBcW5e4lrEg
ZgLspbWbl0rlIOQFizy+IJumXKDmM90WHp2v9wIDAQABAoIBAQDDiSmw4qeJSAuK
2sIJ72VAr8amAbwmPlL4FLIXYfUm0u8a1TR8CGqMUCsfhXfK2PfzWivlOCX0QUDd
riYzCcyLNjauaYUmT4onc7/JgElSPnj99prhrGhj08vSMHMA2O6W4Mexy8Qd18FX
Lv9ZA4rN/KuI7o524NOPeEtxYORoFOslq02PBBuPxTToRs2f++px1HOkLQBt+Mkn
Lqh/gK+0w4CD3JDc/yM2jH4z8jZw8E33vmMGdj59mjhsVlgvOine0mvZnJRU9BWS
sgdtHwnbBIuQBkiXaMWgY83rrP/hSCCcCcKUNyUgxtlWwMcSZrM/gkt2tts7EkRD
e8evVvMhAoGBAO0leVSvjQ8NVqNQajV+o6Z58j2WVTOFG4qZWhuQA4O0oNT4Gcf4
w+DYLQKntmwQ9ShWciw/f0nJCTknCSo0TVmIl5yhJVtudWlIosMw6YerpK7VW+6x
J53ZkHn+6EGgBEYuJjHXFw+vY3VnOmsqO3yCON2oUtw2RA1/tLkiJqZzAoGBANvY
wa5e8dHpdqVKQX1YZFkA1O8y20lDNgGZNz/8qiY21kmMiVAXsTK9wWiF7Uys/jp0
btwWY3u/MHpzP/zz0OTcOJ5b9u+NVcSYzF6FrUGGpOrb9Oh124x2UCKL9exsz8xJ
av4PGfof8uhPGxRSav+DqbmrY+jqVuz1Dn3YnqttAoGAJPPF6DBCpqnJakFJi3Rk
Q7iUyov2UsTW+c3TgJ/8LDWlKgpO2h4lR4/n05YWkthBmzt9Ju/uAa1VxpYSk4T6
2Iy0My/ZBlo76V/sHMYuXXmde7C7VoI8ThhsrtXNkwxAHj9qrDF74nHN6algLPqz
sj8IZWGpJ689A21217I+m4kCgYA21VdpgHDcJFjdXSn8c4GD2XtCtfKP0V21BFwN
b52YrnDAI3dULLSbrUyCH3VSfItkVQoZhtQFV2hmAjzhgIaHro3IobNziFLuGBZR
NRJDl6umkHoDSPIblJ7kHviVoYYqs90lxOp7wmA5pRFh/jSFyncYwjDHNTu9Glok
9VSN+QKBgDdjjMY41JU21fv2FWvKCwHXJwRSFVT8HNlMC0H9k6x2SZAmhNBtfIlU
xY5I5Cnsmkvw2zNxhS2conLAElKqoVSUprv6BvjW+p80dXisctfMTpv/2YM/o0Fs
Iu1ySS+kMK9OAb2kqz9uL38srfN5zdp3FNLrMaE4uRBei8y51D1/
-----END RSA PRIVATE KEY-----
private2.key:
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAy6fZ1JmG4BX02R2Odj/zso7hJwq7qsTZs6SVcNdiHeDxCRT5UQvTO/qxSIips89iyDTahPjFaquTvmF+oTTOXqA80SYtE8JK2r2/QJ9te5je/7jB8yxrRsp5heZ4uQv9yThygvOTItuHDN+w4Le2QReegunRDnbfTrsogwUmVAyam4qFiBDx3zEoTp98H4lRYB4Mpekt0Z2fh8q4g1vBaJLSc+Vc8MXLXsuQTNZ0x61fV7p93ewJAHlSxNYRdEFuhNMjU7hp2DR6zQqqyEWslFyq0JW6pd7hHjuCSoBcW5e4lrEgZgLspbWbl0rlIOQFizy+IJumXKDmM90WHp2v9wIDAQABAoIBAQDDiSmw4qeJSAuK2sIJ72VAr8amAbwmPlL4FLIXYfUm0u8a1TR8CGqMUCsfhXfK2PfzWivlOCX0QUDdriYzCcyLNjauaYUmT4onc7/JgElSPnj99prhrGhj08vSMHMA2O6W4Mexy8Qd18FXLv9ZA4rN/KuI7o524NOPeEtxYORoFOslq02PBBuPxTToRs2f++px1HOkLQBt+MknLqh/gK+0w4CD3JDc/yM2jH4z8jZw8E33vmMGdj59mjhsVlgvOine0mvZnJRU9BWSsgdtHwnbBIuQBkiXaMWgY83rrP/hSCCcCcKUNyUgxtlWwMcSZrM/gkt2tts7EkRDe8evVvMhAoGBAO0leVSvjQ8NVqNQajV+o6Z58j2WVTOFG4qZWhuQA4O0oNT4Gcf4w+DYLQKntmwQ9ShWciw/f0nJCTknCSo0TVmIl5yhJVtudWlIosMw6YerpK7VW+6xJ53ZkHn+6EGgBEYuJjHXFw+vY3VnOmsqO3yCON2oUtw2RA1/tLkiJqZzAoGBANvYwa5e8dHpdqVKQX1YZFkA1O8y20lDNgGZNz/8qiY21kmMiVAXsTK9wWiF7Uys/jp0btwWY3u/MHpzP/zz0OTcOJ5b9u+NVcSYzF6FrUGGpOrb9Oh124x2UCKL9exsz8xJav4PGfof8uhPGxRSav+DqbmrY+jqVuz1Dn3YnqttAoGAJPPF6DBCpqnJakFJi3RkQ7iUyov2UsTW+c3TgJ/8LDWlKgpO2h4lR4/n05YWkthBmzt9Ju/uAa1VxpYSk4T62Iy0My/ZBlo76V/sHMYuXXmde7C7VoI8ThhsrtXNkwxAHj9qrDF74nHN6algLPqzsj8IZWGpJ689A21217I+m4kCgYA21VdpgHDcJFjdXSn8c4GD2XtCtfKP0V21BFwNb52YrnDAI3dULLSbrUyCH3VSfItkVQoZhtQFV2hmAjzhgIaHro3IobNziFLuGBZRNRJDl6umkHoDSPIblJ7kHviVoYYqs90lxOp7wmA5pRFh/jSFyncYwjDHNTu9Glok9VSN+QKBgDdjjMY41JU21fv2FWvKCwHXJwRSFVT8HNlMC0H9k6x2SZAmhNBtfIlUxY5I5Cnsmkvw2zNxhS2conLAElKqoVSUprv6BvjW+p80dXisctfMTpv/2YM/o0FsIu1ySS+kMK9OAb2kqz9uL38srfN5zdp3FNLrMaE4uRBei8y51D1/
-----END RSA PRIVATE KEY-----
public.key:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy6fZ1JmG4BX02R2Odj/z
so7hJwq7qsTZs6SVcNdiHeDxCRT5UQvTO/qxSIips89iyDTahPjFaquTvmF+oTTO
XqA80SYtE8JK2r2/QJ9te5je/7jB8yxrRsp5heZ4uQv9yThygvOTItuHDN+w4Le2
QReegunRDnbfTrsogwUmVAyam4qFiBDx3zEoTp98H4lRYB4Mpekt0Z2fh8q4g1vB
aJLSc+Vc8MXLXsuQTNZ0x61fV7p93ewJAHlSxNYRdEFuhNMjU7hp2DR6zQqqyEWs
lFyq0JW6pd7hHjuCSoBcW5e4lrEgZgLspbWbl0rlIOQFizy+IJumXKDmM90WHp2v
9wIDAQAB
-----END PUBLIC KEY-----
public2.key:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy6fZ1JmG4BX02R2Odj/zso7hJwq7qsTZs6SVcNdiHeDxCRT5UQvTO/qxSIips89iyDTahPjFaquTvmF+oTTOXqA80SYtE8JK2r2/QJ9te5je/7jB8yxrRsp5heZ4uQv9yThygvOTItuHDN+w4Le2QReegunRDnbfTrsogwUmVAyam4qFiBDx3zEoTp98H4lRYB4Mpekt0Z2fh8q4g1vBaJLSc+Vc8MXLXsuQTNZ0x61fV7p93ewJAHlSxNYRdEFuhNMjU7hp2DR6zQqqyEWslFyq0JW6pd7hHjuCSoBcW5e4lrEgZgLspbWbl0rlIOQFizy+IJumXKDmM90WHp2v9wIDAQAB
-----END PUBLIC KEY-----
When I generated jwt using private.key or private2.key and I verified it using public.key or public2.key I got a successful result
const fs = require('fs');
const jwt = require('jsonwebtoken');
const privateKey = fs.readFileSync('./private.key');
const publicKey = fs.readFileSync('./public.key');
const privateKey2 = fs.readFileSync('./private2.key');
const publicKey2 = fs.readFileSync('./public2.key');
const token = jwt.sign({foo: 'bar'}, privateKey, {algorithm: 'RS256'});
console.log(jwt.verify(token, publicKey)); // RESULT IS: { foo: 'bar', iat: 1580192807 }
console.log(jwt.verify(token, publicKey2)); // RESULT IS: { foo: 'bar', iat: 1580192807 }
const token2 = jwt.sign({foo: 'bar'}, privateKey2, {algorithm: 'RS256'});
console.log(jwt.verify(token2, publicKey)); // RESULT IS: { foo: 'bar', iat: 1580192807 }
console.log(jwt.verify(token2, publicKey2)); // RESULT IS: { foo: 'bar', iat: 1580192807 }
My question is: Scientifically is "remove all break lines except the first and last one from jwt key (RSA Key: private and public)" does not affect the jwt, is this way safe (please provide references that prove your answer)
So I can do this (with comfortable feel)
.env
JWT_PRIVATE_KEY=MIIEowIBAAKCAQEAy6fZ1JmG4BX02R2Odj/zso7hJwq7qsTZs6SVcNdiHeDxCRT5UQvTO/qxSIips89iyDTahPjFaquTvmF+oTTOXqA80SYtE8JK2r2/QJ9te5je/7jB8yxrRsp5heZ4uQv9yThygvOTItuHDN+w4Le2QReegunRDnbfTrsogwUmVAyam4qFiBDx3zEoTp98H4lRYB4Mpekt0Z2fh8q4g1vBaJLSc+Vc8MXLXsuQTNZ0x61fV7p93ewJAHlSxNYRdEFuhNMjU7hp2DR6zQqqyEWslFyq0JW6pd7hHjuCSoBcW5e4lrEgZgLspbWbl0rlIOQFizy+IJumXKDmM90WHp2v9wIDAQABAoIBAQDDiSmw4qeJSAuK2sIJ72VAr8amAbwmPlL4FLIXYfUm0u8a1TR8CGqMUCsfhXfK2PfzWivlOCX0QUDdriYzCcyLNjauaYUmT4onc7/JgElSPnj99prhrGhj08vSMHMA2O6W4Mexy8Qd18FXLv9ZA4rN/KuI7o524NOPeEtxYORoFOslq02PBBuPxTToRs2f++px1HOkLQBt+MknLqh/gK+0w4CD3JDc/yM2jH4z8jZw8E33vmMGdj59mjhsVlgvOine0mvZnJRU9BWSsgdtHwnbBIuQBkiXaMWgY83rrP/hSCCcCcKUNyUgxtlWwMcSZrM/gkt2tts7EkRDe8evVvMhAoGBAO0leVSvjQ8NVqNQajV+o6Z58j2WVTOFG4qZWhuQA4O0oNT4Gcf4w+DYLQKntmwQ9ShWciw/f0nJCTknCSo0TVmIl5yhJVtudWlIosMw6YerpK7VW+6xJ53ZkHn+6EGgBEYuJjHXFw+vY3VnOmsqO3yCON2oUtw2RA1/tLkiJqZzAoGBANvYwa5e8dHpdqVKQX1YZFkA1O8y20lDNgGZNz/8qiY21kmMiVAXsTK9wWiF7Uys/jp0btwWY3u/MHpzP/zz0OTcOJ5b9u+NVcSYzF6FrUGGpOrb9Oh124x2UCKL9exsz8xJav4PGfof8uhPGxRSav+DqbmrY+jqVuz1Dn3YnqttAoGAJPPF6DBCpqnJakFJi3RkQ7iUyov2UsTW+c3TgJ/8LDWlKgpO2h4lR4/n05YWkthBmzt9Ju/uAa1VxpYSk4T62Iy0My/ZBlo76V/sHMYuXXmde7C7VoI8ThhsrtXNkwxAHj9qrDF74nHN6algLPqzsj8IZWGpJ689A21217I+m4kCgYA21VdpgHDcJFjdXSn8c4GD2XtCtfKP0V21BFwNb52YrnDAI3dULLSbrUyCH3VSfItkVQoZhtQFV2hmAjzhgIaHro3IobNziFLuGBZRNRJDl6umkHoDSPIblJ7kHviVoYYqs90lxOp7wmA5pRFh/jSFyncYwjDHNTu9Glok9VSN+QKBgDdjjMY41JU21fv2FWvKCwHXJwRSFVT8HNlMC0H9k6x2SZAmhNBtfIlUxY5I5Cnsmkvw2zNxhS2conLAElKqoVSUprv6BvjW+p80dXisctfMTpv/2YM/o0FsIu1ySS+kMK9OAb2kqz9uL38srfN5zdp3FNLrMaE4uRBei8y51D1/
JWT_PUBLIC_KEY=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy6fZ1JmG4BX02R2Odj/zso7hJwq7qsTZs6SVcNdiHeDxCRT5UQvTO/qxSIips89iyDTahPjFaquTvmF+oTTOXqA80SYtE8JK2r2/QJ9te5je/7jB8yxrRsp5heZ4uQv9yThygvOTItuHDN+w4Le2QReegunRDnbfTrsogwUmVAyam4qFiBDx3zEoTp98H4lRYB4Mpekt0Z2fh8q4g1vBaJLSc+Vc8MXLXsuQTNZ0x61fV7p93ewJAHlSxNYRdEFuhNMjU7hp2DR6zQqqyEWslFyq0JW6pd7hHjuCSoBcW5e4lrEgZgLspbWbl0rlIOQFizy+IJumXKDmM90WHp2v9wIDAQAB
index.js
require('dotenv').config();
const jwt = require('jsonwebtoken');
const privateKey = `-----BEGIN RSA PRIVATE KEY-----\n${process.env.JWT_PRIVATE_KEY}\n-----END RSA PRIVATE KEY-----`;
const publicKey = `-----BEGIN PUBLIC KEY-----\n${process.env.JWT_PUBLIC_KEY}\n-----END PUBLIC KEY-----`;
const token = jwt.sign({foo: 'bar'}, privateKey, {algorithm: 'RS256'});
console.log(jwt.verify(token, publicKey)); // RESULT IS: { foo: 'bar', iat: 1580192822 }
It depends.
Theoretically, the answer is no - you can't always remove the line breaks. This is simply because RFC 1421 defines situations in which you must include the line breaks:
Text lines, delimited by the character pair <CR><LF>, must be no more than 1000 characters long.
The above statement is in Section 4.3 of RFC 1421, the document where the PEM format is defined.
Practically, however, the answer is generally yes: a number of common implementations are quite lenient when parsing objects in PEM format and allow for excessively long text lengths. Specifically, OpenSSL and the Golang PEM implementation allow this (or, at least lengths longer than 1000 characters).
Try running this command on one of your certificates with the line breaks removed - it succeeds:
openssl x509 -text -noout -in certificate.crt
What should you do?
Don't concern yourself with this problem and instead store your certificates external to your application. They should be configuration values and stored externally from your application. Even better, delegate this problem to a technology that is designed to deal with it - Azure has Key Vault, AWS has Certificate Manager and KMS.

node-forge how to read a private rsa key from file

This question is related to Issue using RSA encryption in javascript
I have a node script that I am trying to read a PEM RSA private key from a file:
const forge = require('node-forge');
const fs = require('fs');
const path = require('path');
let pkey = fs.readFileSync(path.join(__dirname, 'test.key'), 'utf8');
//let pkeyDer = forge.util.decode64(pkey); // since it's not base64 encoded, i suppose don't need to decode
let pkeyAsn1 = forge.asn1.fromDer(pkey);
let privateKey = forge.pki.privateKeyFromAsn1(pkeyAsn1);
The test.key file has a format like this:
-----BEGIN RSA PRIVATE KEY-----
{mumbo jumbo line1}
{mumbo jumbo line2}
...
-----END RSA PRIVATE KEY-----
When I tried to import the file, the line fails at pkeyAsn1 = forge.asn1.fromDer(pkey);, giving this error:
Too few bytes to read ASN.1 value.
I don't know too much about the file format, would somebody help me?
The private key file i generated is using the following openssl command:
openssl rsa -in encrypted_test.key -out test.key and I entered my passphrase to decrypt such rsa key.
Read pkey as bytes and use forge.pki.privateKeyFromPem.
Working code:
const forge = require('node-forge');
const fs = require('fs');
const path = require('path');
let pkey = fs.readFileSync(path.join(__dirname, 'test.key'));
let privateKey = forge.pki.privateKeyFromPem(pkey);
I think i figured it out. When reading a private key file, you must include the ---BEGIN RSA PRIVATE KEY--- and ---END RSA PRIVATE KEY--- banner.

Resources