web-dev-qa-db-ja.com

NodeJSがメッセージの署名と検証に有効なPEMキーを生成する

環境

Node v10.9.0(2018-AUG)のTLS/SSLに関するNodeJSドキュメントから

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

openssl genrsa -out ryans-key.pem 2048

生成されます:

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

次に、Signクラスを使用してメッセージに暗号で署名できます。

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'));

私は成功せずに以下を試しました:

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);

次のエラーが発生しました:

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

質問

NodeJSのcryptoライブラリを使用して、opensslコマンドラインツール(または別のNPMモジュール)が実行していることを実現して、有効なPEM形式の公開/秘密鍵ペアを作成するにはどうすればよいですか。 Signクラス?

同様の未解決の質問

解決

受け入れられた回答JacobTDC のおかげで、ソリューションを完成させるための開始点は次のとおりです。NodeJSv10.12.0がこの機能を追加しました。

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

Node.js v10.12.0以降、 crypto.generateKeyPair および crypto.generateKeyPairSync を使用できます。

以下のNode.jsドキュメントの例を(コメントを追加して)提供しました。

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

ここでの問題は、DHキーがRSAキーではなく、完全に互換性がないことです。

残念ながら、ノードはcryptoモジュールを介して実際のRSAペアを生成する機能もありませんが、これは少しがっかりです。これを行うには、ローカルのopensslライブラリを操作するか、要件に応じてサードパーティのモジュールを操作する必要があります。

サードパーティのモジュールに関しては、 keypair は、特定の状況で機能する単純なライブラリです

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

openpgpjs でも良い結果が見つかりました。これは、プラットフォームにとらわれないモジュールであることに焦点を当てている一方で、はるかに機能的です。ブラウザとノードの両方で暗号化を実行している場合は、これが適切なオプションになる可能性があります。

1
Ian Belcher