NodeJS:无法登录nodeJS 10.14.2

时间:2019-01-23 18:51:44

标签: javascript node.js encryption public-key-encryption encryption-asymmetric

我阅读了以下https://nodejs.org/api/crypto.html#crypto_class_sign,并试图复制代码:

  

sign.js

const crypto = require('crypto');

const { privateKey, publicKey } = crypto.generateKeyPairSync('ec', {
  namedCurve: 'sect239k1'
});

const sign = crypto.createSign('SHA256');
sign.write('some data to sign');
sign.end();
const signature = sign.sign(privateKey, 'hex');

const verify = crypto.createVerify('SHA256');
verify.write('some data to sign');
verify.end();
console.log(verify.verify(publicKey, signature));
// Prints: true or false

但是它抛出了一个错误

>> node sign.js  
internal/crypto/keygen.js:73
    throw new ERR_INVALID_OPT_VALUE('publicKeyEncoding', publicKeyEncoding);
    ^

TypeError [ERR_INVALID_OPT_VALUE]: The value "undefined" is invalid for option "publicKeyEncoding"
    at parseKeyEncoding (internal/crypto/keygen.js:73:11)
    at check (internal/crypto/keygen.js:240:7)
    at Object.generateKeyPairSync (internal/crypto/keygen.js:53:16)
    at Object.<anonymous> (/Users/norfeldt/Desktop/AsymEnc/sign.js:3:42)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)

更新

我做了以下更改(由@ottomeister建议)

const crypto = require('crypto')

const { privateKey, publicKey } = crypto.generateKeyPairSync('ec', {
  namedCurve: 'sect239k1',
  publicKeyEncoding: { type: 'spki', format: 'der' },
  privateKeyEncoding: { type: 'pkcs8', format: 'der' },
})

const sign = crypto.createSign('SHA256')
sign.write('some data to sign')
sign.end()
const signature = sign.sign(privateKey, 'hex')

const verify = crypto.createVerify('SHA256')
verify.write('some data to sign')
verify.end()
console.log(verify.verify(publicKey, signature))
// Prints: true or false

但是现在它引发了我一个新错误

internal/crypto/sig.js:80
  var ret = this._handle.sign(key, passphrase, rsaPadding, pssSaltLength);

Error: error:0906D06C:PEM routines:PEM_read_bio:no start line
    at Sign.sign (internal/crypto/sig.js:80:26)
    at Object.<anonymous> (/Users/norfeldt/Desktop/AsymEnc/sign.js:12:24)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)
    at startup (internal/bootstrap/node.js:282:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:743:3)

(我不知道这有什么区别,但是我想阅读我用openssl创建的.pem文件)

1 个答案:

答案 0 :(得分:3)

您说您正在使用Node.js版本10,但是链接指向Node.js版本11的文档。版本10的文档位于https://nodejs.org/dist/latest-v10.x/docs/api/crypto.html

在版本11中,作为第二个参数传递给publicKeyEncoding的{​​{1}}对象的privateKeyEncodingoptions属性是可选的。在版本10中,这些属性不是可选的,必须必须指定。您的程序没有提供这些属性,这就是为什么它会崩溃的原因。

如果您更改:

crypto.generateKeyPairSync

收件人:

const { privateKey, publicKey } = crypto.generateKeyPairSync('ec', {
  namedCurve: 'sect239k1'
});

那么您的程序应该更快乐。


更新

好的,我安装了Node 10并运行了程序。 const { privateKey, publicKey } = crypto.generateKeyPairSync('ec', { namedCurve: 'sect239k1', publicKeyEncoding: { type: 'spki', format: 'der' }, privateKeyEncoding: { type: 'pkcs8', format: 'der' } }); 之所以爆炸,是因为如文档中所述,它要求私钥采用PEM格式。它无法处理我原始答案产生的DER格式的私钥。传递给sign.sign()的公钥格式也是如此-它必须是PEM,而不是DER。所以改变这个:

verify.verify()

对此:

const { privateKey, publicKey } = crypto.generateKeyPairSync('ec', {
  namedCurve: 'sect239k1',
  publicKeyEncoding:  { type: 'spki', format: 'der' },
  privateKeyEncoding: { type: 'pkcs8', format: 'der' }
});

也就是说,将const { privateKey, publicKey } = crypto.generateKeyPairSync('ec', { namedCurve: 'sect239k1', publicKeyEncoding: { type: 'spki', format: 'pem' }, privateKeyEncoding: { type: 'pkcs8', format: 'pem' } }); 的两次出现都更改为'der'

这将使您的程序运行而不会引发异常。但是,验证尝试将失败,并且最终'pem'调用写入的报告结果将为console.log()。这是因为程序不会告诉false字符串verify.verify()中使用的编码。要解决此问题并从验证中获得privateKey的结果,请更改:

true

收件人:

verify.verify(publicKey, signature)

匹配verify.verify(publicKey, signature, 'hex') 生成签名时指定的字符串编码。关于这部分的文档不是很清楚,但是从实验来看,如果签名是字符串,那么您必须始终指定字符串的编码。唯一可以跳过此处提供编码的情况是,如果您还在sign.sign()调用中也跳过了编码,这将导致sign.sign()生成为signature而不是生成为字符串。