UNPKG

cyberchef

Version:

The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.

452 lines (433 loc) 20.7 kB
/** * @file GOST 34.10-2012 signature function with 1024/512 bits digest * @version 1.76 * @copyright 2014-2016, Rudolf Nickolaev. All rights reserved. */ /* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ import GostRandom from './gostRandom.mjs'; import GostCipher from './gostCipher.mjs'; import GostDigest from './gostDigest.mjs'; import GostSign from './gostSign.mjs'; /* * Engine definition base on normalized algorithm identifier * */ // <editor-fold defaultstate="collapsed"> var root = {}; // Define engine function defineEngine(method, algorithm) { if (!algorithm) throw new (root.SyntaxError || Error)('Algorithm not defined'); if (!algorithm.name) throw new (root.SyntaxError || Error)('Algorithm name not defined'); var name = algorithm.name, mode = algorithm.mode; if ((name === 'GOST 28147' || name === 'GOST R 34.12' || name === 'RC2') && (method === 'generateKey' || (mode === 'MAC' && (method === 'sign' || method === 'verify')) || ((mode === 'KW' || mode === 'MASK') && (method === 'wrapKey' || method === 'unwrapKey')) || ((!mode || mode === 'ES') && (method === 'encrypt' || method === 'decrypt')))) { return 'GostCipher'; } else if ((name === 'GOST R 34.11' || name === 'SHA') && (method === 'digest' || (mode === 'HMAC' && (method === 'sign' || method === 'verify' || method === 'generateKey')) || ((mode === 'KDF' || mode === 'PBKDF2' || mode === 'PFXKDF' || mode === 'CPKDF') && (method === 'deriveKey' || method === 'deriveBits' || method === 'generateKey')))) { return 'GostDigest'; } else if (name === 'GOST R 34.10' && (method === 'generateKey' || ((!mode || mode === 'SIGN') && (method === 'sign' || method === 'verify')) || (mode === 'MASK' && (method === 'wrapKey' || method === 'unwrapKey')) || (mode === 'DH' && (method === 'deriveKey' || method === 'deriveBits')))) { return 'GostSign'; } else throw new (root.NotSupportedError || Error)('Algorithm ' + name + '-' + mode + ' is not valid for ' + method); } // </editor-fold> /** * Object implements dedicated Web Workers and provide a simple way to create * and run GOST cryptographic algorithms in background thread. * * Object provide interface to GOST low-level cryptogric classes: * <ul> * <li>GostCipher - implementation of GOST 28147, GOST R 34.12, GOST R 34.13 Encryption algorithms. Reference {@link http://tools.ietf.org/html/rfc5830}</li> * <li>GostDigest - implementation of GOST R 34.11 Hash Function algorithms. References {@link http://tools.ietf.org/html/rfc5831} and {@link http://tools.ietf.org/html/rfc6986}</li> * <li>GostSign - implementation of GOST R 34.10 Digital Signature algorithms. References {@link http://tools.ietf.org/html/rfc5832} and {@link http://tools.ietf.org/html/rfc7091}</li> * </ul> * @namespace gostEngine */ var gostEngine = { /** * gostEngine.execute(algorithm, method, args) Entry point to execution * all low-level GOST cryptographic methods * * <ul> * <li>Determine the appropriate engine for a given execution method</li> * <li>Create cipher object for determineted engine</li> * <li>Execute method of cipher with given args</li> * </ul> * * @memberOf gostEngine * @param {AlgorithmIndentifier} algorithm Algorithm identifier * @param {string} method Crypto method for execution * @param {Array} args Method arguments (keys, data, additional parameters) * @returns {(CryptoOperationData|Key|KeyPair|boolean)} Result of method execution */ execute: function (algorithm, method, args) // <editor-fold defaultstate="collapsed"> { // Define engine for GOST algorithms var engine = defineEngine(method, algorithm); // Create cipher var cipher = this['get' + engine](algorithm); // Execute method return cipher[method].apply(cipher, args); }, // </editor-fold> /** * gostEngine.getGostCipher(algorithm) returns GOST 28147 / GOST R 34.12 cipher instance<br><br> * * GOST 28147-89 / GOST R 34.12-15 Encryption Algorithm<br><br> * When keys and initialization vectors are converted to/from byte arrays, * little-endian byte order is assumed.<br><br> * * Normalized algorithm identifier common parameters: * * <ul> * <li><b>name</b> Algorithm name 'GOST 28147' or 'GOST R 34.12'</li> * <li><b>version</b> Algorithm version, number * <ul> * <li><b>1989</b> Current version of standard</li> * <li><b>2015</b> New draft version of standard</li> * </ul> * </li> * <li><b>length</b> Block length * <ul> * <li><b>64</b> 64 bits length (default)</li> * <li><b>128</b> 128 bits length (only for version 2015)</li> * </ul> * </li> * <li><b>mode</b> Algorithm mode, string * <ul> * <li><b>ES</b> Encryption mode (default)</li> * <li><b>MAC</b> "imitovstavka" (MAC) mode</li> * <li><b>KW</b> Key wrapping mode</li> * <li><b>MASK</b> Key mask mode</li> * </ul> * </li> * <li><b>sBox</b> Paramset sBox for GOST 28147-89, string. Used only if version = 1989</li> * </ul> * * Supported algorithms, modes and parameters: * * <ul> * <li>Encript/Decrypt mode (ES) * <ul> * <li><b>block</b> Block mode, string. Default ECB</li> * <li><b>keyMeshing</b> Key meshing mode, string. Default NO</li> * <li><b>padding</b> Padding mode, string. Default NO for CFB and CTR modes, or ZERO for others</li> * <li><b>iv</b> {@link CryptoOperationData} Initial vector with length of block. Default - zero block</li> * </ul> * </li> * <li>Sign/Verify mode (MAC) * <ul> * <li><b>macLength</b> Length of mac in bits (default - 32 bits)</li> * <li><b>iv</b> {@link CryptoOperationData} Initial vector with length of block. Default - zero block</li> * </ul> * </li> * <li>Wrap/Unwrap key mode (KW) * <ul> * <li><b>keyWrapping</b> Mode of keywrapping, string. Default NO - standard GOST key wrapping</li> * <li><b>ukm</b> {@link CryptoOperationData} User key material. Default - random generated value</li> * </ul> * </li> * <li>Wrap/Unwrap key mode (MASK)</li> * </ul> * * Supported paramters values: * * <ul> * <li>Block modes (parameter 'block') * <ul> * <li><b>ECB</b> "prostaya zamena" (ECB) mode (default)</li> * <li><b>CFB</b> "gammirovanie s obratnoj svyaziyu" (64-bit CFB) mode</li> * <li><b>CTR</b> "gammirovanie" (counter) mode</li> * <li><b>CBC</b> Cipher-Block-Chaining (CBC) mode</li> * </ul> * </li> * <li>Key meshing modes (parameter 'keyMeshing') * <ul> * <li><b>NO</b> No key wrapping (default)</li> * <li><b>CP</b> CryptoPor Key key meshing</li> * </ul> * </li> * <li>Padding modes (parameter 'padding') * <ul> * <li><b>NO</b> No padding only for CFB and CTR modes</li> * <li><b>PKCS5</b> PKCS#5 padding mode</li> * <li><b>ZERO</b> Zero bits padding mode</li> * <li><b>RANDOM</b> Random bits padding mode</li> * </ul> * </li> * <li>Wrapping key modes (parameter 'keyWrapping') * <ul> * <li><b>NO</b> Ref. rfc4357 6.1 GOST 28147-89 Key wrapping</li> * <li><b>CP</b> CryptoPro Key wrapping mode</li> * <li><b>SC</b> SignalCom Key wrapping mode</li> * </ul> * </li> * </ul> * * @memberOf gostEngine * @param {AlgorithmIndentifier} algorithm Algorithm identifier * @returns {GostCipher} Instance of GostCipher */ getGostCipher: function (algorithm) // <editor-fold defaultstate="collapsed"> { return new (GostCipher || (GostCipher = root.GostCipher))(algorithm); }, // </editor-fold> /** * gostEngine.getGostDigest(algorithm) returns GOST R 34.11 cipher instance<br><br> * * Normalized algorithm identifier common parameters: * * <ul> * <li><b>name</b> Algorithm name 'GOST R 34.11'</li> * <li><b>version</b> Algorithm version * <ul> * <li><b>1994</b> old-style 256 bits digest based on GOST 28147-89</li> * <li><b>2012</b> 256 ro 512 bits digest algorithm "Streebog" GOST R 34.11-2012 (default)</li> * </ul> * </li> * <li><b>length</b> Digest length * <ul> * <li><b>256</b> 256 bits digest</li> * <li><b>512</b> 512 bits digest, valid only for algorithm "Streebog"</li> * </ul> * </li> * <li><b>mode</b> Algorithm mode * <ul> * <li><b>HASH</b> simple digest mode (default)</li> * <li><b>HMAC</b> HMAC algorithm based on GOST R 34.11</li> * <li><b>KDF</b> Derive bits for KEK deversification</li> * <li><b>PBKDF2</b> Password based key dirivation algorithms PBKDF2 (based on HMAC)</li> * <li><b>PFXKDF</b> PFX key dirivation algorithms PFXKDF</li> * <li><b>CPKDF</b> CryptoPro Password based key dirivation algorithms</li> * </ul> * </li> * <li><b>sBox</b> Paramset sBox for GOST 28147-89. Used only if version = 1994</li> * </ul> * * Supported algorithms, modes and parameters: * * <ul> * <li>Digest HASH mode (default)</li> * <li>Sign/Verify HMAC modes parameters depends on version and length * <ul> * <li><b>version: 1994</b> HMAC parameters (B = 32, L = 32)</li> * <li><b>version: 2012, length: 256</b> HMAC parameters (B = 64, L = 32)</li> * <li><b>version: 2012, length: 512</b> HMAC parameters (B = 64, L = 64)</li> * </ul> * </li> * <li>DeriveBits/DeriveKey KDF mode * <ul> * <li><b>context</b> {@link CryptoOperationData} Context of the key derivation</li> * <li><b>label</b> {@link CryptoOperationData} Label that identifies the purpose for the derived keying material</li> * </ul> * </li> * <li>DeriveBits/DeriveKey PBKDF2 mode * <ul> * <li><b>salt</b> {@link CryptoOperationData} Random salt as input for HMAC algorithm</li> * <li><b>iterations</b> Iteration count. GOST recomended value 1000 (default) or 2000</li> * </ul> * </li> * <li>DeriveBits/DeriveKey PFXKDF mode * <ul> * <li><b>salt</b> {@link CryptoOperationData} Random salt as input for HMAC algorithm</li> * <li><b>iterations</b> Iteration count. GOST recomended value 1000 (default) or 2000</li> * <li><b>diversifier</b> Deversifier, ID=1 - key material for performing encryption or decryption, * ID=2 - IV (Initial Value) for encryption or decryption, ID=3 - integrity key for MACing</li> * </ul> * </li> * <li>DeriveBits/DeriveKey CPKDF mode * <ul> * <li><b>salt</b> {@link CryptoOperationData} Random salt as input for HMAC algorithm</li> * <li><b>iterations</b> Iteration count. GOST recomended value 1000 (default) or 2000</li> * </ul> * </li> * </ul> * * @memberOf gostEngine * @param {AlgorithmIndentifier} algorithm Algorithm identifier * @returns {GostDigest} Instance of GostDigest */ getGostDigest: function (algorithm) // <editor-fold defaultstate="collapsed"> { return new (GostDigest || (GostDigest = root.GostDigest))(algorithm); }, // </editor-fold> /** * gostEngine.getGostSign(algorithm) returns GOST R 34.10 cipher instance<br><br> * * Normalized algorithm identifier common parameters: * * <ul> * <li><b>name</b> Algorithm name 'GOST R 34.10'</li> * <li><b>version</b> Algorithm version * <ul> * <li><b>1994</b> - Old-style GOST R 34.10-94 ExpMod algorithm with GOST R 34.11-94 hash</li> * <li><b>2001</b> - GOST R 34.10-2001 Eliptic curve algorithm with old GOST R 34.11-94 hash</li> * <li><b>2012</b> - GOST R 34.10-2012 Eliptic curve algorithm with GOST R 34.11-12 hash, default mode</li> * </ul> * </li> * <li><b>length</b> Length of hash and signature. Key length == hash length for EC algorithms and 2 * hash length for ExpMod algorithm * <ul> * <li><b>GOST R 34.10-256</b> - 256 bits digest, default mode</li> * <li><b>GOST R 34.10-512</b> - 512 bits digest only for GOST R 34.11-2012 hash</li> * </ul> * </li> * <li><b>mode</b> Algorithm mode * <ul> * <li><b>SIGN</b> Digital signature mode (default)</li> * <li><b>DH</b> Diffie-Hellman key generation and key agreement mode</li> * <li><b>MASK</b> Key mask mode</li> * </ul> * </li> * <li><b>sBox</b> Paramset sBox for GOST 34.11-94. Used only if version = 1994 or 2001</li> * </ul> * * Supported algorithms, modes and parameters: * * <ul> * <li>Sign/Verify mode (SIGN)</li> * <li>Wrap/Unwrap mode (MASK)</li> * <li>DeriveKey/DeriveBits mode (DH) * <ul> * <li>{@link CryptoOperationData} <b>ukm</b> User key material. Default - random generated value</li> * <li>{@link CryptoOperationData} <b>public</b> The peer's EC public key data</li> * </ul> * </li> * <li>GenerateKey mode (SIGN and DH and MASK) version = 1994 * <ul> * <li><b>namedParam</b> Paramset for key generation algorithm. If specified no additianal parameters required</li> * </ul> * Additional parameters, if namedParam not specified * <ul> * <li><b>modulusLength</b> Bit length of p (512 or 1024 bits). Default = 1024</li> * <li><b>p</b> {@link CryptoOperationData} Modulus, prime number, 2^(t-1)<p<2^t</li> * <li><b>q</b> {@link CryptoOperationData} Order of cyclic group, prime number, 2^254<q<2^256, q is a factor of p-1</li> * <li><b>a</b> {@link CryptoOperationData} Generator, integer, 1<a<p-1, at that aq (mod p) = 1</li> * </ul> * </li> * <li>GenerateKey mode (SIGN and DH and MASK) version = 2001 or 2012 * <ul> * <li><b>namedCurve</b> Paramset for key generation algorithm. If specified no additianal parameters required</li> * </ul> * Additional EC parameters, if namedCurve not specified * <ul> * <li><b>p</b> {@link CryptoOperationData} Prime number - elliptic curve modulus</li> * <li><b>a</b> {@link CryptoOperationData} Coefficients a of the elliptic curve E</li> * <li><b>b</b> {@link CryptoOperationData} Coefficients b of the elliptic curve E</li> * <li><b>q</b> {@link CryptoOperationData} Prime number - order of cyclic group</li> * <li><b>x</b> {@link CryptoOperationData} Base point p x-coordinate</li> * <li><b>y</b> {@link CryptoOperationData} Base point p y-coordinate</li> * </ul> * </li> * </ul> * * @memberOf gostEngine * @param {AlgorithmIndentifier} algorithm Algorithm identifier * @returns {GostSign} Instance of GostSign */ getGostSign: function (algorithm) // <editor-fold defaultstate="collapsed"> { return new (GostSign || (GostSign = root.GostSign))(algorithm); } // </editor-fold> }; /* * Worker method execution * */ // <editor-fold defaultstate="collapsed"> // Worker for gostCripto method execution if (root.importScripts) { /** * Method called when {@link SubtleCrypto} calls its own postMessage() * method with data parameter: algorithm, method and arg.<br> * Call method execute and postMessage() results to onmessage event handler * in the main process.<br> * If error occurred onerror event handler executed in main process. * * @memberOf gostEngine * @name onmessage * @param {MessageEvent} event Message event with data {algorithm, method, args} */ root.onmessage = function (event) { try { postMessage({ id: event.data.id, result: gostEngine.execute(event.data.algorithm, event.data.method, event.data.args)}); } catch (e) { postMessage({ id: event.data.id, error: e.message }); } }; } else { // Load dependens var baseUrl = '', nameSuffix = ''; // Try to define from DOM model if (typeof document !== 'undefined') { (function () { var regs = /^(.*)gostCrypto(.*)\.js$/i; var list = document.querySelectorAll('script'); for (var i = 0, n = list.length; i < n; i++) { var value = list[i].getAttribute('src'); var test = regs.exec(value); if (test) { baseUrl = test[1]; nameSuffix = test[2]; } } })(); } // Local importScripts procedure for include dependens var importScripts = function () { for (var i = 0, n = arguments.length; i < n; i++) { var name = arguments[i].split('.'), src = baseUrl + name[0] + nameSuffix + '.' + name[1]; var el = document.querySelector('script[src="' + src + '"]'); if (!el) { el = document.createElement('script'); el.setAttribute('src', src); document.head.appendChild(el); } } }; // Import engines if (!GostRandom) importScripts('gostRandom.js'); if (!GostCipher) importScripts('gostCipher.js'); if (!GostDigest) importScripts('gostDigest.js'); if (!GostSign) importScripts('gostSign.js'); } // </editor-fold> export default gostEngine;