web-dev-qa-db-fra.com

Utilisation de node.js pour vérifier un certificat X509 avec CA cert

Je cherche un moyen node.js pour vérifier un certificat client au format X509 avec un certificat CA qui m'a été donné (aucun de ceux-ci n'est créé/géré par moi, mon logiciel n'a qu'à vérifier ce qui lui est envoyé) .

J'ai trouvé plusieurs modules pour ce travail, mais j'ai des problèmes avec chacun d'eux:

  • X509 est capable de le faire en utilisant x509.verify(cert, CABundlePath, cb), mais il doit lire les certificats de FS, et je les ai déjà en mémoire. C'est fastidieux car cela se fera à chaque demande Web qui parviendra à mon application.
  • Il semble que PKI.js soit capable de le faire, mais leurs exemples ne fonctionnent pas pour moi mais se plaignent des fichiers manquants, donc je ne peux même pas l'essayer.
  • J'ai essayé node-forge , mais même si je ne sais pas si je l'utilise correctement (ils n'ont pas de documentation API), il génère une erreur forge.pki.BadCertificate De forge.pki.verifyCertificateChain(caStore, [ cer ], cb).
  • Lorsque vous essayez pem , l'utilisation d'une simple pem.verifySigningChain(cer, [ ca ], cb) entraînerait une erreur se plaignant du chargement d'un fichier à partir de /var/.... Même si cela fonctionnait, j'éviterais d'utiliser cette lib car elle s'appuie sur outil de ligne de commande openssl, ce que j'aimerais éviter

Maintenant, je me sens assez stupide parce que je n'ai pas réussi à faire cette tâche simple avec l'un des modules ci-dessus. Quelqu'un pourrait-il m'indiquer une solution simple qui me permettra de vérifier la signature/validité d'un certificat X509 en utilisant un certificat CA donné? : s

[edit] Fondamentalement, j'aurais besoin de openssl verify -verbose -CAfile ca-crt.pem client1-crt.pem dans Node.js mais sans dépendances à l'outil de ligne de commande openssl et sans enregistrer temporairement les certificats sur le disque.

[edit2] Serait-il possible d'utiliser simplement https://nodejs.org/api/crypto.html#crypto_verify_verify_object_signature_signatureformat ?

13
user826955

J'ai finalement réussi à le faire en utilisant node-forge. Voici un exemple de code de travail:

let pki = require('node-forge').pki;
let fs = require('fs');

let caCert;
let caStore;

try {
    caCert = fs.readFileSync('path/to/ca-cert.pem').toString();
    caStore = pki.createCaStore([ caCert ]);
} catch (e) {
    log.error('Failed to load CA certificate (' + e + ')');
    return....;
}

try {
    pki.verifyCertificateChain(caStore, [ cert ]);
} catch (e) {
    return handleResponse(new Error('Failed to verify certificate (' + e.message || e + ')'));
}

Les deux certificats doivent être donnés au format PEM codé en base64/chaîne js.

verifyCertificateChain vérifie la validité du certificat (notBefore/notAfter) ainsi que vérifie la chaîne CA donnée.

Je ne suis pas sûr à 100% si c'est la meilleure approche, ou si cette bibliothèque fait du bon travail, puisque leur code source de verifyCertificateChain est plein de #TODOs, alors peut-être que ce n'est pas prêt pour la production? Mais au moins, j'ai une solution quelque peu efficace. Il serait probablement préférable de créer un module de noeud qui encapsule les appels libssl c, mais c'est juste beaucoup d'efforts pour cette petite tâche.

5
user826955

Vous pouvez également faire cela si vous souhaitez vérifier directement l'utilisation des certificats clients de la demande http:

// retrieve certificates from the request ( in der format )
clientCert = req.connection.getPeerCertificate(true).raw.toString('base64'))

Méthode pour convertir le certificat der en pem et vérifier contre le castore.

  const caCert = fs....
  const ca = pki.certificateFromPem(caCert)
  const caStore = pki.createCaStore([ ca ])

  const verify = (clientCert, next) => {
    try {
      const derKey = forge.util.decode64(clientCert)
      const asnObj = forge.asn1.fromDer(derKey)
      const asn1Cert = pki.certificateFromAsn1(asnObj)
      const pemCert = pki.certificateToPem(asn1Cert)
      const client = pki.certificateFromPem(pemCert)
      return pki.verifyCertificateChain(caStore, [ client ], cb)
    } catch (err) {
      next(new Error(err))
    }
  }

Je n'ai pas trouvé de meilleur moyen de vérifier le certificat "der" du client à partir du request.

fas3r

0
fas3r

Cela fonctionne pour moi:

const fs = require('fs'), pki = require('node-forge').pki
var ca = pki.certificateFromPem(fs.readFileSync('ca.pem', 'ascii'))
var client = pki.certificateFromPem(fs.readFileSync('client.pem', 'ascii'))
try {
    if (!ca.verify(client)) throw 'verify failed'
} catch (err) {
    console.log(err)
}

try/catch était nécessaire, car .verify a généré une erreur (au lieu de renvoyer false) dans mon cas.

0
Joerg Veigel