web-dev-qa-db-fra.com

NodeJS Générer des clés PEM valides pour la signature et la vérification des messages

Le contexte

De la documentation NodeJS sur TLS/SSL pour Node v10.9.0 (2018-AUG))

https://nodejs.org/api/tls.html#tls_tls_ssl_concepts

openssl genrsa -out ryans-key.pem 2048

Produira:

-----BEGIN RSA PRIVATE KEY-----
base64 encoded magic here...
-----END RSA PRIVATE KEY-----

Que je peux ensuite utiliser avec succès la classe Sign pour signer cryptographiquement un message:

https://nodejs.org/api/crypto.html#crypto_class_sign

const crypto = require('crypto');
const sign = crypto.createSign('RSA-SHA256');

sign.update('some data to sign');

const privateKey = `Insert magic value from above`;
console.log(sign.sign(privateKey, 'base64'));

J'ai essayé ce qui suit sans succès:

const crypto = require('crypto');
const dhke = crypto.createDiffieHellman(2048);
dhke.generateKeys();
const private_pem = `-----BEGIN RSA PRIVATE KEY-----
${dhke.getPrivateKey('base64')}
-----END RSA PRIVATE KEY-----`;
console.log(private_pem);

const sign = crypto.createSign('RSA-SHA256');
sign.update('some data to sign');

const signature = sign.sign(private_pem, 'base64');
console.log(signature);

Obtention de l'erreur suivante:

Error: error:0D07207B:asn1 encoding routines:ASN1_get_object:header too long
    at Sign.sign (internal/crypto/sig.js:84:26)
...

La question

Comment utiliser la bibliothèque crypto dans NodeJS pour réaliser ce que l'outil de ligne de commande openssl effectue (ou un autre module NPM) pour créer une paire de clés publique/privée au format PEM valide qui est requise par la classe Sign?

Questions similaires non résolues

Solution

Voici la solution de travail du début à la fin grâce à la réponse acceptée de JacobTDC où NodeJS v10.12.0 a ajouté cette fonctionnalité.

const crypto = require('crypto'); const sign = crypto.createSign('RSA-SHA256');

sign.update('some data to sign');

// $ openssl genrsa -out ryans-key.pem 2048 
// const privateKey = `Insert magic value from above`;

const { generateKeyPairSync } = require('crypto'); 
const { publicKey, privateKey } = generateKeyPairSync('rsa', 
{   modulusLength: 2048,  // the length of your key in bits   
    publicKeyEncoding: {
      type: 'spki',       // recommended to be 'spki' by the Node.js docs
      format: 'pem'   
    },   
    privateKeyEncoding: {
      type: 'pkcs8',      // recommended to be 'pkcs8' by the Node.js docs
      format: 'pem',
      //cipher: 'aes-256-cbc',   // *optional*
      //passphrase: 'top secret' // *optional*   
  } 
}); 
console.log(privateKey); 
console.log(sign.sign(privateKey, 'base64'));
9
Josh Peak

Depuis Node.js v10.12.0, vous pouvez utiliser crypto.generateKeyPair et crypto.generateKeyPairSync .

J'ai fourni un exemple à partir des documents Node.js ci-dessous (avec des commentaires ajoutés):

const { generateKeyPairSync } = require('crypto');
const { publicKey, privateKey } = generateKeyPairSync('rsa', {
  modulusLength: 4096,  // the length of your key in bits
  publicKeyEncoding: {
    type: 'spki',       // recommended to be 'spki' by the Node.js docs
    format: 'pem'
  },
  privateKeyEncoding: {
    type: 'pkcs8',      // recommended to be 'pkcs8' by the Node.js docs
    format: 'pem',
    cipher: 'aes-256-cbc',   // *optional*
    passphrase: 'top secret' // *optional*
  }
});
7
JacobTDC

Le problème ici est que les clés DH ne sont pas des clés RSA et ne sont pas entièrement compatibles.

Malheureusement, node n'a pas non plus la capacité de produire de vraies paires RSA via le module crypto ce qui est un peu décevant. Pour ce faire, vous devrez soit interagir avec votre bibliothèque locale openssl, soit avec un module tiers en fonction de vos besoins.

En ce qui concerne les modules tiers, keypair est une bibliothèque simple qui fonctionnera dans votre situation donnée

const keypair = require('keypair');
const keys: { private: string, public: string } = keypair({ bits : 2056 }); // 2056 is the default but added for example

J'ai également trouvé de bons résultats avec openpgpjs qui est beaucoup plus en vedette tout en se concentrant sur le fait d'être un module indépendant de la plate-forme. Si vous cherchez à faire de la cryptographie dans le navigateur ainsi que dans le nœud, cela pourrait être une bonne option.

1
Ian Belcher