【问题标题】:Unable to sign a file with nodejs crypto无法使用 nodejs 加密签署文件
【发布时间】:2017-02-03 10:42:17
【问题描述】:

我已经用 nodejs 加密创建了一个私钥,并想用这个密钥签署一个文件。 我的代码如下:

var ecdh = crypto.createECDH('brainpoolP512t1');
        ecdh.generateKeys();
        var key = ecdh.getPrivateKey('buffer');

        var data= fs.readFileSync(req.file.path);
        var sign = crypto.createSign('sha512');
        sign.update(data);
        var signature = sign.sign(key, 'hex');

但我得到了错误:

Error: error:0906D06C:PEM routines:PEM_read_bio:no start line
    at Error (native)
    at Sign.sign (crypto.js:283:26)
    at /....js:32:27
    at Immediate.<anonymous> (/.../node_modules/multer/lib/make-middleware.js:52:37)
    at runCallback (timers.js:578:20)
    at tryOnImmediate (timers.js:554:5)
    at processImmediate [as _immediateCallback] (timers.js:533:5)

我知道这与密钥格式有关,但我不知道如何解决这个问题。有人可以帮忙吗?

更新: 我编辑了 privateKey 以适应 pem 格式:

var KEY_START = '-----BEGIN EC PRIVATE KEY-----\n';
var KEY_END = '\n-----END EC PRIVATE KEY-----';

const ecdh = crypto.createECDH('brainpoolP512t1');
            ecdh.generateKeys();
            var key =KEY_START + ecdh.getPrivateKey('base64') + KEY_END;        
            var data= fs.readFileSync(req.file.path);
            const sign = crypto.createSign('sha512');
            sign.update(data);
            var signature = sign.sign(key, 'hex');

现在我遇到了另一个错误:

Error: error:0D07207B:asn1 encoding routines:ASN1_get_object:header too long
    at Error (native)
    at Sign.sign (crypto.js:283:26)
    at /...js:37:27
    at Immediate.<anonymous> (/.../node_modules/multer/lib/make-middleware.js:52:37)
    at runCallback (timers.js:578:20)
    at tryOnImmediate (timers.js:554:5)
    at processImmediate [as _immediateCallback] (timers.js:533:5)

【问题讨论】:

    标签: node.js header signature private-key elliptic-curve


    【解决方案1】:

    您用来签署数据的密钥必须是有效的 PEM 编码私钥。 DHgetPrivateKey() 函数不返回这种格式的密钥,它返回的是裸私钥数据。

    您的选择包括:

    • 通过 OpenSSL 密钥生成器实用程序或类似工具生成私钥

    • 使用第三方节点模块对私钥进行正确编码,如RFC 5915 中所述。使用 asn1.jsbn.js 模块的完整示例:

        var crypto = require('crypto');
      
        var asn1 = require('asn1.js');
        var BN = require('bn.js');
      
        function toOIDArray(oid) {
          return oid.split('.').map(function(s) {
            return parseInt(s, 10)
          });
        }
      
        // Define ECPrivateKey from RFC 5915
        var ECPrivateKey = asn1.define('ECPrivateKey', function() {
          this.seq().obj(
            this.key('version').int(),
            this.key('privateKey').octstr(),
            this.key('parameters').explicit(0).objid().optional(),
            this.key('publicKey').explicit(1).bitstr().optional()
          );
        });
      
        // Generate the DH keys
        var ecdh = crypto.createECDH('brainpoolP512t1');
        ecdh.generateKeys();
      
        // Generate the PEM-encoded private key
        var pemKey = ECPrivateKey.encode({
          version: new BN(1),
          privateKey: ecdh.getPrivateKey(),
          // OID for brainpoolP512t1
          parameters: toOIDArray('1.3.36.3.3.2.8.1.1.14')
        }, 'pem', { label: 'EC PRIVATE KEY' });
      
        // Sign data
        var sign = crypto.createSign('sha512');
        sign.update('hello world');
        var signature = sign.sign(pemKey, 'hex');
      
        console.log('signature', signature);
      

    【讨论】:

    • 我认为应该有我要签名的文件的文件路径?
    • 如果您想从 DH 私钥生成(在节点内)有效的 PEM 格式密钥,我现在还添加了一个代码示例。
    • 非常感谢!在尝试您的解决方案时,出现错误“TypeError: asn1.define is not a function”。
    • 您是否安装了正确的模块?它应该是asn1.js 而不是asn1
    • 安装了 asn1 而不是 asn1.js,现在可以正常工作了。谢谢你的代码!花很多时间来解决这个问题。
    猜你喜欢
    • 2012-09-22
    • 1970-01-01
    • 1970-01-01
    • 2016-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-06
    • 2015-05-27
    相关资源
    最近更新 更多