From 688871d85734813484814b4376315575652df105 Mon Sep 17 00:00:00 2001 From: Kirill Revenkov Date: Sun, 21 Oct 2018 18:19:53 +0300 Subject: [PATCH 1/4] added converting to utf16 for gosts --- cryptography.js | 26 +++++++++++++++------- utils.js | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 utils.js diff --git a/cryptography.js b/cryptography.js index 08b87d3..59c411d 100644 --- a/cryptography.js +++ b/cryptography.js @@ -45,6 +45,9 @@ function repairKey(key) { class Cryptography { constructor(config){ + this.utils = require('./utils'); + this.coding = new _this.coding(); + this.config = config; let ha,sa; if (config) { //настраиваем хэш @@ -76,7 +79,7 @@ class Cryptography { } else { this.digitalSignature = new _this.DigitalSignature(); } - this.coding = new _this.coding(); + } /** @@ -87,12 +90,10 @@ class Cryptography { data2Buffer(data) { let bData; try{ - //bData = Buffer.from(data); - bData = this.coding.Chars.decode(data); + bData = this.coding.Chars.decode(data, 'utf8'); } catch (e) { - // bData = Buffer.from(JSON.stringify(data)); - bData = this.coding.Chars.decode(JSON.stringify(data)); + bData = this.coding.Chars.decode(JSON.stringify(data), 'utf8'); } return bData; } @@ -105,14 +106,20 @@ class Cryptography { let keyPair; if (this.gostSign) { keyPair = this.gostSign.generateKey(); - //конвертируем в формат - keyPair.public = this.coding.Hex.encode(keyPair.publicKey); + //convert to hex + keyPair.public = this.coding.Hex.encode(keyPair.publicKey).replace('\r\n',''); + //convert to utf-16 gor compression + keyPair.public = this.utils.hexString2Unicode(keyPair.public); keyPair.private = this.coding.Hex.encode(keyPair.privateKey); } else { keyPair = this.digitalSignature.generate(); keyPair.private = repairKey(keyPair.private); keyPair.public = repairKey(keyPair.public); } + if (this.config.signFunction.toUpperCase() === 'NEWRSA'){ + //get old rsa key in PEM format and convert to utf-16 with two steps + + } return {private: keyPair.private, public: keyPair.public}; } @@ -155,6 +162,8 @@ class Cryptography { if (this.gostSign) { let bData, bKey, bSign; bData = this.data2Buffer(data); + //convertion from utf16 to hex before using + key = this.utils.unicode2HexString(key); bKey = this.coding.Hex.decode(key); bSign = this.coding.Hex.decode(sign); result = this.gostSign.verify(bKey, bSign, bData); @@ -184,4 +193,5 @@ class Cryptography { if (this.window === undefined) { module.exports = Cryptography; -} \ No newline at end of file +} + diff --git a/utils.js b/utils.js new file mode 100644 index 0000000..a16b94f --- /dev/null +++ b/utils.js @@ -0,0 +1,59 @@ +/** + iZ³ | Izzzio blockchain - https://izzz.io + @author: Andrey Nedobylsky (admin@twister-vl.ru) + */ + + +const utils = { + /** + * convert hex number string to utf-16 + * @param str + * @return {*} + */ + hexString2Unicode: function (str) { + + if(str.length % 4 !== 0) { + return false; + } + + str = str.toLowerCase(); + let code = ''; + str = str.match(/.{1,4}/g); + for (let s of str) { + if(s.length === 4) { + code += String.fromCharCode(parseInt(s, 16)); + } else { + code += s; + } + } + + return code; + }, + /** + * convert utf-16 string to hex + * @param uniStr + * @return {string} + */ + unicode2HexString: function (uniStr) { + let str = ''; + for (let i = 0; i < uniStr.length; i++) { + let charCode = uniStr.charCodeAt(i); + if(charCode < 0x1000) { + str += '0'; + } + if(charCode < 0x100) { + str += '0'; + } + if(charCode < 0x10) { + str += '0'; + } + str += charCode.toString(16); + } + + return str; + } +}; + +if (this.window === undefined) { + module.exports = utils; +} \ No newline at end of file From 5121fb04b2daf0daed90aa7a34866c8ba450c93c Mon Sep 17 00:00:00 2001 From: Kirill Revenkov Date: Sun, 21 Oct 2018 19:10:51 +0300 Subject: [PATCH 2/4] added conversion and compability for node and browser --- cryptography.js | 71 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 61 insertions(+), 10 deletions(-) diff --git a/cryptography.js b/cryptography.js index 59c411d..687dc02 100644 --- a/cryptography.js +++ b/cryptography.js @@ -21,12 +21,14 @@ if (_this.window === undefined) { _this.GostDigest = require('./GOSTModules/gostDigest'); _this.CryptoJS = require('crypto-js'); _this.GostSign = require('./GOSTModules/gostSign'); + _this.utils = require('./utils'); } else { _this.GostDigest = _this.GostDigest ? _this.GostDigest : gostFunctionForDigest; _this.coding = _this.coding ? _this.coding : gostFunctionForCoding; _this.CryptoJS = _this.CryptoJS ? _this.CryptoJS : CryptoJS; _this.GostSign = _this.GostSign ? _this.GostSign : gostFunctionForSign; _this.DigitalSignature = _this.DigitalSignature ? _this.DigitalSignature : DigitalSignature; + _this.utils = _this.utils ? _this.utils : utils; } const inputOutputFormat = 'hex'; @@ -45,7 +47,7 @@ function repairKey(key) { class Cryptography { constructor(config){ - this.utils = require('./utils'); + this.utils = _this.utils; this.coding = new _this.coding(); this.config = config; let ha,sa; @@ -98,6 +100,56 @@ class Cryptography { return bData; } + /** + * convert key from PEM format to hex string + * @param key PEM key + * @param kind kind of the key: public or private + * @returns {string} base64 encoded key + * @constructor + */ + PEMToUtf16(key, kind = 'PUBLIC') { + let k = this.coding.PEM.decode(key, `rsa ${kind} key`); + let hex = this.coding.Hex.encode(k); + hex = hex.replace(new RegExp(/\r\n/, 'g'),""); + return this.utils.hexString2Unicode(hex); + } + + /** + * convert key from hex string to PEM format + * @param key + * @param kind + * @returns {*|String|string|CryptoOperationData|Uint8Array} + * @constructor + */ + utf16ToPem(key, kind = 'PUBLIC') { + key = this.utils.unicode2HexString(key).replace(new RegExp(/\r\n/, 'g'),""); + let k = this.coding.Hex.decode(key); + let pem = this.coding.PEM.encode(k, `RSA ${kind} KEY`); + return pem; + } + + /** + * convert ArrayBuffer to unicode string + * @param key {ArrayBuffer} + * @returns {*|string} + */ + bufferToUtf16(key){ + let k = this.coding.Hex.encode(key).replace(new RegExp(/\r\n/, 'g'),""); + k = this.utils.hexString2Unicode(k); + return k; + } + + /** + * convert unicode string to ArrayBuffer + * @param key {string} unicode string + * @returns {*|string} + */ + utf16ToBuffer(key){ + let k = this.utils.unicode2HexString(key); + k = this.coding.Hex.decode(k); + return k; + } + /** * generates pair of keys * @returns {{private: *, public: *}} @@ -106,10 +158,7 @@ class Cryptography { let keyPair; if (this.gostSign) { keyPair = this.gostSign.generateKey(); - //convert to hex - keyPair.public = this.coding.Hex.encode(keyPair.publicKey).replace('\r\n',''); - //convert to utf-16 gor compression - keyPair.public = this.utils.hexString2Unicode(keyPair.public); + keyPair.public = this.bufferToUtf16(keyPair.publicKey); keyPair.private = this.coding.Hex.encode(keyPair.privateKey); } else { keyPair = this.digitalSignature.generate(); @@ -117,8 +166,8 @@ class Cryptography { keyPair.public = repairKey(keyPair.public); } if (this.config.signFunction.toUpperCase() === 'NEWRSA'){ - //get old rsa key in PEM format and convert to utf-16 with two steps - + //get old rsa key in PEM format and convert to utf-16 + keyPair.public = this.PEMToUtf16(keyPair.public); } return {private: keyPair.private, public: keyPair.public}; } @@ -162,12 +211,14 @@ class Cryptography { if (this.gostSign) { let bData, bKey, bSign; bData = this.data2Buffer(data); - //convertion from utf16 to hex before using - key = this.utils.unicode2HexString(key); - bKey = this.coding.Hex.decode(key); + bKey = this.utf16ToBuffer(key); bSign = this.coding.Hex.decode(sign); result = this.gostSign.verify(bKey, bSign, bData); } else { + if (this.config.signFunction.toUpperCase() === 'NEWRSA'){ + //get old rsa key in PEM format and convert to utf-16 + key = this.utf16ToPem(key); + } result = this.digitalSignature.verifyData(data, sign, key); } return result; From ac66bf4c38adc8f964fb8367252d97ec20ff9d76 Mon Sep 17 00:00:00 2001 From: Kirill Revenkov Date: Sun, 21 Oct 2018 19:57:22 +0300 Subject: [PATCH 3/4] more key conversation --- cryptography.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/cryptography.js b/cryptography.js index 687dc02..4c22ed8 100644 --- a/cryptography.js +++ b/cryptography.js @@ -46,14 +46,16 @@ function repairKey(key) { } class Cryptography { - constructor(config){ + constructor(config = {}){ this.utils = _this.utils; this.coding = new _this.coding(); this.config = config; + this.config.hashFunction = this.config.hashFunction ? this.config.hashFunction.toUpperCase() : this.config.hashFunction; + this.config.signFunction = this.config.signFunction ? this.config.signFunction.toUpperCase() : this.config.signFunction; let ha,sa; if (config) { //настраиваем хэш - switch (config.hashFunction) { + switch (this.config.hashFunction) { case 'STRIBOG': ha = {length: 256}; break; @@ -62,7 +64,7 @@ class Cryptography { break; } //настраиваем подпись - switch (config.signFunction) { + switch (this.config.signFunction) { case 'GOST': sa = {hash: "GOST R 34.11", length: 256}; break; @@ -165,7 +167,7 @@ class Cryptography { keyPair.private = repairKey(keyPair.private); keyPair.public = repairKey(keyPair.public); } - if (this.config.signFunction.toUpperCase() === 'NEWRSA'){ + if (this.config.signFunction === 'NEWRSA'){ //get old rsa key in PEM format and convert to utf-16 keyPair.public = this.PEMToUtf16(keyPair.public); } @@ -215,11 +217,10 @@ class Cryptography { bSign = this.coding.Hex.decode(sign); result = this.gostSign.verify(bKey, bSign, bData); } else { - if (this.config.signFunction.toUpperCase() === 'NEWRSA'){ - //get old rsa key in PEM format and convert to utf-16 - key = this.utf16ToPem(key); - } - result = this.digitalSignature.verifyData(data, sign, key); + let k = key; + //convert key if it's not in PEM + k = k.indexOf('RSA PUBLIC KEY') < 0 ? this.utf16ToPem(k,'PUBLIC') : k; + result = this.digitalSignature.verifyData(data, sign, k); } return result; } From dc4fec9de5ba5a128a59b6bf761fdb3e5eafa62d Mon Sep 17 00:00:00 2001 From: Kirill Date: Mon, 22 Oct 2018 17:16:24 +0300 Subject: [PATCH 4/4] Update cryptography.js --- cryptography.js | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/cryptography.js b/cryptography.js index 4c22ed8..25497ac 100644 --- a/cryptography.js +++ b/cryptography.js @@ -102,6 +102,34 @@ class Cryptography { return bData; } + /** + * convert key from PEM format to Hex string + * @param key PEM key + * @param kind kind of the key: public or private + * @returns {string} hex encoded key + * @constructor + */ + PEMToHex(key, kind = 'PUBLIC') { + let k = this.coding.PEM.decode(key, `rsa ${kind} key`); + let hex = this.coding.Hex.encode(k); + hex = hex.replace(new RegExp(/\r\n/, 'g'),""); + return hex; + } + + /** + * convert key from Hex string to PEM format + * @param key + * @param kind + * @returns {*|String|string|} PEM key + * @constructor + */ + hexToPem(key, kind = 'PUBLIC') { + key = key.replace(new RegExp(/\r\n/, 'g'),""); + let k = this.coding.Hex.decode(key); + let pem = this.coding.PEM.encode(k, `RSA ${kind} KEY`); + return pem; + } + /** * convert key from PEM format to hex string * @param key PEM key @@ -160,7 +188,7 @@ class Cryptography { let keyPair; if (this.gostSign) { keyPair = this.gostSign.generateKey(); - keyPair.public = this.bufferToUtf16(keyPair.publicKey); + keyPair.public = this.coding.Hex.encode(keyPair.publicKey).replace(new RegExp(/\r\n/, 'g'),""); keyPair.private = this.coding.Hex.encode(keyPair.privateKey); } else { keyPair = this.digitalSignature.generate(); @@ -169,7 +197,7 @@ class Cryptography { } if (this.config.signFunction === 'NEWRSA'){ //get old rsa key in PEM format and convert to utf-16 - keyPair.public = this.PEMToUtf16(keyPair.public); + keyPair.public = this.PEMToHex(keyPair.public); } return {private: keyPair.private, public: keyPair.public}; } @@ -187,7 +215,6 @@ class Cryptography { //prepare data for processing bData = this.data2Buffer(data); bKey = this.coding.Hex.decode(key); - signedData = this.gostSign.sign(bKey, bData); signedData = this.coding.Hex.encode(signedData); } else { @@ -213,13 +240,13 @@ class Cryptography { if (this.gostSign) { let bData, bKey, bSign; bData = this.data2Buffer(data); - bKey = this.utf16ToBuffer(key); + bKey = this.coding.Hex.decode(key); bSign = this.coding.Hex.decode(sign); result = this.gostSign.verify(bKey, bSign, bData); } else { let k = key; //convert key if it's not in PEM - k = k.indexOf('RSA PUBLIC KEY') < 0 ? this.utf16ToPem(k,'PUBLIC') : k; + k = k.indexOf('RSA PUBLIC KEY') < 0 ? this.hexToPem(k,'PUBLIC') : k; result = this.digitalSignature.verifyData(data, sign, k); } return result; @@ -246,4 +273,3 @@ class Cryptography { if (this.window === undefined) { module.exports = Cryptography; } -