← Back to list

CMS/PKCS7 Sign Contents With NodeJS

To sign contents, you need to have the following

Allen Kim · 2023-02-06 22:05 · 51 claps · 1.8 min read
#pkcs7 #cms #certificate #nodejs
Open on Medium ↗
Wiki topics: 🌐 · Web Development

CMS/PKCS7 Sign Contents With NodeJS

Photo by Markus Winkler on Unsplash

Photo by Markus Winkler on Unsplash

To sign contents, you need to have the following

  1. A certificate
  2. A private key (associated with #1)

If you don’t have a certificate, let’s create one with openssl . This is the command to generate.

$ openssl req -config example-com.conf -new -x509 -sha256 -newkey rsa:2048 -nodes -keyout example-com.key.pem -days 365 -out example-com.cert.pem

This command requires example-com.conf . You can get the contents from here. example-com.conf (github.com)

$ openssl req -config example-com.conf -new -x509 -sha256 -newkey rsa:2048 -nodes -keyout example-com.key.pem -days 365 -out example-com.cert.pem
.+......+............+..+.+...+..+.......+..+...+...+..................+............+............+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...+....+.........+........+....+...+...........+.+.....+.+...+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*......+...+.+......+.....+.+.....+....+......+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*........+.+.....+...+......+...+......+......+....+...........+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.+......+..+...............+............+.+..+..................+...+.......+...+..+...+....+............+...............+........+...+....+..............+.........+...+...+................+...+..+..................+...+.......+..................+...+..+...+.+...+...........+.......+.........+.....+.........+.......+...............+...+......+...+.....+.......+...+...+..+.+..+...+.+...+.....+......+.+.................................+..+.+...+..+.......+..+...+.+..+.............+.....+.+......+..+.+.....+.........+.......+.....+.........+...............+......+....+..+.......+...+..+...+.......+...........+.+......+........+.......+........+............+...+....+...........+.+...+...........+......+.+...+......+..............+....+........+.......+......+.....+.........+...+...+.........+...+....+.........+...........+.+.........+.....+.............+...+............+.....+.+..............+.+..+.......+.....+...+...+......+....+..+..........+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [NY]:
Locality Name (eg, city) [New York]:
Organization Name (eg, company) [Example, LLC]:
Common Name (e.g. server FQDN or YOUR name) [Example Company]:
Email Address [test@example.com]:

$ ls
example-com.cert.pem    example-com.conf        example-com.key.pem

Now you have a certificate and a private key

  • certificate: example-com.cert.pem
  • private key: example-com.key.pem

Run the following function with the certificate and private key.

const fs = require('fs');
const forge = require('node-forge');

function signPKCS7(content, certOrCertPem, privateKeyAssociatedWithCert) {
  var p7 = forge.pkcs7.createSignedData();
  var cert = forge.pki.certificateFromPem(certOrCertPem);
  var privateKey = forge.pki.privateKeyFromPem(privateKeyAssociatedWithCert);
  p7.content = forge.util.createBuffer(content, 'utf8');
  p7.addCertificate(cert);
  p7.addSigner({
    key: privateKey,
    certificate: cert,
    digestAlgorithm: forge.pki.oids.sha256,
    authenticatedAttributes: [{
      type: forge.pki.oids.contentType,
      value: forge.pki.oids.data
    }, {
      type: forge.pki.oids.messageDigest // value will be auto-populated at signing time
    }, {
      type: forge.pki.oids.signingTime, // value can also be auto-populated at signing time
      value: new Date()
    }]
  });
  p7.sign();
  return forge.pkcs7.messageToPem(p7);
}

const cert = fs.readFileSync('./example-com.cert.pem');
const privKey = fs.readFileSync('./example-com.key.pem');

console.log(signPKCS7('hello-world', cert, privKey));

Result

$ node test.js 
-----BEGIN PKCS7-----
MIIHawYJKoZIhvcNAQcCoIIHXDCCB1gCAQExDzANBglghkgBZQMEAgEFADAaBgkq
hkiG9w0BBwGgDQQLaGVsbG8td29ybGSgggTyMIIE7jCCA9agAwIBAgIUHVYBVt4l
fkipTX1iuS36jQxH5zYwDQYJKoZIhvcNAQELBQAwfzELMAkGA1UEBhMCVVMxCzAJ
BgNVBAgMAk5ZMREwDwYDVQQHDAhOZXcgWW9yazEVMBMGA1UECgwMRXhhbXBsZSwg
TExDMRgwFgYDVQQDDA9FeGFtcGxlIENvbXBhbnkxHzAdBgkqhkiG9w0BCQEWEHRl
c3RAZXhhbXBsZS5jb20wHhcNMjMwMjA2MjE0ODMxWhcNMjQwMjA2MjE0ODMxWjB/
MQswCQYDVQQGEwJVUzELMAkGA1UECAwCTlkxETAPBgNVBAcMCE5ldyBZb3JrMRUw
EwYDVQQKDAxFeGFtcGxlLCBMTEMxGDAWBgNVBAMMD0V4YW1wbGUgQ29tcGFueTEf
MB0GCSqGSIb3DQEJARYQdGVzdEBleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAMPwsz+T7hAx629ERoIN2RDq6V13FxabnfNuONDEqTFn
8iKD0j6YwogRla92OT49Xm7iyfdUp2WD5gxlyJ7T0hW/YNsuCw/34/R0XnlAUdgu
3+a9T8IxDeeu8uSlwM4xV1cQNPZJ70Auhlh/TxUD7Dvz9ePZVYZoP5EJ/kHgndU6
7CGvh3p8GGf7LyrapP+hChhdJnbL3Hlk/P7S4V+SG+jJpCqsIYgeIiwOlvcDB91O
hf7C4aoen59v5rA6FAtKks8NBAyxJvsvOlngwfJ2bvWta+gFe3OMgnrdKUA/IQNs
LI9R4R7PymxVgOEJ3Pmz7xDwqK3uS9sA6hpaLrm9ob0CAwEAAaOCAWAwggFcMB0G
A1UdDgQWBBQ89RpBwU4rqdrGMF0rt3PKmGRcuTCBqAYDVR0jBIGgMIGdoYGEpIGB
MH8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJOWTERMA8GA1UEBwwITmV3IFlvcmsx
FTATBgNVBAoMDEV4YW1wbGUsIExMQzEYMBYGA1UEAwwPRXhhbXBsZSBDb21wYW55
MR8wHQYJKoZIhvcNAQkBFhB0ZXN0QGV4YW1wbGUuY29tghQdVgFW3iV+SKlNfWK5
LfqNDEfnNjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDBKBgNVHREEQzBBggtleGFt
cGxlLmNvbYIPd3d3LmV4YW1wbGUuY29tghBtYWlsLmV4YW1wbGUuY29tgg9mdHAu
ZXhhbXBsZS5jb20wLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENl
cnRpZmljYXRlMA0GCSqGSIb3DQEBCwUAA4IBAQC/GRaiRpYJe3F1b0nx3XGbPFZ8
E1TklipIcP4+Ost9HOVFkl0MtEhSPmQtiw1b4k4E793m+mkS0/1BjDSZeZ3Q/nOi
6u2pHLiwEnNkLojc4v4cWKdxmUP2SC56lrQm/Y1dSJkSUOow/PZ3vcLr/j7W+762
iWEbz4g5BaLsIQMTlwxtKzYyjXSCnpw+EJscxE30OuPlo+l9BypxsDZ2R0Ta4XtJ
Noyz1UOFVV7/pIQFMKj3Lngo81/INpb+S9lQBhT7ZFiLqb6Yi99XvdC99LBYprjW
jNsUgB5tSfKvd3q1ecjumpC+UbSq2ldosSzwBnXKPq8SDeI3Hc54+WKc3B/JMYIC
LjCCAioCAQEwgZcwfzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMREwDwYDVQQH
DAhOZXcgWW9yazEVMBMGA1UECgwMRXhhbXBsZSwgTExDMRgwFgYDVQQDDA9FeGFt
cGxlIENvbXBhbnkxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5jb20CFB1W
AVbeJX5IqU19Yrkt+o0MR+c2MA0GCWCGSAFlAwQCAQUAoGkwGAYJKoZIhvcNAQkD
MQsGCSqGSIb3DQEHATAvBgkqhkiG9w0BCQQxIgQgr6J7RNQ7Aqn+pB0TztwuQBbP
z4fF2/mQ5ZNmmqjOKG0wHAYJKoZIhvcNAQkFMQ8XDTIzMDIwNjIxNTIxMlowDQYJ
KoZIhvcNAQEBBQAEggEAVkvbp+33nyQ02tFV0LQfbmxPnxmmNsdNayKC/z9KWGTz
4Wd8rELrVtLF9FO+W8/IB/ZBNIX/MEROV5EYmjQt1l8A7zLgl0vJdtiMa30jIYVx
4eAEI9Fmq0Q5tHUHrbd5gXddfQb4WUyMeMCBygxkq4j3qOSEMw+o1lfNBFR4yX2i
fLXkOQSSzmQGTpCmAjQr1V2HOfnZllQCH/qimZz7Ex8IDA0ZXplzMDl/zuD2fiKs
aMvkZrPdPb7qvqRCZsJEGbnS89S+dlev++Ua+xOh74i2bZkjGOD4Wb51v+5iPFgi
alNvZ0f5UatbPeVFFMeG/DhPqne7/xEqwLOFiI0mNg==
-----END PKCS7-----

Here is how to extract contents from signed CMS contents

// The following is concatenated string of the previous output without any space
const str = `-----BEGIN PKCS7-----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-----END PKCS7-----`;

const CMS = require('@lapo/extractcms');
const content = CMS.extract(Buffer.from(str, "utf-8"));
console.log(content.toString()); // hello-world

Happy Coding :)

Allen Kim


메타데이터
post_id
720eb8d2c2f7
slug
cms-pkcs7-sign-contents-with-nodejs-720eb8d2c2f7
url
https://medium.com/@allenhwkim/cms-pkcs7-sign-contents-with-nodejs-720eb8d2c2f7
canonical_url
https://medium.com/@allenhwkim/cms-pkcs7-sign-contents-with-nodejs-720eb8d2c2f7
author_url
https://medium.com/@allenhwkim
status
ok
fetched_at
2026-07-26 04:19:54