NodeJS загружает сертификат PFX из файла

Я пишу небольшой проект с использованием Node.JS и TypeScript, одна из требований - прочитать сертификат PFX из файла.pfx и использовать его в коде для шифрования тела полезной нагрузки.

У меня есть файл сертификата открытого / закрытого ключа cert1.pfxмой код требует этот сертификат, как показано ниже

...
const cert = loadPfx("cert1.pfx");
const p: Payload = new Payload();
p.addReaderCertificate(cert);
...

Я искал вокруг, но не могу найти способ загрузить PFX для моего варианта использования, я видел примеры загрузки PFX для HTTPS-сервера или Express.JS, я смотрел node-x509, но это для сертификатов CER или PEM в кодировке BASE64 Я также посмотрел на node-rsa, но это для шифрования / дешифрования с использованием открытых / закрытых ключей.

Кто-нибудь знает возможно ли это? Если это так, буду признателен за некоторые советы о том, как достичь.

5 ответов

Поэтому после МНОГО исследований и траления в архивах Google я наткнулся на пакет под названием pem и это имеет следующий метод:

pem.readPkcs12(bufferOrPath, [options], callback)

Это может прочитать файл PKCS#12 (или другими словами *.pfx или же *.p12 файл) среди прочего, я, должно быть, пропустил это в моих предыдущих исследованиях.

Использование:

const pem = require("pem");
const fs = require("fs");

const pfx = fs.readFileSync(__dirname + "/test.pfx");
pem.readPkcs12(pfx, { p12Password: "password" }, (err, cert) => {
    console.log(cert);
});

Выход:

{ cert: "...", ca: ["subca", "rootca"], key: "..." }

Вы можете найти больше здесь и здесь.

Похоже, вам нужно использовать только собственные возможности Node по протоколу https. Node может читать файл PFX напрямую. ( Https.createServer, Параметры SSL)

Пример с сайта Node.js:

const https = require('https');
const fs = require('fs');

const options = {
  pfx: fs.readFileSync('test/fixtures/test_cert.pfx'),
  passphrase: 'sample'
};

https.createServer(options, (req, res) => {
  res.writeHead(200);
  res.end('hello world\n');
}).listen(8000);

Я также застрял на аналогичной проблеме. Решение @neil-stevens помогло мне прочитать файл.pfx, но я обнаружил одну функцию / ошибку (я точно не знаю, что это такое) pem, которая в основном возвращает зашифрованный закрытый ключ в RSA, но если вам нужен реальный закрытый ключ, вам нужно экспортировать зашифрованный ключ в pkcs8, что можно сделать с помощью Node RSA.

Применение:

const RSAKey = cert.key; const key = new NodeRSA(RSAKey); const privateKey = key.exportKey("pkcs8");

Я прибыл сюда, пытаясь найти способ настроить локальный веб-сервер с HTTPS для локальной разработки с использованием сертификата разработки, сгенерированного .NET CLI (поскольку его легко создать/доверить/удалить).

Благодаря ответу Нила Стивена я смог создать рабочее решение для Windows, используя комбинацию npm, dotnetинтерфейс командной строки, opensslи пакет npm pem.

Gitпоставляется с копией OpenSSL, поэтому мне не нужно было устанавливать его отдельно :)

.env

      OPENSSL_PATH=C:\Program Files\Git\usr\bin\openssl
CERT_PASSWORD=SecurePassword123
CERT_PFX=cert/localhost.pfx
CERT_PEM=cert/localhost.pem
CERT_KEY=cert/localhost.key
PORT=443
ENTRYPOINT=src/index.html

пакет.json

      "scripts": {
  "start": "env-cmd -x parcel $ENTRYPOINT --https --cert $CERT_PEM --key $CERT_KEY --port $PORT --open",
  "build": "env-cmd -x parcel build $ENTRYPOINT",
  "dev-certs": "run-s dev-certs:create dev-certs:convert",
  "dev-certs:create": "env-cmd -x dotnet dev-certs https -ep $CERT_PFX -p $CERT_PASSWORD --verbose --trust",
  "dev-certs:convert": "node ./cli/cert.mjs",
  "dev-certs:clean": "dotnet dev-certs https --clean"
},

сертификат.mjs

      import pem from "pem";
import { PFX2PEM } from "pem/lib/convert.js";
import fs from "fs";
import "dotenv/config";

pem.config({
  pathOpenSSL: process.env.OPENSSL_PATH
});

const pass = process.env.CERT_PASSWORD;

// GET .KEY FILE - without this, HMR won't work
const pfx = fs.readFileSync(process.env.CERT_PFX);
pem.readPkcs12(pfx, { p12Password: pass }, (err, cert) => {
  if (!!err) {
    console.error(err);
    return;
  }
  // console.log(cert.key);
  fs.writeFileSync(process.env.CERT_KEY, cert.key);
});

// GET .PEM FILE
PFX2PEM(process.env.CERT_PFX, process.env.CERT_PEM, pass, (errPem, successPem) => {
  if (!successPem) {
    console.error(errPem);
    return;
  }
  
  console.log(`Certificate '${process.env.CERT_PEM}' created!`);
});

Репозиторий находится здесь: https://github.com/zplume/parcel-https и READMEсодержит подробную информацию о том, как это работает.

Дополняя ответ Нила Стивенса (извините, не знаю, как цитировать).

  • У меня была проблема с получением только пустого объекта, но я просто заметил, что не регистрировал ошибку . Так что я сделал это, после этого я смог решить свои проблемы

1º Вам необходимо установить openSSL или libressl, как описано на https://github.com/Dexus/pem.

  • Совет: Для установки, если вы уже настроили и установили Chocolatey. Просто запустите команду: «choco install openssl». (с повышенными правами)

2º Мне пришлось использовать pem.config(), чтобы установить точный путь к папке openSSL. Я думаю, вы также можете определить переменные среды, я просто еще не тестировал этот способ.

3º Наконец, мой код остался таким:

      const pem = require("pem");
const fs = require("fs");
const pfx = fs.readFileSync("./cert.pfx");
let certificate = '';

pem.config({
  pathOpenSSL: 'C:\\Program Files\\OpenSSL-Win64\\bin\\openssl'
})

const getPrivateKey = async () => {
  return new Promise(async (resolve, reject) => {
    pem.readPkcs12(pfx, { p12Password: 'myPassWordStr' }, (err, cert) => {
      console.log('err::: ', err);
      // console.log('cert::: ', cert);
      resolve(cert);
    });
  });
}

const start = async () => {
  certificate = await getPrivateKey();
  console.log('privateKey::: ', certificate);
}

start();
Другие вопросы по тегам