Skip to content

Commit

Permalink
feat: deprecated crypto api (#35)
Browse files Browse the repository at this point in the history
fix the warning: (node:74957) [DEP0106] DeprecationWarning: crypto.createCipher is deprecated.

Co-authored-by: wanghx <whx89768@antgroup.com>
  • Loading branch information
whxaxes and wanghx committed Jun 20, 2022
1 parent a6300d0 commit 7ed0ded
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/nodejs.yml
Expand Up @@ -35,7 +35,7 @@ jobs:
node-version: ${{ matrix.node-version }}

- name: Install Dependencies
run: npm i -g npminstall && npminstall
run: npm i -g npminstall@5 && npminstall

- name: Continuous Integration
run: npm run ci
Expand Down
38 changes: 36 additions & 2 deletions lib/keygrip.js
Expand Up @@ -4,6 +4,9 @@ const debug = require('debug')('egg-cookies:keygrip');
const crypto = require('crypto');
const assert = require('assert');
const constantTimeCompare = require('scmp');
const KEY_LEN = 32;
const IV_SIZE = 16;
const passwordCache = new Map();

const replacer = {
'/': '_',
Expand All @@ -25,7 +28,8 @@ class Keygrip {
// encrypt a message
encrypt(data, key) {
key = key || this.keys[0];
const cipher = crypto.createCipher(this.cipher, key);
const password = keyToPassword(key);
const cipher = crypto.createCipheriv(this.cipher, password.key, password.iv);
return crypt(cipher, data);
}

Expand All @@ -43,7 +47,8 @@ class Keygrip {
}

try {
const cipher = crypto.createDecipher(this.cipher, key);
const password = keyToPassword(key);
const cipher = crypto.createDecipheriv(this.cipher, password.key, password.iv);
return crypt(cipher, data);
} catch (err) {
debug('crypt error', err.stack);
Expand Down Expand Up @@ -80,4 +85,33 @@ function crypt(cipher, data) {
return Buffer.concat([ text, pad ]);
}

function keyToPassword(key) {
if (passwordCache.has(key)) {
return passwordCache.get(key);
}

// Simulate EVP_BytesToKey.
// see https://github.com/nodejs/help/issues/1673#issuecomment-503222925
const bytes = Buffer.alloc(KEY_LEN + IV_SIZE);
let lastHash = null,
nBytes = 0;
while (nBytes < bytes.length) {
const hash = crypto.createHash('md5');
if (lastHash) hash.update(lastHash);
hash.update(key);
lastHash = hash.digest();
lastHash.copy(bytes, nBytes);
nBytes += lastHash.length;
}

// Use these for decryption.
const password = {
key: bytes.slice(0, KEY_LEN),
iv: bytes.slice(KEY_LEN, bytes.length),
};

passwordCache.set(key, password);
return password;
}

module.exports = Keygrip;
13 changes: 13 additions & 0 deletions test/lib/keygrip.test.js
Expand Up @@ -2,6 +2,7 @@

const Keygrip = require('../../lib/keygrip');
const assert = require('assert');
const crypto = require('crypto');

describe('test/lib/keygrip.test.js', () => {
it('should throw without keys', () => {
Expand Down Expand Up @@ -31,6 +32,18 @@ describe('test/lib/keygrip.test.js', () => {
assert(newKeygrip.decrypt(encrypted) === false);
});

it('should decrypt key encrypted by createCipher without error', () => {
const keygrip = new Keygrip([ 'foo' ]);
const encrypted = keygrip.encrypt('hello');

const cipher = crypto.createCipher(keygrip.cipher, 'foo');
const text = cipher.update('hello', 'utf8');
const oldEncrypted = Buffer.concat([ text, cipher.final() ]);

assert(encrypted.toString('hex') === oldEncrypted.toString('hex'));
assert(keygrip.decrypt(oldEncrypted).value.toString('utf-8') === 'hello');
});

it('should signed and verify success', () => {
const keygrip = new Keygrip([ 'foo', 'bar' ]);
const newKeygrip = new Keygrip([ 'another', 'foo' ]);
Expand Down

0 comments on commit 7ed0ded

Please sign in to comment.