Node.js v6.2.2 crypto.createCipheriv“密钥长度无效”错误

时间:2022-10-20 18:29:58

Below is the source for multipassify.

以下是multipassify的来源。

The code works perfectly below Node 6 and gives an error onward.

该代码在节点6下完美地工作,并向前发出错误。

The error looks like this:

错误如下所示:

crypto.js:184
  this._handle.initiv(cipher, toBuf(key), toBuf(iv));
               ^

Error: Invalid key length
    at Error (native)
    at new Cipheriv (crypto.js:184:16)
    at Object.Cipheriv (crypto.js:182:12)
    at multipassify.encrypt (/Users/thomasreggi/Desktop/super-octopus/node_modules/multipassify/multipassify.js:52:25)
    at multipassify.encode (/Users/thomasreggi/Desktop/super-octopus/node_modules/multipassify/multipassify.js:28:27)
    at Object.<anonymous> (/Users/thomasreggi/Desktop/super-octopus/multi.js:8:26)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)

Here's the source.

这是来源。

var crypto = require('crypto');

var BLOCK_SIZE = 16;

var multipassify = module.exports = function(secret) {
    if (!(this instanceof multipassify)) return new multipassify(secret);
    if (!(typeof secret == 'string' && secret.length > 0)) throw new Error('Invalid Secret');

    // Use the Multipass secret to derive two cryptographic keys,
    // one for encryption, one for signing
    var hash = crypto.createHash("sha256").update(secret).digest('binary');
    this._encryptionKey = hash.substring(0, BLOCK_SIZE);
    this._signingKey = hash.substring(BLOCK_SIZE, 32);
    return this;
};

multipassify.prototype.encode = function(obj) {
    if (!obj) return;

    // Store the current time in ISO8601 format.
    // The token will only be valid for a small timeframe around this timestamp.
    obj["created_at"] = new Date().toISOString();

    // Serialize the customer data to JSON and encrypt it
    var cipherText = this.encrypt(JSON.stringify(obj));

    // Create a signature (message authentication code) of the ciphertext
    // and encode everything using URL-safe Base64 (RFC 4648)
    var token = new Buffer(cipherText + this.sign(cipherText),'binary').toString('base64');
    token = token.replace(/\+/g, '-') // Replace + with -
        .replace(/\//g, '_'); // Replace / with _

    return token;
};

multipassify.prototype.generateUrl = function(obj, domain) {
    if(!domain) return;
    return "https://" + domain + "/account/login/multipass/" + this.encode(obj);
};

multipassify.prototype.sign = function (data) {
    var signed = crypto.createHmac("SHA256", this._signingKey).update(data).digest('binary');
    return signed;
}

multipassify.prototype.encrypt = function(plaintext) {
    // Use a random IV
    var iv = crypto.randomBytes(BLOCK_SIZE);
    var cipher = crypto.createCipheriv('aes-128-cbc', this._encryptionKey,iv);

    // Use IV as first block of ciphertext
    var encrypted = iv.toString('binary') + cipher.update(plaintext, 'utf8', 'binary') + cipher.final('binary');
    return encrypted;
}

I've tried messing around with converting the hash and this._encryptionKey to binary. Using this github issue as a guide but I'm having no luck trying to get this working with Node 6. Anyone know an easy way to get this working with later versions of node?

我已经尝试过将hash和this._encryptionKey转换为二进制文件。使用这个github问题作为指南,但我没有运气试图让这个与Node 6一起工作。任何人都知道一个简单的方法来使用更高版本的节点吗?

1 个解决方案

#1


1  

Came across the fix in a fork of the repo.

在repo的一个分叉中遇到了修复。

https://github.com/achinn/multipassify/blob/176c7664c8458cdfb8f20fac97fe27b7b7d1bff4/multipassify.js

All of the "binary" statements are removed because I believe it's the default, so no sense in switching back and forth.

所有的“二进制”语句都被删除了,因为我认为它是默认的,所以来回切换没有任何意义。

I also noticed that Buffer.concat([value, value]) is being used over new Buffer(value + value).

我还注意到Buffer.concat([value,value])正在使用新的Buffer(value + value)。

var crypto = require('crypto');

var BLOCK_SIZE = 16;

var multipassify = module.exports = function(secret) {
    if (!(this instanceof multipassify)) return new multipassify(secret);
    if (!(typeof secret == 'string' && secret.length > 0)) throw new Error('Invalid Secret');

    // Use the Multipass secret to derive two cryptographic keys,
    // one for encryption, one for signing
    var hash = crypto.createHash("sha256").update(secret).digest();
    this._encryptionKey = hash.slice(0, BLOCK_SIZE);
    this._signingKey = hash.slice(BLOCK_SIZE, 32);
    return this;
};

multipassify.prototype.encode = function(obj) {
    if (!obj) return;

    // Store the current time in ISO8601 format.
    // The token will only be valid for a small timeframe around this timestamp.
    obj["created_at"] = new Date().toISOString();

    // Serialize the customer data to JSON and encrypt it
    var cipherText = this.encrypt(JSON.stringify(obj));

    // Create a signature (message authentication code) of the ciphertext
    // and encode everything using URL-safe Base64 (RFC 4648)
    var token = Buffer.concat([cipherText, this.sign(cipherText)]).toString('base64');
    token = token.replace(/\+/g, '-') // Replace + with -
        .replace(/\//g, '_'); // Replace / with _

    return token;
};

multipassify.prototype.generateUrl = function(obj, domain) {
    if(!domain) return;
    return "https://" + domain + "/account/login/multipass/" + this.encode(obj);
};

multipassify.prototype.sign = function (data) {
    var signed = crypto.createHmac("SHA256", this._signingKey).update(data).digest();
    return signed;
}

multipassify.prototype.encrypt = function(plaintext) {
    // Use a random IV
    var iv = crypto.randomBytes(BLOCK_SIZE);
    var cipher = crypto.createCipheriv('aes-128-cbc', this._encryptionKey,iv);

    // Use IV as first block of ciphertext
    var encrypted = Buffer.concat([iv, cipher.update(plaintext, 'utf8'), cipher.final()]);
    return encrypted;
}

#1


1  

Came across the fix in a fork of the repo.

在repo的一个分叉中遇到了修复。

https://github.com/achinn/multipassify/blob/176c7664c8458cdfb8f20fac97fe27b7b7d1bff4/multipassify.js

All of the "binary" statements are removed because I believe it's the default, so no sense in switching back and forth.

所有的“二进制”语句都被删除了,因为我认为它是默认的,所以来回切换没有任何意义。

I also noticed that Buffer.concat([value, value]) is being used over new Buffer(value + value).

我还注意到Buffer.concat([value,value])正在使用新的Buffer(value + value)。

var crypto = require('crypto');

var BLOCK_SIZE = 16;

var multipassify = module.exports = function(secret) {
    if (!(this instanceof multipassify)) return new multipassify(secret);
    if (!(typeof secret == 'string' && secret.length > 0)) throw new Error('Invalid Secret');

    // Use the Multipass secret to derive two cryptographic keys,
    // one for encryption, one for signing
    var hash = crypto.createHash("sha256").update(secret).digest();
    this._encryptionKey = hash.slice(0, BLOCK_SIZE);
    this._signingKey = hash.slice(BLOCK_SIZE, 32);
    return this;
};

multipassify.prototype.encode = function(obj) {
    if (!obj) return;

    // Store the current time in ISO8601 format.
    // The token will only be valid for a small timeframe around this timestamp.
    obj["created_at"] = new Date().toISOString();

    // Serialize the customer data to JSON and encrypt it
    var cipherText = this.encrypt(JSON.stringify(obj));

    // Create a signature (message authentication code) of the ciphertext
    // and encode everything using URL-safe Base64 (RFC 4648)
    var token = Buffer.concat([cipherText, this.sign(cipherText)]).toString('base64');
    token = token.replace(/\+/g, '-') // Replace + with -
        .replace(/\//g, '_'); // Replace / with _

    return token;
};

multipassify.prototype.generateUrl = function(obj, domain) {
    if(!domain) return;
    return "https://" + domain + "/account/login/multipass/" + this.encode(obj);
};

multipassify.prototype.sign = function (data) {
    var signed = crypto.createHmac("SHA256", this._signingKey).update(data).digest();
    return signed;
}

multipassify.prototype.encrypt = function(plaintext) {
    // Use a random IV
    var iv = crypto.randomBytes(BLOCK_SIZE);
    var cipher = crypto.createCipheriv('aes-128-cbc', this._encryptionKey,iv);

    // Use IV as first block of ciphertext
    var encrypted = Buffer.concat([iv, cipher.update(plaintext, 'utf8'), cipher.final()]);
    return encrypted;
}