Encrypting a file with Nodejs (Crypto) throw an error: bad base64 decode - node.js

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

Related

Trying to symmetrically encrypt a value for storage in the client (httpOnly cookie) and having an issue decrypting

I am trying to encrypt a value on my server with a private key to store it on the client within an httpOnly cookie.
I am having trouble with the encryption/decryption lifecycle
function encrypt(input) {
const encryptedData = crypto.privateEncrypt(
privateKey,
Buffer.from(input)
)
return encryptedData.toString('base64')
}
function decrypt(input) {
const decryptedData = crypto.privateDecrypt(
{ key: privateKey },
Buffer.from(input, 'base64'),
)
return decryptedData.toString()
}
const enc = encrypt('something moderately secret')
const dec = decrypt(enc)
console.log(dec) // 'something moderately secret'
However the crypto.privateDecrypt function is throwing with
Error: error:04099079:rsa routines:RSA_padding_check_PKCS1_OAEP_mgf1:oaep decoding error
Side question, is it safe to reuse the same private key the server uses to sign JWTs. It's an rsa key generated using ssh-keygen -t rsa -b 4096 -m PEM -f RS256.key
So, you don't use crypto.privateEncrypt() with crypto.privateDecrypt(). That's not how they work. Those functions are for asymmetric encryption, not for symmetric encryption. You use either of these two pairs:
crypto.publicEncrypt() ==> crypto.privateDescrypt()
crypto.privateEncrypt() ==> crypto.publicDecrypt()
So, that's why you're getting the error you're getting. The nodejs doc for crypto.privateDecript() says this:
Decrypts buffer with privateKey. buffer was previously encrypted using the corresponding public key, for example using crypto.publicEncrypt().
If what you really want is symmetric encryption, there are a bunch of options in the crypto module for that. There are some examples shown here: https://www.section.io/engineering-education/data-encryption-and-decryption-in-node-js-using-crypto/ and https://fireship.io/lessons/node-crypto-examples/#symmetric-encryption-in-nodejs.

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.

error:0409A06E:rsa routines data too large for key size

I'm generating a SAML response and it needs to be encrypted and signed with public and private keys. I generated private.pem and public.pem in the terminal with the commands
openssl genrsa -out private.pem 2048
openssl rsa -in ./private.pem -pubout -out public.pem
Then in nodeJS.
encrypt: function(message) {
return new Promise(function (resolve, reject) {
var publicKey = require("fs").readFileSync(__dirname + "/public.pem", "utf8");
var encrypted = require("crypto").publicEncrypt(publicKey, new Buffer(message));
resolve(encrypted.toString("base64"));
});
},
Once I call the message encrypt(xml), I get the following error
{
library: 'rsa routines',
function: 'RSA_padding_add_PKCS1_OAEP_mgf1',
reason: 'data too large for key size',
code: 'ERR_OSSL_RSA_DATA_TOO_LARGE_FOR_KEY_SIZE'
}
Objective:
I've to sign the message as per the demo here samltools.com (Mode: SignMessage), my SAML message looks like this. (see SAML Response section).
Sign the message
Base64Encode the message
The problem here is that you cannot directly encrypted with RSA, a piece of data which is larger than the key size.
Surprising I know, it surprised me too.
In reality very little payload data is encrypted directly with RSA or even elliptic curves.
You should be using RSA Diffie-Hellman to generate a shared secret.
Signature of the file, is really signature of the hash of the file.

How can i pass the base64 string as a input certificate for Openssl?

I have a certificate which i am getting in string . I just want that string to be directly pass as -in in the openssl command.
But i don't see any method in openssl , can you help.
my code
const { exec } = require('child_process');
exec('openssl x509 -noout -issuer -in '+certificateString , (err, stdout, stderr) => {
if (err) {
console.log(err);
}else{
console.log(studout);
}
});
If i directly pass certificate file url it works, like this
openssl x509 -noout -issuer -in certificate.pem
this work
but how can i pass the certificate string directly in openssl ?
Any help?
First, do you have base64 or PEM? Those are not the same thing; although PEM includes base64, it is not only base64. If you have a file that works with openssl x509 -in file then it is PEM, NOT only base64. People seem to look at PEM, see more than 40 base64 characters, and their brains shut down and become unable to see the dashes-BEGIN line, the dashes-END line, and the line breaks, all of which are REQUIRED.
Second, certificate.pem is a filename or pathname, not a URL. A filename or pathname is not a URL, and a URL is not a filename or pathname, although some URL schemes (and particularly the only ones most people notice) include some elements in common with pathnames.
The certificate input to openssl x509 must be either a (named) file, or standard input (commonly abbreviated stdin). If you don't want to supply it as a named file, nodejs can provide data to a child's stdin, but not with the higher-level exec* methods, only the more basic spawn:
const{ spawn } = require('child_process');
const pem = `-----BEGIN CERTIFICATE-----
MIIDUzCCAjugAwIBAgIJANK2Ysp8bp+6MA0GCSqGSIb3DQEBCwUAMEAxCzAJBgNV
BAYTAlVTMQswCQYDVQQIDAJDQTETMBEGA1UEBwwKVGluc2VsdG93bjEPMA0GA1UE
CgwGRGlzbmV5MB4XDTE5MDUwOTA5MTQ0NVoXDTIwMDUwODA5MTQ0NVowQDELMAkG
A1UEBhMCVVMxCzAJBgNVBAgMAkNBMRMwEQYDVQQHDApUaW5zZWx0b3duMQ8wDQYD
VQQKDAZEaXNuZXkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCuKNJI
oBJ6acFSqMlG6e6WS44jC0RP+2y0q+02P4xc9BIuPjKV6/Lkg3bnYenAzktemvc7
EVFOUS/Ema4UIc+aDtSpjAegWnZNrzX+K76Xxzw+RnZalXB1Z++CpTdtsgSmkrmR
wJ7ZZpclAK+Yt6Ggx9ea3/d8WJ85V30ezcG7hPf5BrCSxzjSPsxG3heDPh1/X0zk
H7PD0JB+IW08yOikLmQNZeTZXaIAaSXoIPj5L9Ax7kyDEiDcSBIcQbPGMfIG6CPO
hKOM4yZKWni0mO9jwgfYNU6Bxei35/KTVwBWXHck9N7DdEtoST9THYO7ZFqqvTdk
mLfBpsPXorFT+vAVAgMBAAGjUDBOMB0GA1UdDgQWBBQyXFJDoapFe4JaZBD1xVYE
ImDj7DAfBgNVHSMEGDAWgBQyXFJDoapFe4JaZBD1xVYEImDj7DAMBgNVHRMEBTAD
AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAwFXI13uxhGz+fem7N03r0+dnNaXZQQ9CR
owTHVVOjsfrsbFPhKdZIKMKeqpc1AksqynhbV2zY5VjINMab8ADw165gTCgy8/0S
X3QQsy2P5RNx/YuRMvs6hP7ZhZQlabLVbBnCWqAevT2qEZ7Gmi+m9A9sdK2Hsrkj
0lxGCozscme7E3ZfR/3GQVzyfZVppRLsgIth9F2y6SyLXwi+v39C+a9vdZjMS3Uy
HuRD9Sk8xydWywI8wKBlfnX4KGMBjKpSDpMeb6723eXuPC+soUBafuUoP+fWqjg4
LFgYg1TtyzfdrkkWZ9/KxS47OxkF6BAQtFGVF2nNgcpdXxToK7pP
-----END CERTIFICATE-----
`;
const p = spawn("/path/to/openssl", ["x509","-noout","-issuer"]);
// options.stdio defaults to ['pipe','pipe','pipe']
p.stdout.on('data',(data)=> {console.log(data.toString())} );
p.stderr.on('data',(data)=> {console.log("ERROR:"+data.toString())} );
p.on('close',()=> {} );
p.stdin.write(pem); p.stdin.end();
However, you don't need to run an external program to parse a certificate; there are lots of JS libraries to do it. For example, with the second one npmjs finds for me:
const { Certificate } = require('#fidm/x509');
const { ASN1 } = require('#fidm/asn1');
var iss = Certificate.fromPEM(pem).issuer.attributes;
var s = ""; for(var a of iss){ s += "/" + a.shortName + "=" + a.value; }
console.log(s);
If you actually did have base64 and not PEM, replace the third line with
const bin = Buffer.from(b64,'base64');
var iss = new Certificate(ASN1.fromDER(bin)).issuer.attributes;

Is it possible to verify and sign data in Node.js "native" (without using external call to OpenSSL)?

I have tried to find any package or solution to do a S/MIME sign/verify signature in Node.js but only found solutions using external calls (child process) to OpenSSL.
I need to run my code in AWS Lambda as Node.js so calling OpenSSL binary is not an option...
Is it at all possible to verify and sign X.509 pkcs7-signature S/MIME (Base64) signatures using only Node.js?
Sample public key:
-----BEGIN CERTIFICATE-----
MIIDwzCCAqugAwIBAgIIKHUtBJ7PgSwwDQYJKoZIhvcNAQELBQAwRjELMAkGA1UE
BhMCU0UxEjAQBgNVBAcMCVN0b2NraG9sbTEMMAoGA1UECgwDQVMyMRUwEwYDVQQD
DAx0ZXN0LmFzMi5uZXQwHhcNMTgwMzE0MTI1MTAzWhcNMTkwMzE0MTI1MTAzWjBG
MQswCQYDVQQGEwJTRTESMBAGA1UEBwwJU3RvY2tob2xtMQwwCgYDVQQKDANBUzIx
FTATBgNVBAMMDHRlc3QuYXMyLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBALXXVK5jP9H9JjOe9Iiba1235Xz/WuFUVP5I2Pl1ClkvGlUZRIQrje7K
Ar3OBuh8iOiNko+HuWXN505WvmiVESH9mrSSfXHDUU+JcCDkbNLDFJKiEAeZni6f
cTMMU7eWL/ZwVvAaOVXIjCC6l+nf6+rI9HNIKUpr96iIWDUMot5PQURFNUEg0OQ4
HFsuXtrm8CvbD/v3dj/2nke+HzIra27+2v3hFFP0EPCRz4+okh3a6pWrXnozrmRn
e+FFRH8mq0N0UH1AtiArDpCspnZJEGsquvj2/ruSHCarQpOS12MfPY6uFlGym3fZ
H1AxpDn11KIC3L3iNAMNCh7DWtxyrbcCAwEAAaOBtDCBsTAMBgNVHRMEBTADAQH/
MB0GA1UdDgQWBBTOWGctZLOpraEmeF77hpPcbHzbZzB1BgNVHSMEbjBsgBTOWGct
ZLOpraEmeF77hpPcbHzbZ6FKpEgwRjELMAkGA1UEBhMCU0UxEjAQBgNVBAcMCVN0
b2NraG9sbTEMMAoGA1UECgwDQVMyMRUwEwYDVQQDDAx0ZXN0LmFzMi5uZXSCCCh1
LQSez4EsMAsGA1UdDwQEAwICvDANBgkqhkiG9w0BAQsFAAOCAQEAQNhK/jVm6PRd
ui2ptx0wLd4QD7duPxULfYdhbab+Odp/LbQ08Mp1FZ8JjnJnH/z1H7SH4kPjEHIC
22VDvK1+MAjTq4iPKgpmtBSdC8dJ/S8rNE9nzpfuheM79ES8ERPNTi2Mumq1OM8L
43J+LMVwNyWx4JlI7egJgqzP5NKaPo35pI1Z/71eVGn6uPwlOdP9s8unwtOYSGZ+
mVUwQ/wiGuJ7VsxCeGPpG2rV38zUGQGiOqerkqHCLDL2K3ondA53M/myAhA7M2qP
BNPee9guEEXiI/W038rzPVSE8lETbNEnsTLxCI1uN68tEBRSZlBQwu/r/pOXP3fw
/HaEGP0gsQ==
-----END CERTIFICATE-----
Sample message signed with the matching Private Key:
This is an S/MIME signed message
------FF336B91207E7B459FAC35C0D274B8F8
Content-Type: text/plain
UNB+UNOC:3+esab+postnet+111101:1954+6045++++++'UNH+12011+INVOIC:D:93A:UN:EDIT30'BGM+380::9+006124412+9'DTM+137:20111101:102'UNT+55+12011'UNZ+1+6045'
------FF336B91207E7B459FAC35C0D274B8F8
Content-Type: application/pkcs7-signature; name="smime.p7s"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7s"
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
------FF336B91207E7B459FAC35C0D274B8F8--
Yes, it is possible with a combination of crypto and node-forge!
function verify() {
var crypto = require('crypto');
// pkg_sig is the extracted Signature from the S/MIME
// with added -----BEGIN PKCS7----- around it
var msg = pkcs7.messageFromPem(pkg_sig);
var sig = msg.rawCapture.signature;
// pkg is the "clean" signed data from the S/MIME
var buf = new Buffer(pkg, 'binary');
var verifier = crypto.createVerify("RSA-SHA256");
verifier.update(buf);
var verified = verifier.verify(cert, sig, 'binary');
console.log(verified);
}
function sign() {
/*
// Verified working AW, 2018-03-15
// Signature successfully verified by OPENSSL
openssl smime -verify -in packageCopy.txt -CAfile test.as2.net-sscert.pem
Content-Type: text/plain
UNB+UNOC:3+esab+postnet+111101:1954+6045++++++'UNH+12011+INVOIC:D:93A:UN:EDIT30'BGM+380::9+006124412+9'DTM+137:20111101:102'UNT+55+12011'UNZ+1+6045' Verification successful
*/
var p7 = pkcs7.createSignedData();
p7.content = forge.util.createBuffer(pkg);
p7.addCertificate(cert);
p7.addSigner({
key: forge.pki.privateKeyFromPem(key),
certificate: cert,
digestAlgorithm: forge.pki.oids.sha256
});
p7.sign();
var pem = pkcs7.messageToPem(p7);
console.log(pem);
}

Resources