From 02dc780c774b7b61a173f3ca9353a4d3e1ea93d3 Mon Sep 17 00:00:00 2001 From: Sun Yimin Date: Sun, 7 Apr 2024 15:11:36 +0800 Subject: [PATCH] refactoring --- src/cryptojs_sm3.js | 7 -- src/cryptojs_sm4.js | 120 -------------------- src/cryptojs_sm4_test.js | 86 --------------- src/jsrsasign_patch.js | 211 ++++++++++++++++++++++++++++++++++++ src/jsrsasign_patch_test.js | 90 +++++++++++++++ src/sm2.js | 80 +------------- 6 files changed, 302 insertions(+), 292 deletions(-) create mode 100644 src/jsrsasign_patch.js create mode 100644 src/jsrsasign_patch_test.js diff --git a/src/cryptojs_sm3.js b/src/cryptojs_sm3.js index 875325d..17be8a1 100644 --- a/src/cryptojs_sm3.js +++ b/src/cryptojs_sm3.js @@ -1,5 +1,4 @@ const rs = require('jsrsasign') -const KJUR = rs.KJUR const C = rs.CryptoJS const CLib = C.lib const WordArray = CLib.WordArray @@ -188,10 +187,4 @@ C.SM3 = Hasher._createHelper(SM3) */ C.HmacSM3 = Hasher._createHmacHelper(SM3) -KJUR.crypto.Util.DEFAULTPROVIDER.sm3 = 'cryptojs' -KJUR.crypto.Util.CRYPTOJSMESSAGEDIGESTNAME.sm3 = SM3 - -rs.asn1.x509.OID.name2oidList.sm3 = '1.2.156.10197.1.401.1' -rs.asn1.x509.OID.name2oidList.hmacWithSM3 = '1.2.156.10197.1.401.2' - module.exports = SM3 diff --git a/src/cryptojs_sm4.js b/src/cryptojs_sm4.js index 7ec8e6d..b221ca0 100644 --- a/src/cryptojs_sm4.js +++ b/src/cryptojs_sm4.js @@ -1,5 +1,4 @@ const rs = require('jsrsasign') -const KJUR = rs.KJUR const C = rs.CryptoJS const CAlgo = C.algo const CLib = C.lib @@ -217,123 +216,4 @@ C.pad.NoPadding = { } } -function aryval (val, keys, def) { - if (typeof val !== 'object') return undefined - const keyArr = String(keys).split('.') - for (let i = 0; i < keyArr.length && val; i++) { - let key = keyArr[i] - if (key.match(/^[0-9]+$/)) key = parseInt(key) - val = val[key] - } - return val || val === false ? val : def -} - -/** - * encrypt raw string by specified key and algorithm
- * @name encrypt - * @memberOf KJUR.crypto.Cipher - * @function - * @param {string} s input string to encrypt - * @param {string} hexadecimal string of symmetric cipher key - * @param {string} algName short/long algorithm name for encryption/decryption (OPTION) - * @param {object} param parameters for synchronous cipher such as initial vector (OPTION) - * @return {string} hexadecimal encrypted string - * @since jsrsasign 6.2.0 crypto 1.1.10 - * - * @description - * This static method encrypts raw string with specified key and algorithm. - *
- * NOTE: From jsrsasign 10.9.0, asymmetric cipher ({des-EDE3,sm4-CBC,aes{128,256}}-CBC) is also supported. - * NOTE2: From jsrsasign 11.0.0, RSA and RSAOAEP encryption/decryption support is removed - * because of Marvin attack vulnerability. - * - * @example - * KJUR.crypto.Cipher.encrypt("12abcd...", "5a7d...", "aes256-CBC", { iv: "1b3c..." }) - * KJUR.crypto.Cipher.encrypt("12abcd...", "5a7d...", any, { encalg: "aes128-CBC", iv: "1b3c..." }) - * KJUR.crypto.Cipher.encrypt("12abcd...", any, any, { encalg: "des-EDE3-CBC", iv: "1b3c...", key: "3d41..." }) - * KJUR.crypto.Cipher.encrypt("12abcd...", "5a7d...", "sm4-CBC", { iv: "1b3c..." }) - * KJUR.crypto.Cipher.encrypt(any, any, any, { encalg: "des-EDE3-CBC", iv: "1b3c...", key: "3d41...", enc: "12abcd..." }) - */ -KJUR.crypto.Cipher.encrypt = function (s, keyObj, algName, param) { - if (aryval(param, 'enclag') !== undefined) algName = param.encalg - - if (typeof algName === 'string' && algName.substr(-4) === '-CBC') { - let hKey = keyObj - const hPlain = s - if (aryval(param, 'key') !== undefined) hKey = param.key - // if (aryval(param, 'enc') !== undefined) hEnc = param.enc - const wKey = C.enc.Hex.parse(hKey) - const wPlain = C.enc.Hex.parse(hPlain) - const wIV = C.enc.Hex.parse(param.iv) - let wEnc - if (algName === 'des-EDE3-CBC') { - wEnc = C.TripleDES.encrypt(wPlain, wKey, { iv: wIV }) - } else if (algName === 'aes128-CBC' || algName === 'aes256-CBC') { - wEnc = C.AES.encrypt(wPlain, wKey, { iv: wIV }) - } else if (algName === 'sm4-CBC') { - wEnc = C.SM4.encrypt(wPlain, wKey, { iv: wIV }) - } else { - throw new Error('unsupported algorithm: ' + algName) - } - return wEnc + '' - } else { - throw new Error('Cipher.encrypt: unsupported key or algorithm') - } -} - -/** - * decrypt encrypted hexadecimal string with specified key and algorithm
- * @name decrypt - * @memberOf KJUR.crypto.Cipher - * @function - * @param {string} hex hexadecimal string of encrypted message - * @param {object} hexadecimal string of symmetric cipher key - * @param {string} algName short/long algorithm name for encryption/decryption (OPTION) - * @param {object} param parameters for synchronous cipher such as initial vector (OPTION) - * @return {string} decrypted raw string - * @since jsrsasign 6.2.0 crypto 1.1.10 - * - * @description - * This static method decrypts encrypted hexadecimal string with specified key and algorithm. - *
- * NOTE: From jsrsasign 10.9.0, asymmetric cipher ({des-EDE3,sm4-CBC,aes{128,256}}-CBC) is also supported. - * NOTE2: From jsrsasign 11.0.0, RSA and RSAOAEP encryption/decryption support is removed - * because of Marvin attack vulnerability. - * - * @example - * KJUR.crypto.Cipher.decrypt("12abcd...", "5a7d...", "aes256-CBC", { iv: "1b3c..." }) - * KJUR.crypto.Cipher.decrypt("12abcd...", "5a7d...", any, { encalg: "aes128-CBC", iv: "1b3c..." }) - * KJUR.crypto.Cipher.decrypt("12abcd...", any, any, { encalg: "des-EDE3-CBC", iv: "1b3c...", key: "3d41..." }) - * KJUR.crypto.Cipher.decrypt("12abcd...", "5a7d...", "sm4-CBC", { iv: "1b3c..." }) - * KJUR.crypto.Cipher.decrypt(any, any, any, { encalg: "des-EDE3-CBC", iv: "1b3c...", key: "3d41...", enc: "12abcd..." }) - */ -KJUR.crypto.Cipher.decrypt = function (hex, keyObj, algName, param) { - if (aryval(param, 'enclag') !== undefined) algName = param.encalg - - if (typeof algName === 'string' && algName.substr(-4) === '-CBC') { - let hKey = keyObj - const hEnc = hex - if (aryval(param, 'key') !== undefined) hKey = param.key - // if (aryval(param, 'enc') !== undefined) hEnc = param.enc - const wKey = C.enc.Hex.parse(hKey) - const wEnc = C.enc.Hex.parse(hEnc) - const wIV = C.enc.Hex.parse(param.iv) - let wDec - if (algName === 'des-EDE3-CBC') { - wDec = C.TripleDES.decrypt({ ciphertext: wEnc }, wKey, { iv: wIV }) - } else if (algName === 'aes128-CBC' || algName === 'aes256-CBC') { - wDec = C.AES.decrypt({ ciphertext: wEnc }, wKey, { iv: wIV }) - } else if (algName === 'sm4-CBC') { - wDec = C.SM4.decrypt({ ciphertext: wEnc }, wKey, { iv: wIV }) - } else { - throw new Error('unsupported algorithm: ' + algName) - } - return C.enc.Hex.stringify(wDec) - } else { - throw new Error('Cipher.decrypt: unsupported key or algorithm') - } -} - -rs.asn1.x509.OID.name2oidList['sm4-CBC'] = '1.2.156.10197.1.104.2' - module.exports = SM4 diff --git a/src/cryptojs_sm4_test.js b/src/cryptojs_sm4_test.js index 7719a8e..b1a7f3c 100644 --- a/src/cryptojs_sm4_test.js +++ b/src/cryptojs_sm4_test.js @@ -1,7 +1,6 @@ require('./cryptojs_sm4') const test = require('tape') const rs = require('jsrsasign') -const KJUR = rs.KJUR const C = rs.CryptoJS test('test sample 1', (t) => { @@ -61,88 +60,3 @@ test('test sm4-cbc', (t) => { } t.end() }) - -test('test sm4-cbc with default mode', (t) => { - const cases = [ - { - key: '30313233343536373839414243444546', - iv: '30313233343536373839414243444546', - plaintext: '48656c6c6f20576f726c64', - ciphertext: '0a67062f0cd2dce26a7b978ebf2134f9' - }, - { - key: '30313233343536373839414243444546', - iv: '30313233343536373839414243444546', - plaintext: - '48656c6c6f20576f726c642048656c6c6f20576f726c642048656c6c6f20576f726c642048656c6c6f20576f726c6464', - ciphertext: - 'd31e3683e4fc9b516a2c0f983676a9eb1fdcc32af38408978157a2065de34c6a068d0fef4e2bfab4bcaba66441fde0fe92c164eca170247572de1202952ec727' - }, - { - key: '0123456789abcdeffedcba9876543210', - iv: '00000000000000000000000000000000', - plaintext: '0123456789abcdeffedcba9876543210', - ciphertext: - '681edf34d206965e86b3e94f536e4246677d307e844d7aa24579d556490dc7aa' - } - ] - for (const c of cases) { - const ciphertext = C.SM4.encrypt( - C.enc.Hex.parse(c.plaintext), - C.enc.Hex.parse(c.key), - { iv: C.enc.Hex.parse(c.iv) } - ).ciphertext.toString() - - t.equal(ciphertext, c.ciphertext) - const plaintext = C.SM4.decrypt( - { ciphertext: C.enc.Hex.parse(c.ciphertext) }, - C.enc.Hex.parse(c.key), - { iv: C.enc.Hex.parse(c.iv) } - ) - t.equal(plaintext.toString(), c.plaintext) - } - t.end() -}) - -test('test sm4-cbc with KJUR.crypto.Cipher', (t) => { - const cases = [ - { - key: '30313233343536373839414243444546', - iv: '30313233343536373839414243444546', - plaintext: '48656c6c6f20576f726c64', - ciphertext: '0a67062f0cd2dce26a7b978ebf2134f9' - }, - { - key: '30313233343536373839414243444546', - iv: '30313233343536373839414243444546', - plaintext: - '48656c6c6f20576f726c642048656c6c6f20576f726c642048656c6c6f20576f726c642048656c6c6f20576f726c6464', - ciphertext: - 'd31e3683e4fc9b516a2c0f983676a9eb1fdcc32af38408978157a2065de34c6a068d0fef4e2bfab4bcaba66441fde0fe92c164eca170247572de1202952ec727' - }, - { - key: '0123456789abcdeffedcba9876543210', - iv: '00000000000000000000000000000000', - plaintext: '0123456789abcdeffedcba9876543210', - ciphertext: - '681edf34d206965e86b3e94f536e4246677d307e844d7aa24579d556490dc7aa' - } - ] - for (const c of cases) { - const ciphertext = KJUR.crypto.Cipher.encrypt( - c.plaintext, - c.key, - 'sm4-CBC', - { iv: c.iv } - ) - t.equal(ciphertext, c.ciphertext) - const plaintext = KJUR.crypto.Cipher.decrypt( - c.ciphertext, - c.key, - 'sm4-CBC', - { iv: c.iv } - ) - t.equal(plaintext, c.plaintext) - } - t.end() -}) diff --git a/src/jsrsasign_patch.js b/src/jsrsasign_patch.js new file mode 100644 index 0000000..6c81a25 --- /dev/null +++ b/src/jsrsasign_patch.js @@ -0,0 +1,211 @@ +const rs = require('jsrsasign') +const util = require('./util') +const KJUR = rs.KJUR +const C = rs.CryptoJS + +function parsePBES2 (hP8Prv) { + const pASN = rs.ASN1HEX.parse(hP8Prv) + if (util.aryval(pASN, 'seq.0.seq.0.oid') !== 'pkcs5PBES2' || + util.aryval(pASN, 'seq.0.seq.1.seq.0.seq.0.oid') !== 'pkcs5PBKDF2') { + throw new Error('not pkcs5PBES2 and pkcs5PBKDF2 used') + } + const pASNKDF = util.aryval(pASN, 'seq.0.seq.1.seq.0.seq.1.seq') + if (pASNKDF === undefined) { + throw new Error('PBKDF2 parameter not found') + } + const salt = util.aryval(pASNKDF, '0.octstr.hex') + const hIter = util.aryval(pASNKDF, '1.int.hex') + const prf = util.aryval(pASNKDF, `${pASNKDF.length - 1}.seq.0.oid`, 'hmacWithSHA1') + let iter = -1 + try { + iter = parseInt(hIter, 16) + } catch (ex) { + throw new Error('iter not proper value') + } + + const encalg = util.aryval(pASN, 'seq.0.seq.1.seq.1.seq.0.oid') + const enciv = util.aryval(pASN, 'seq.0.seq.1.seq.1.seq.1.octstr.hex') + const enc = util.aryval(pASN, 'seq.1.octstr.hex') + if (encalg === undefined || enciv === undefined || enc === undefined) { + throw new Error('encalg, enciv or enc is undefined') + } + + return { + salt, + iter, + prf, + encalg, + enciv, + enc + } +} + +function getDKFromPBES2Param (pPBES2, passcode) { + const pHasher = { + hmacWithSHA1: C.algo.SHA1, + hmacWithSHA224: C.algo.SHA224, + hmacWithSHA256: C.algo.SHA256, + hmacWithSHA384: C.algo.SHA384, + hmacWithSHA512: C.algo.SHA512, + hmacWithSM3: C.algo.SM3 + } + const pKeySize = { + 'des-EDE3-CBC': 192 / 32, + 'aes128-CBC': 128 / 32, + 'aes256-CBC': 256 / 32, + 'sm4-CBC': 128 / 32 + } + + const hasher = pHasher[pPBES2.prf] + if (hasher === undefined) { throw new Error('unsupported prf') } + + const keysize = pKeySize[pPBES2.encalg] + if (keysize === undefined) { throw new Error('unsupported encalg') } + + const wSalt = C.enc.Hex.parse(pPBES2.salt) + const iter = pPBES2.iter + try { + const wKey = C.PBKDF2(passcode, + wSalt, + { + keySize: keysize, + iterations: iter, + hasher + }) + const keyHex = C.enc.Hex.stringify(wKey) + return keyHex + } catch (ex) { + throw new Error('PBKDF2 error: ' + ex + ' ' + JSON.stringify(pPBES2) + ' ' + passcode) + } +} + +function patchSM3 () { + KJUR.crypto.Util.DEFAULTPROVIDER.sm3 = 'cryptojs' + KJUR.crypto.Util.CRYPTOJSMESSAGEDIGESTNAME.sm3 = C.algo.SM3 + + rs.asn1.x509.OID.name2oidList.sm3 = '1.2.156.10197.1.401.1' + rs.asn1.x509.OID.name2oidList.hmacWithSM3 = '1.2.156.10197.1.401.2' +} + +function patchSM4 () { +/** + * encrypt raw string by specified key and algorithm
+ * @name encrypt + * @memberOf KJUR.crypto.Cipher + * @function + * @param {string} s input string to encrypt + * @param {string} hexadecimal string of symmetric cipher key + * @param {string} algName short/long algorithm name for encryption/decryption (OPTION) + * @param {object} param parameters for synchronous cipher such as initial vector (OPTION) + * @return {string} hexadecimal encrypted string + * @since jsrsasign 6.2.0 crypto 1.1.10 + * + * @description + * This static method encrypts raw string with specified key and algorithm. + *
+ * NOTE: From jsrsasign 10.9.0, asymmetric cipher ({des-EDE3,sm4-CBC,aes{128,256}}-CBC) is also supported. + * NOTE2: From jsrsasign 11.0.0, RSA and RSAOAEP encryption/decryption support is removed + * because of Marvin attack vulnerability. + * + * @example + * KJUR.crypto.Cipher.encrypt("12abcd...", "5a7d...", "aes256-CBC", { iv: "1b3c..." }) + * KJUR.crypto.Cipher.encrypt("12abcd...", "5a7d...", any, { encalg: "aes128-CBC", iv: "1b3c..." }) + * KJUR.crypto.Cipher.encrypt("12abcd...", any, any, { encalg: "des-EDE3-CBC", iv: "1b3c...", key: "3d41..." }) + * KJUR.crypto.Cipher.encrypt("12abcd...", "5a7d...", "sm4-CBC", { iv: "1b3c..." }) + * KJUR.crypto.Cipher.encrypt(any, any, any, { encalg: "des-EDE3-CBC", iv: "1b3c...", key: "3d41...", enc: "12abcd..." }) + */ + KJUR.crypto.Cipher.encrypt = function (s, keyObj, algName, param) { + if (util.CryptoJSaryval(param, 'enclag') !== undefined) algName = param.encalg + + if (typeof algName === 'string' && algName.substr(-4) === '-CBC') { + let hKey = keyObj + const hPlain = s + if (util.aryval(param, 'key') !== undefined) hKey = param.key + // if (aryval(param, 'enc') !== undefined) hEnc = param.enc + const wKey = C.enc.Hex.parse(hKey) + const wPlain = C.enc.Hex.parse(hPlain) + const wIV = C.enc.Hex.parse(param.iv) + let wEnc + if (algName === 'des-EDE3-CBC') { + wEnc = C.TripleDES.encrypt(wPlain, wKey, { iv: wIV }) + } else if (algName === 'aes128-CBC' || algName === 'aes256-CBC') { + wEnc = C.AES.encrypt(wPlain, wKey, { iv: wIV }) + } else if (algName === 'sm4-CBC') { + wEnc = C.SM4.encrypt(wPlain, wKey, { iv: wIV }) + } else { + throw new Error('unsupported algorithm: ' + algName) + } + return wEnc + '' + } else { + throw new Error('Cipher.encrypt: unsupported key or algorithm') + } + } + + /** + * decrypt encrypted hexadecimal string with specified key and algorithm
+ * @name decrypt + * @memberOf KJUR.crypto.Cipher + * @function + * @param {string} hex hexadecimal string of encrypted message + * @param {object} hexadecimal string of symmetric cipher key + * @param {string} algName short/long algorithm name for encryption/decryption (OPTION) + * @param {object} param parameters for synchronous cipher such as initial vector (OPTION) + * @return {string} decrypted raw string + * @since jsrsasign 6.2.0 crypto 1.1.10 + * + * @description + * This static method decrypts encrypted hexadecimal string with specified key and algorithm. + *
+ * NOTE: From jsrsasign 10.9.0, asymmetric cipher ({des-EDE3,sm4-CBC,aes{128,256}}-CBC) is also supported. + * NOTE2: From jsrsasign 11.0.0, RSA and RSAOAEP encryption/decryption support is removed + * because of Marvin attack vulnerability. + * + * @example + * KJUR.crypto.Cipher.decrypt("12abcd...", "5a7d...", "aes256-CBC", { iv: "1b3c..." }) + * KJUR.crypto.Cipher.decrypt("12abcd...", "5a7d...", any, { encalg: "aes128-CBC", iv: "1b3c..." }) + * KJUR.crypto.Cipher.decrypt("12abcd...", any, any, { encalg: "des-EDE3-CBC", iv: "1b3c...", key: "3d41..." }) + * KJUR.crypto.Cipher.decrypt("12abcd...", "5a7d...", "sm4-CBC", { iv: "1b3c..." }) + * KJUR.crypto.Cipher.decrypt(any, any, any, { encalg: "des-EDE3-CBC", iv: "1b3c...", key: "3d41...", enc: "12abcd..." }) + */ + KJUR.crypto.Cipher.decrypt = function (hex, keyObj, algName, param) { + if (util.aryval(param, 'enclag') !== undefined) algName = param.encalg + + if (typeof algName === 'string' && algName.substr(-4) === '-CBC') { + let hKey = keyObj + const hEnc = hex + if (util.aryval(param, 'key') !== undefined) hKey = param.key + // if (aryval(param, 'enc') !== undefined) hEnc = param.enc + const wKey = C.enc.Hex.parse(hKey) + const wEnc = C.enc.Hex.parse(hEnc) + const wIV = C.enc.Hex.parse(param.iv) + let wDec + if (algName === 'des-EDE3-CBC') { + wDec = C.TripleDES.decrypt({ ciphertext: wEnc }, wKey, { iv: wIV }) + } else if (algName === 'aes128-CBC' || algName === 'aes256-CBC') { + wDec = C.AES.decrypt({ ciphertext: wEnc }, wKey, { iv: wIV }) + } else if (algName === 'sm4-CBC') { + wDec = C.SM4.decrypt({ ciphertext: wEnc }, wKey, { iv: wIV }) + } else { + throw new Error('unsupported algorithm: ' + algName) + } + return C.enc.Hex.stringify(wDec) + } else { + throw new Error('Cipher.decrypt: unsupported key or algorithm') + } + } + + rs.asn1.x509.OID.name2oidList['sm4-CBC'] = '1.2.156.10197.1.104.2' +} + +function patch () { + require('./cryptojs_sm3') + require('./cryptojs_sm4') + patchSM3() + patchSM4() + rs.KEYUTIL.parsePBES2 = parsePBES2 + rs.KEYUTIL.getDKFromPBES2Param = getDKFromPBES2Param +} + +module.exports = { + patch +} diff --git a/src/jsrsasign_patch_test.js b/src/jsrsasign_patch_test.js new file mode 100644 index 0000000..d2c64c7 --- /dev/null +++ b/src/jsrsasign_patch_test.js @@ -0,0 +1,90 @@ +const test = require('tape') +const rs = require('jsrsasign') +const KJUR = rs.KJUR +const C = rs.CryptoJS +require('./jsrsasign_patch').patch() + +test('test sm4-cbc with default mode', (t) => { + const cases = [ + { + key: '30313233343536373839414243444546', + iv: '30313233343536373839414243444546', + plaintext: '48656c6c6f20576f726c64', + ciphertext: '0a67062f0cd2dce26a7b978ebf2134f9' + }, + { + key: '30313233343536373839414243444546', + iv: '30313233343536373839414243444546', + plaintext: + '48656c6c6f20576f726c642048656c6c6f20576f726c642048656c6c6f20576f726c642048656c6c6f20576f726c6464', + ciphertext: + 'd31e3683e4fc9b516a2c0f983676a9eb1fdcc32af38408978157a2065de34c6a068d0fef4e2bfab4bcaba66441fde0fe92c164eca170247572de1202952ec727' + }, + { + key: '0123456789abcdeffedcba9876543210', + iv: '00000000000000000000000000000000', + plaintext: '0123456789abcdeffedcba9876543210', + ciphertext: + '681edf34d206965e86b3e94f536e4246677d307e844d7aa24579d556490dc7aa' + } + ] + for (const c of cases) { + const ciphertext = C.SM4.encrypt( + C.enc.Hex.parse(c.plaintext), + C.enc.Hex.parse(c.key), + { iv: C.enc.Hex.parse(c.iv) } + ).ciphertext.toString() + + t.equal(ciphertext, c.ciphertext) + const plaintext = C.SM4.decrypt( + { ciphertext: C.enc.Hex.parse(c.ciphertext) }, + C.enc.Hex.parse(c.key), + { iv: C.enc.Hex.parse(c.iv) } + ) + t.equal(plaintext.toString(), c.plaintext) + } + t.end() +}) + +test('test sm4-cbc with KJUR.crypto.Cipher', (t) => { + const cases = [ + { + key: '30313233343536373839414243444546', + iv: '30313233343536373839414243444546', + plaintext: '48656c6c6f20576f726c64', + ciphertext: '0a67062f0cd2dce26a7b978ebf2134f9' + }, + { + key: '30313233343536373839414243444546', + iv: '30313233343536373839414243444546', + plaintext: + '48656c6c6f20576f726c642048656c6c6f20576f726c642048656c6c6f20576f726c642048656c6c6f20576f726c6464', + ciphertext: + 'd31e3683e4fc9b516a2c0f983676a9eb1fdcc32af38408978157a2065de34c6a068d0fef4e2bfab4bcaba66441fde0fe92c164eca170247572de1202952ec727' + }, + { + key: '0123456789abcdeffedcba9876543210', + iv: '00000000000000000000000000000000', + plaintext: '0123456789abcdeffedcba9876543210', + ciphertext: + '681edf34d206965e86b3e94f536e4246677d307e844d7aa24579d556490dc7aa' + } + ] + for (const c of cases) { + const ciphertext = KJUR.crypto.Cipher.encrypt( + c.plaintext, + c.key, + 'sm4-CBC', + { iv: c.iv } + ) + t.equal(ciphertext, c.ciphertext) + const plaintext = KJUR.crypto.Cipher.decrypt( + c.ciphertext, + c.key, + 'sm4-CBC', + { iv: c.iv } + ) + t.equal(plaintext, c.plaintext) + } + t.end() +}) diff --git a/src/sm2.js b/src/sm2.js index 57f70fe..5843ff6 100644 --- a/src/sm2.js +++ b/src/sm2.js @@ -1,6 +1,5 @@ -require('./cryptojs_sm3') -require('./cryptojs_sm4') const rs = require('jsrsasign') +require('./jsrsasign_patch').patch() const sm3 = require('gmsm-sm3js') const util = require('./util') @@ -706,83 +705,6 @@ function plainEncrypterOptions () { return new EncrypterOptions(CIPHERTEXT_ENCODING_PLAIN) } -const C = rs.CryptoJS -rs.KEYUTIL.parsePBES2 = function (hP8Prv) { - const pASN = rs.ASN1HEX.parse(hP8Prv) - if (util.aryval(pASN, 'seq.0.seq.0.oid') !== 'pkcs5PBES2' || - util.aryval(pASN, 'seq.0.seq.1.seq.0.seq.0.oid') !== 'pkcs5PBKDF2') { - throw new Error('not pkcs5PBES2 and pkcs5PBKDF2 used') - } - const pASNKDF = util.aryval(pASN, 'seq.0.seq.1.seq.0.seq.1.seq') - if (pASNKDF === undefined) { - throw new Error('PBKDF2 parameter not found') - } - const salt = util.aryval(pASNKDF, '0.octstr.hex') - const hIter = util.aryval(pASNKDF, '1.int.hex') - const prf = util.aryval(pASNKDF, `${pASNKDF.length - 1}.seq.0.oid`, 'hmacWithSHA1') - let iter = -1 - try { - iter = parseInt(hIter, 16) - } catch (ex) { - throw new Error('iter not proper value') - } - - const encalg = util.aryval(pASN, 'seq.0.seq.1.seq.1.seq.0.oid') - const enciv = util.aryval(pASN, 'seq.0.seq.1.seq.1.seq.1.octstr.hex') - const enc = util.aryval(pASN, 'seq.1.octstr.hex') - if (encalg === undefined || enciv === undefined || enc === undefined) { - throw new Error('encalg, enciv or enc is undefined') - } - - return { - salt, - iter, - prf, - encalg, - enciv, - enc - } -} - -rs.KEYUTIL.getDKFromPBES2Param = function (pPBES2, passcode) { - const pHasher = { - hmacWithSHA1: C.algo.SHA1, - hmacWithSHA224: C.algo.SHA224, - hmacWithSHA256: C.algo.SHA256, - hmacWithSHA384: C.algo.SHA384, - hmacWithSHA512: C.algo.SHA512, - hmacWithSM3: C.algo.SM3 - } - const pKeySize = { - 'des-EDE3-CBC': 192 / 32, - 'aes128-CBC': 128 / 32, - 'aes256-CBC': 256 / 32, - 'sm4-CBC': 128 / 32 - } - - const hasher = pHasher[pPBES2.prf] - if (hasher === undefined) { throw new Error('unsupported prf') } - - const keysize = pKeySize[pPBES2.encalg] - if (keysize === undefined) { throw new Error('unsupported encalg') } - - const wSalt = C.enc.Hex.parse(pPBES2.salt) - const iter = pPBES2.iter - try { - const wKey = C.PBKDF2(passcode, - wSalt, - { - keySize: keysize, - iterations: iter, - hasher - }) - const keyHex = C.enc.Hex.stringify(wKey) - return keyHex - } catch (ex) { - throw new Error('PBKDF2 error: ' + ex + ' ' + JSON.stringify(pPBES2) + ' ' + passcode) - } -} - module.exports = { Signature, createSM2Signature,