From 4766470b0aab33f47ed26ed1f78a9f81fcfc4c8b Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Thu, 19 Apr 2018 15:02:44 +0200 Subject: [PATCH 1/3] crypto: add createCipher/WithIV functions This commit extracts the common code from the Cipher/Cipheriv and Decipher/Decipheriv constructors into a separate function to avoid code duplication. --- lib/internal/crypto/cipher.js | 129 ++++++++++++---------------------- 1 file changed, 46 insertions(+), 83 deletions(-) diff --git a/lib/internal/crypto/cipher.js b/lib/internal/crypto/cipher.js index 118fc1da5b7c2c..0970d27c7662e0 100644 --- a/lib/internal/crypto/cipher.js +++ b/lib/internal/crypto/cipher.js @@ -73,10 +73,21 @@ function getUIntOption(options, key) { return -1; } -function Cipher(cipher, password, options) { - if (!(this instanceof Cipher)) - return new Cipher(cipher, password, options); +function createCipherBase(cipher, credential, options, decipher, iv) { + const authTagLength = getUIntOption(options, 'authTagLength'); + + this._handle = new CipherBase(decipher); + if (iv === undefined) { + this._handle.init(cipher, credential, authTagLength); + } else { + this._handle.initiv(cipher, credential, iv, authTagLength); + } + this._decoder = null; + LazyTransform.call(this, options); +} + +function createCipher(cipher, password, options, decipher) { if (typeof cipher !== 'string') throw new ERR_INVALID_ARG_TYPE('cipher', 'string', cipher); @@ -89,14 +100,38 @@ function Cipher(cipher, password, options) { ); } - const authTagLength = getUIntOption(options, 'authTagLength'); + createCipherBase.call(this, cipher, password, options, decipher); +} - this._handle = new CipherBase(true); +function createCipherWithIV(cipher, key, options, decipher, iv) { + if (typeof cipher !== 'string') + throw new ERR_INVALID_ARG_TYPE('cipher', 'string', cipher); - this._handle.init(cipher, password, authTagLength); - this._decoder = null; + key = toBuf(key); + if (!isArrayBufferView(key)) { + throw new ERR_INVALID_ARG_TYPE( + 'key', + ['string', 'Buffer', 'TypedArray', 'DataView'], + key + ); + } - LazyTransform.call(this, options); + iv = toBuf(iv); + if (iv !== null && !isArrayBufferView(iv)) { + throw new ERR_INVALID_ARG_TYPE( + 'iv', + ['string', 'Buffer', 'TypedArray', 'DataView'], + iv + ); + } + createCipherBase.call(this, cipher, key, options, decipher, iv); +} + +function Cipher(cipher, password, options) { + if (!(this instanceof Cipher)) + return new Cipher(cipher, password, options); + + createCipher.call(this, cipher, password, options, true); } inherits(Cipher, LazyTransform); @@ -198,34 +233,7 @@ function Cipheriv(cipher, key, iv, options) { if (!(this instanceof Cipheriv)) return new Cipheriv(cipher, key, iv, options); - if (typeof cipher !== 'string') - throw new ERR_INVALID_ARG_TYPE('cipher', 'string', cipher); - - key = toBuf(key); - if (!isArrayBufferView(key)) { - throw new ERR_INVALID_ARG_TYPE( - 'key', - ['string', 'Buffer', 'TypedArray', 'DataView'], - key - ); - } - - iv = toBuf(iv); - if (iv !== null && !isArrayBufferView(iv)) { - throw new ERR_INVALID_ARG_TYPE( - 'iv', - ['string', 'Buffer', 'TypedArray', 'DataView'], - iv - ); - } - - const authTagLength = getUIntOption(options, 'authTagLength'); - - this._handle = new CipherBase(true); - this._handle.initiv(cipher, key, iv, authTagLength); - this._decoder = null; - - LazyTransform.call(this, options); + createCipherWithIV.call(this, cipher, key, options, true, iv); } inherits(Cipheriv, LazyTransform); @@ -244,25 +252,7 @@ function Decipher(cipher, password, options) { if (!(this instanceof Decipher)) return new Decipher(cipher, password, options); - if (typeof cipher !== 'string') - throw new ERR_INVALID_ARG_TYPE('cipher', 'string', cipher); - - password = toBuf(password); - if (!isArrayBufferView(password)) { - throw new ERR_INVALID_ARG_TYPE( - 'password', - ['string', 'Buffer', 'TypedArray', 'DataView'], - password - ); - } - - const authTagLength = getUIntOption(options, 'authTagLength'); - - this._handle = new CipherBase(false); - this._handle.init(cipher, password, authTagLength); - this._decoder = null; - - LazyTransform.call(this, options); + createCipher.call(this, cipher, password, options, false); } inherits(Decipher, LazyTransform); @@ -281,34 +271,7 @@ function Decipheriv(cipher, key, iv, options) { if (!(this instanceof Decipheriv)) return new Decipheriv(cipher, key, iv, options); - if (typeof cipher !== 'string') - throw new ERR_INVALID_ARG_TYPE('cipher', 'string', cipher); - - key = toBuf(key); - if (!isArrayBufferView(key)) { - throw new ERR_INVALID_ARG_TYPE( - 'key', - ['string', 'Buffer', 'TypedArray', 'DataView'], - key - ); - } - - iv = toBuf(iv); - if (iv !== null && !isArrayBufferView(iv)) { - throw new ERR_INVALID_ARG_TYPE( - 'iv', - ['string', 'Buffer', 'TypedArray', 'DataView'], - iv - ); - } - - const authTagLength = getUIntOption(options, 'authTagLength'); - - this._handle = new CipherBase(false); - this._handle.initiv(cipher, key, iv, authTagLength); - this._decoder = null; - - LazyTransform.call(this, options); + createCipherWithIV.call(this, cipher, key, options, false, iv); } inherits(Decipheriv, LazyTransform); From a28723f4ddf39332c616574d5166833456199392 Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Fri, 20 Apr 2018 08:03:02 +0200 Subject: [PATCH 2/3] crypto: add addCipherPrototypeFunctions function This commit adds a function named addCipherPrototypeFunctions to avoid code duplication. --- lib/internal/crypto/cipher.js | 43 ++++++++++++----------------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/lib/internal/crypto/cipher.js b/lib/internal/crypto/cipher.js index 0970d27c7662e0..75d4af717f27dd 100644 --- a/lib/internal/crypto/cipher.js +++ b/lib/internal/crypto/cipher.js @@ -236,17 +236,19 @@ function Cipheriv(cipher, key, iv, options) { createCipherWithIV.call(this, cipher, key, options, true, iv); } -inherits(Cipheriv, LazyTransform); - -Cipheriv.prototype._transform = Cipher.prototype._transform; -Cipheriv.prototype._flush = Cipher.prototype._flush; -Cipheriv.prototype.update = Cipher.prototype.update; -Cipheriv.prototype.final = Cipher.prototype.final; -Cipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding; -Cipheriv.prototype.getAuthTag = Cipher.prototype.getAuthTag; -Cipheriv.prototype.setAuthTag = Cipher.prototype.setAuthTag; -Cipheriv.prototype.setAAD = Cipher.prototype.setAAD; +function addCipherPrototypeFunctions(constructor) { + constructor.prototype._transform = Cipher.prototype._transform; + constructor.prototype._flush = Cipher.prototype._flush; + constructor.prototype.update = Cipher.prototype.update; + constructor.prototype.final = Cipher.prototype.final; + constructor.prototype.setAutoPadding = Cipher.prototype.setAutoPadding; + constructor.prototype.getAuthTag = Cipher.prototype.getAuthTag; + constructor.prototype.setAuthTag = Cipher.prototype.setAuthTag; + constructor.prototype.setAAD = Cipher.prototype.setAAD; +} +inherits(Cipheriv, LazyTransform); +addCipherPrototypeFunctions(Cipheriv); function Decipher(cipher, password, options) { if (!(this instanceof Decipher)) @@ -256,15 +258,7 @@ function Decipher(cipher, password, options) { } inherits(Decipher, LazyTransform); - -Decipher.prototype._transform = Cipher.prototype._transform; -Decipher.prototype._flush = Cipher.prototype._flush; -Decipher.prototype.update = Cipher.prototype.update; -Decipher.prototype.final = Cipher.prototype.final; -Decipher.prototype.setAutoPadding = Cipher.prototype.setAutoPadding; -Decipher.prototype.getAuthTag = Cipher.prototype.getAuthTag; -Decipher.prototype.setAuthTag = Cipher.prototype.setAuthTag; -Decipher.prototype.setAAD = Cipher.prototype.setAAD; +addCipherPrototypeFunctions(Decipher); function Decipheriv(cipher, key, iv, options) { @@ -275,16 +269,7 @@ function Decipheriv(cipher, key, iv, options) { } inherits(Decipheriv, LazyTransform); - -Decipheriv.prototype._transform = Cipher.prototype._transform; -Decipheriv.prototype._flush = Cipher.prototype._flush; -Decipheriv.prototype.update = Cipher.prototype.update; -Decipheriv.prototype.final = Cipher.prototype.final; -Decipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding; -Decipheriv.prototype.getAuthTag = Cipher.prototype.getAuthTag; -Decipheriv.prototype.setAuthTag = Cipher.prototype.setAuthTag; -Decipheriv.prototype.setAAD = Cipher.prototype.setAAD; - +addCipherPrototypeFunctions(Decipheriv); module.exports = { Cipher, From 05cd46c1a0e6a7a63c531a96723fc470ee9a4c67 Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Fri, 20 Apr 2018 08:14:23 +0200 Subject: [PATCH 3/3] crypto: remove rsaPrivate and rename rsaPublic This commit renames rsaPublic and removes the rsaPrivate function as the code in these two functions are identical. --- lib/internal/crypto/cipher.js | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/lib/internal/crypto/cipher.js b/lib/internal/crypto/cipher.js index 75d4af717f27dd..d1c45bfdce0e0d 100644 --- a/lib/internal/crypto/cipher.js +++ b/lib/internal/crypto/cipher.js @@ -33,7 +33,7 @@ const { StringDecoder } = require('string_decoder'); const { inherits } = require('util'); const { normalizeEncoding } = require('internal/util'); -function rsaPublic(method, defaultPadding) { +function rsaFunctionFor(method, defaultPadding) { return function(options, buffer) { const key = options.key || options; const padding = options.padding || defaultPadding; @@ -42,19 +42,10 @@ function rsaPublic(method, defaultPadding) { }; } -function rsaPrivate(method, defaultPadding) { - return function(options, buffer) { - const key = options.key || options; - const passphrase = options.passphrase || null; - const padding = options.padding || defaultPadding; - return method(toBuf(key), buffer, padding, passphrase); - }; -} - -const publicEncrypt = rsaPublic(_publicEncrypt, RSA_PKCS1_OAEP_PADDING); -const publicDecrypt = rsaPublic(_publicDecrypt, RSA_PKCS1_PADDING); -const privateEncrypt = rsaPrivate(_privateEncrypt, RSA_PKCS1_PADDING); -const privateDecrypt = rsaPrivate(_privateDecrypt, RSA_PKCS1_OAEP_PADDING); +const publicEncrypt = rsaFunctionFor(_publicEncrypt, RSA_PKCS1_OAEP_PADDING); +const publicDecrypt = rsaFunctionFor(_publicDecrypt, RSA_PKCS1_PADDING); +const privateEncrypt = rsaFunctionFor(_privateEncrypt, RSA_PKCS1_PADDING); +const privateDecrypt = rsaFunctionFor(_privateDecrypt, RSA_PKCS1_OAEP_PADDING); function getDecoder(decoder, encoding) { encoding = normalizeEncoding(encoding);