Compare commits

...

9 Commits

Author SHA1 Message Date
LethalServant 1e87c76db9
Merge 7a6235ff21 into 18159ce806 2024-05-18 16:37:20 +01:00
n1474335 18159ce806
10.18.6 2024-05-16 18:09:22 +01:00
n1474335 86d59783fa
Improved GOST algorithm naming and block size selection 2024-05-16 18:09:12 +01:00
n1474335 fb818c3149
10.18.5 2024-05-16 14:29:46 +01:00
n1474335 37398188f9
Improved testing to account for race conditions 2024-05-16 14:29:32 +01:00
n1474335 d1a0da3f8d
10.18.4 2024-05-13 17:48:41 +01:00
n1474335 57c8c6dbc6
Added operation counts to categories and ops list with option to hide by default for categories. 2024-05-13 17:48:09 +01:00
LethalServant 7a6235ff21 add small fixes 2021-12-12 15:26:35 -05:00
LethalServant 31dc316192 updates DNSOverHTTPS operation to handle multiple FQDN lookups 2021-12-12 15:25:53 -05:00
20 changed files with 309 additions and 113 deletions

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "cyberchef",
"version": "10.18.3",
"version": "10.18.6",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "cyberchef",
"version": "10.18.3",
"version": "10.18.6",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {

View File

@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "10.18.3",
"version": "10.18.6",
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
"author": "n1474335 <n1474335@gmail.com>",
"homepage": "https://gchq.github.io/CyberChef",

View File

@ -20,7 +20,7 @@ class DNSOverHTTPS extends Operation {
this.name = "DNS over HTTPS";
this.module = "Default";
this.description = [
"Takes a single domain name and performs a DNS lookup using DNS over HTTPS.",
"Takes one or more FQDN(s) that are seperated by newlines, and performs a DNS lookup using DNS over HTTPS.",
"<br><br>",
"By default, <a href='https://developers.cloudflare.com/1.1.1.1/dns-over-https/'>Cloudflare</a> and <a href='https://developers.google.com/speed/public-dns/docs/dns-over-https'>Google</a> DNS over HTTPS services are supported.",
"<br><br>",
@ -99,24 +99,45 @@ class DNSOverHTTPS extends Operation {
url = new URL(resolver);
} catch (error) {
throw new OperationError(error.toString() +
"\n\nThis error could be caused by one of the following:\n" +
" - An invalid Resolver URL\n");
"\n\nThis error could be caused by one of the following:\n" +
" - An invalid Resolver URL\n");
}
const params = {name: input, type: requestType, cd: DNSSEC};
url.search = new URLSearchParams(params);
let fqdns = processInput(input);
return fetch(url, {headers: {"accept": "application/dns-json"}}).then(response => {
return response.json();
}).then(data => {
if (justAnswer) {
return extractData(data.Answer);
}
return data;
}).catch(e => {
throw new OperationError(`Error making request to ${url}\n${e.toString()}`);
});
let fqdnPromises = [];
for (let index = 0; index < fqdns.length; index++) {
const params = { name: fqdns[index], type: requestType, cd: DNSSEC };
url.search = new URLSearchParams(params);
let fqdnPromise = fetch(url, { headers: { "accept": "application/dns-json" } }).then(response => {
return response.json();
}).then(data => {
if (justAnswer) {
if (data.Answer) {
return extractData(data.Answer);
} else {
if(data.Question.length > 0){
let r = {};
r[data.Question[0].name] = null;
return r;
} else {
return null;
}
}
} else {
return data;
}
}).catch(e => {
return `Error making request to ${url}\n${e.toString()}`;
});
fqdnPromises.push(fqdnPromise);
}
return Promise.all(fqdnPromises);
}
}
@ -128,15 +149,43 @@ class DNSOverHTTPS extends Operation {
* @returns {JSON}
*/
function extractData(data) {
if (typeof(data) == "undefined") {
if (typeof (data) == "undefined") {
return [];
} else {
const dataValues = [];
let dataValues = {};
data.forEach(element => {
dataValues.push(element.data);
if (!(element.name in dataValues)) {
dataValues[element.name] = [];
}
if (!(element.data in dataValues[element.name])) {
dataValues[element.name].push(element.data);
}
});
return dataValues;
}
}
/**
* Process and clean input data
*
* @private
* @param {string} input
* @returns {Array[string]} list of fqdns
*/
function processInput(input) {
let fqdns = [];
let fqdnRegex = /[A-Za-z0-9\.]*/;
input.split('\n').forEach((fqdn, index) => {
let m = fqdn.match(fqdnRegex);
if (m.length > 0) {
if (m[0] !== '') {
fqdns.push(m[0]);
}
}
});
return fqdns;
}
export default DNSOverHTTPS;

View File

@ -55,22 +55,19 @@ class GOSTDecrypt extends Operation {
type: "argSelector",
value: [
{
name: "GOST 28147 (Magma, 1989)",
off: [5],
name: "GOST 28147 (1989)",
on: [6]
},
{
name: "GOST R 34.12 (Magma, 2015)",
off: [5]
},
{
name: "GOST R 34.12 (Kuznyechik, 2015)",
on: [5],
off: [6]
off: [5]
}
]
},
{
name: "Block length",
type: "option",
value: ["64", "128"]
},
{
name: "sBox",
type: "option",
@ -100,14 +97,30 @@ class GOSTDecrypt extends Operation {
* @returns {string}
*/
async run(input, args) {
const [keyObj, ivObj, inputType, outputType, version, length, sBox, blockMode, keyMeshing, padding] = args;
const [keyObj, ivObj, inputType, outputType, version, sBox, blockMode, keyMeshing, padding] = args;
const key = toHexFast(Utils.convertToByteArray(keyObj.string, keyObj.option));
const iv = toHexFast(Utils.convertToByteArray(ivObj.string, ivObj.option));
input = inputType === "Hex" ? input : toHexFast(Utils.strToArrayBuffer(input));
const versionNum = version === "GOST 28147 (Magma, 1989)" ? 1989 : 2015;
const blockLength = versionNum === 1989 ? 64 : parseInt(length, 10);
let blockLength, versionNum;
switch (version) {
case "GOST 28147 (1989)":
versionNum = 1989;
blockLength = 64;
break;
case "GOST R 34.12 (Magma, 2015)":
versionNum = 2015;
blockLength = 64;
break;
case "GOST R 34.12 (Kuznyechik, 2015)":
versionNum = 2015;
blockLength = 128;
break;
default:
throw new OperationError(`Unknown algorithm version: ${version}`);
}
const sBoxVal = versionNum === 1989 ? sBox : null;
const algorithm = {

View File

@ -55,22 +55,19 @@ class GOSTEncrypt extends Operation {
type: "argSelector",
value: [
{
name: "GOST 28147 (Magma, 1989)",
off: [5],
name: "GOST 28147 (1989)",
on: [6]
},
{
name: "GOST R 34.12 (Magma, 2015)",
off: [5]
},
{
name: "GOST R 34.12 (Kuznyechik, 2015)",
on: [5],
off: [6]
off: [5]
}
]
},
{
name: "Block length",
type: "option",
value: ["64", "128"]
},
{
name: "sBox",
type: "option",
@ -100,14 +97,30 @@ class GOSTEncrypt extends Operation {
* @returns {string}
*/
async run(input, args) {
const [keyObj, ivObj, inputType, outputType, version, length, sBox, blockMode, keyMeshing, padding] = args;
const [keyObj, ivObj, inputType, outputType, version, sBox, blockMode, keyMeshing, padding] = args;
const key = toHexFast(Utils.convertToByteArray(keyObj.string, keyObj.option));
const iv = toHexFast(Utils.convertToByteArray(ivObj.string, ivObj.option));
input = inputType === "Hex" ? input : toHexFast(Utils.strToArrayBuffer(input));
const versionNum = version === "GOST 28147 (Magma, 1989)" ? 1989 : 2015;
const blockLength = versionNum === 1989 ? 64 : parseInt(length, 10);
let blockLength, versionNum;
switch (version) {
case "GOST 28147 (1989)":
versionNum = 1989;
blockLength = 64;
break;
case "GOST R 34.12 (Magma, 2015)":
versionNum = 2015;
blockLength = 64;
break;
case "GOST R 34.12 (Kuznyechik, 2015)":
versionNum = 2015;
blockLength = 128;
break;
default:
throw new OperationError(`Unknown algorithm version: ${version}`);
}
const sBoxVal = versionNum === 1989 ? sBox : null;
const algorithm = {

View File

@ -55,22 +55,19 @@ class GOSTKeyUnwrap extends Operation {
type: "argSelector",
value: [
{
name: "GOST 28147 (Magma, 1989)",
off: [5],
name: "GOST 28147 (1989)",
on: [6]
},
{
name: "GOST R 34.12 (Magma, 2015)",
off: [5]
},
{
name: "GOST R 34.12 (Kuznyechik, 2015)",
on: [5],
off: [6]
off: [5]
}
]
},
{
name: "Block length",
type: "option",
value: ["64", "128"]
},
{
name: "sBox",
type: "option",
@ -90,14 +87,30 @@ class GOSTKeyUnwrap extends Operation {
* @returns {string}
*/
async run(input, args) {
const [keyObj, ukmObj, inputType, outputType, version, length, sBox, keyWrapping] = args;
const [keyObj, ukmObj, inputType, outputType, version, sBox, keyWrapping] = args;
const key = toHexFast(Utils.convertToByteArray(keyObj.string, keyObj.option));
const ukm = toHexFast(Utils.convertToByteArray(ukmObj.string, ukmObj.option));
input = inputType === "Hex" ? input : toHexFast(Utils.strToArrayBuffer(input));
const versionNum = version === "GOST 28147 (Magma, 1989)" ? 1989 : 2015;
const blockLength = versionNum === 1989 ? 64 : parseInt(length, 10);
let blockLength, versionNum;
switch (version) {
case "GOST 28147 (1989)":
versionNum = 1989;
blockLength = 64;
break;
case "GOST R 34.12 (Magma, 2015)":
versionNum = 2015;
blockLength = 64;
break;
case "GOST R 34.12 (Kuznyechik, 2015)":
versionNum = 2015;
blockLength = 128;
break;
default:
throw new OperationError(`Unknown algorithm version: ${version}`);
}
const sBoxVal = versionNum === 1989 ? sBox : null;
const algorithm = {

View File

@ -55,22 +55,19 @@ class GOSTKeyWrap extends Operation {
type: "argSelector",
value: [
{
name: "GOST 28147 (Magma, 1989)",
off: [5],
name: "GOST 28147 (1989)",
on: [6]
},
{
name: "GOST R 34.12 (Magma, 2015)",
off: [5]
},
{
name: "GOST R 34.12 (Kuznyechik, 2015)",
on: [5],
off: [6]
off: [5]
}
]
},
{
name: "Block length",
type: "option",
value: ["64", "128"]
},
{
name: "sBox",
type: "option",
@ -90,14 +87,30 @@ class GOSTKeyWrap extends Operation {
* @returns {string}
*/
async run(input, args) {
const [keyObj, ukmObj, inputType, outputType, version, length, sBox, keyWrapping] = args;
const [keyObj, ukmObj, inputType, outputType, version, sBox, keyWrapping] = args;
const key = toHexFast(Utils.convertToByteArray(keyObj.string, keyObj.option));
const ukm = toHexFast(Utils.convertToByteArray(ukmObj.string, ukmObj.option));
input = inputType === "Hex" ? input : toHexFast(Utils.strToArrayBuffer(input));
const versionNum = version === "GOST 28147 (Magma, 1989)" ? 1989 : 2015;
const blockLength = versionNum === 1989 ? 64 : parseInt(length, 10);
let blockLength, versionNum;
switch (version) {
case "GOST 28147 (1989)":
versionNum = 1989;
blockLength = 64;
break;
case "GOST R 34.12 (Magma, 2015)":
versionNum = 2015;
blockLength = 64;
break;
case "GOST R 34.12 (Kuznyechik, 2015)":
versionNum = 2015;
blockLength = 128;
break;
default:
throw new OperationError(`Unknown algorithm version: ${version}`);
}
const sBoxVal = versionNum === 1989 ? sBox : null;
const algorithm = {

View File

@ -55,22 +55,19 @@ class GOSTSign extends Operation {
type: "argSelector",
value: [
{
name: "GOST 28147 (Magma, 1989)",
off: [5],
name: "GOST 28147 (1989)",
on: [6]
},
{
name: "GOST R 34.12 (Magma, 2015)",
off: [5]
},
{
name: "GOST R 34.12 (Kuznyechik, 2015)",
on: [5],
off: [6]
off: [5]
}
]
},
{
name: "Block length",
type: "option",
value: ["64", "128"]
},
{
name: "sBox",
type: "option",
@ -93,14 +90,30 @@ class GOSTSign extends Operation {
* @returns {string}
*/
async run(input, args) {
const [keyObj, ivObj, inputType, outputType, version, length, sBox, macLength] = args;
const [keyObj, ivObj, inputType, outputType, version, sBox, macLength] = args;
const key = toHexFast(Utils.convertToByteArray(keyObj.string, keyObj.option));
const iv = toHexFast(Utils.convertToByteArray(ivObj.string, ivObj.option));
input = inputType === "Hex" ? input : toHexFast(Utils.strToArrayBuffer(input));
const versionNum = version === "GOST 28147 (Magma, 1989)" ? 1989 : 2015;
const blockLength = versionNum === 1989 ? 64 : parseInt(length, 10);
let blockLength, versionNum;
switch (version) {
case "GOST 28147 (1989)":
versionNum = 1989;
blockLength = 64;
break;
case "GOST R 34.12 (Magma, 2015)":
versionNum = 2015;
blockLength = 64;
break;
case "GOST R 34.12 (Kuznyechik, 2015)":
versionNum = 2015;
blockLength = 128;
break;
default:
throw new OperationError(`Unknown algorithm version: ${version}`);
}
const sBoxVal = versionNum === 1989 ? sBox : null;
const algorithm = {

View File

@ -56,22 +56,19 @@ class GOSTVerify extends Operation {
type: "argSelector",
value: [
{
name: "GOST 28147 (Magma, 1989)",
off: [5],
name: "GOST 28147 (1989)",
on: [6]
},
{
name: "GOST R 34.12 (Magma, 2015)",
off: [5]
},
{
name: "GOST R 34.12 (Kuznyechik, 2015)",
on: [5],
off: [6]
off: [5]
}
]
},
{
name: "Block length",
type: "option",
value: ["64", "128"]
},
{
name: "sBox",
type: "option",
@ -86,15 +83,31 @@ class GOSTVerify extends Operation {
* @returns {string}
*/
async run(input, args) {
const [keyObj, ivObj, macObj, inputType, version, length, sBox] = args;
const [keyObj, ivObj, macObj, inputType, version, sBox] = args;
const key = toHexFast(Utils.convertToByteArray(keyObj.string, keyObj.option));
const iv = toHexFast(Utils.convertToByteArray(ivObj.string, ivObj.option));
const mac = toHexFast(Utils.convertToByteArray(macObj.string, macObj.option));
input = inputType === "Hex" ? input : toHexFast(Utils.strToArrayBuffer(input));
const versionNum = version === "GOST 28147 (Magma, 1989)" ? 1989 : 2015;
const blockLength = versionNum === 1989 ? 64 : parseInt(length, 10);
let blockLength, versionNum;
switch (version) {
case "GOST 28147 (1989)":
versionNum = 1989;
blockLength = 64;
break;
case "GOST R 34.12 (Magma, 2015)":
versionNum = 2015;
blockLength = 64;
break;
case "GOST R 34.12 (Kuznyechik, 2015)":
versionNum = 2015;
blockLength = 128;
break;
default:
throw new OperationError(`Unknown algorithm version: ${version}`);
}
const sBoxVal = versionNum === 1989 ? sBox : null;
const algorithm = {

View File

@ -42,6 +42,9 @@ class HTMLCategory {
let html = `<div class="panel category">
<a class="category-title" data-toggle="collapse" data-target="#${catName}">
${this.name}
<span class="op-count hidden">
${this.opList.length}
</span>
</a>
<div id="${catName}" class="panel-collapse collapse ${(this.selected ? " show" : "")}" data-parent="#categories">
<ul class="op-list">`;

View File

@ -229,6 +229,7 @@ class Manager {
this.addDynamicListener(".option-item input[type=checkbox]", "change", this.options.switchChange, this.options);
this.addDynamicListener(".option-item input[type=checkbox]#wordWrap", "change", this.options.setWordWrap, this.options);
this.addDynamicListener(".option-item input[type=checkbox]#useMetaKey", "change", this.bindings.updateKeybList, this.bindings);
this.addDynamicListener(".option-item input[type=checkbox]#showCatCount", "change", this.ops.setCatCount, this.ops);
this.addDynamicListener(".option-item input[type=number]", "keyup", this.options.numberChange, this.options);
this.addDynamicListener(".option-item input[type=number]", "change", this.options.numberChange, this.options);
this.addDynamicListener(".option-item select", "change", this.options.selectChange, this.options);

View File

@ -171,6 +171,7 @@
<div id="operations" class="split split-horizontal no-select">
<div class="title no-select" data-help-title="Operations list" data-help="<p>The Operations list contains all the operations in CyberChef arranged into categories. Some operations may be present in multiple categories. You can search for operations using the search box.</p><p>To use an operation, either double click it, or drag it into the Recipe pane. You will then be able to configure its arguments (or 'Ingredients' in CyberChef terminology).</p>">
Operations
<span class="op-count"></span>
</div>
<input id="search" type="search" class="form-control" placeholder="Search..." autocomplete="off" tabindex="2" data-help-title="Searching for operations" data-help="<p>Use the search box to find useful operations.</p><p>Both operation names and descriptions are queried using a fuzzy matching algorithm.</p>">
<ul id="search-results" class="op-list"></ul>
@ -521,6 +522,13 @@
Keep the current tab in sync between the input and output
</label>
</div>
<div class="checkbox option-item">
<label for="showCatCount">
<input type="checkbox" option="showCatCount" id="showCatCount">
Show the number of operations in each category
</label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" id="reset-options">Reset options to default</button>

View File

@ -51,7 +51,8 @@ function main() {
logLevel: "info",
autoMagic: true,
imagePreview: true,
syncTabs: true
syncTabs: true,
showCatCount: false,
};
document.removeEventListener("DOMContentLoaded", main, false);

View File

@ -40,4 +40,13 @@
margin: 0 !important;
border-radius: 0 !important;
border: none;
}
}
.op-count {
float: right;
color: var(--subtext-font-colour);
font-weight: normal;
font-size: xx-small;
opacity: 0.5;
padding-left: .5em;
}

View File

@ -36,6 +36,10 @@ body {
line-height: 0;
}
.hidden {
display: none;
}
.blur {
color: transparent !important;
text-shadow: rgba(0, 0, 0, 0.95) 0 0 10px !important;

View File

@ -168,6 +168,10 @@ class OperationsWaiter {
*/
opListCreate(e) {
this.manager.recipe.createSortableSeedList(e.target);
// Populate ops total
document.querySelector("#operations .title .op-count").innerText = Object.keys(this.app.operations).length;
this.enableOpsListPopovers(e.target);
}
@ -293,6 +297,18 @@ class OperationsWaiter {
this.app.resetFavourites();
}
/**
* Sets whether operation counts are displayed next to a category title
*/
setCatCount() {
if (this.app.options.showCatCount) {
document.querySelectorAll(".category-title .op-count").forEach(el => el.classList.remove("hidden"));
} else {
document.querySelectorAll(".category-title .op-count").forEach(el => el.classList.add("hidden"));
}
}
}
export default OperationsWaiter;

View File

@ -50,6 +50,7 @@ class OptionsWaiter {
// Initialise options
this.setWordWrap();
this.manager.ops.setCatCount();
}

View File

@ -430,7 +430,7 @@ function bakeOp(browser, opName, input, args=[]) {
*/
function testOp(browser, opName, input, output, args=[]) {
bakeOp(browser, opName, input, args);
utils.expectOutput(browser, output);
utils.expectOutput(browser, output, true);
}
/** @function

View File

@ -41,6 +41,7 @@ function setInput(browser, input, type=true) {
}, [input]);
browser.pause(100);
}
expectInput(browser, input);
}
/** @function
@ -49,6 +50,11 @@ function setInput(browser, input, type=true) {
* @param {Browser} browser - Nightwatch client
*/
function bake(browser) {
browser
// Ensure we're not currently busy
.waitForElementNotVisible("#output-loader", 5000)
.expect.element("#bake span").text.to.equal("BAKE!");
browser
.click("#bake")
.waitForElementNotVisible("#stale-indicator", 5000)
@ -162,7 +168,6 @@ function loadRecipe(browser, opName, input, args) {
throw new Error("Invalid operation type. Must be string or array of strings. Received: " + typeof(opName));
}
clear(browser);
setInput(browser, input, false);
browser
.urlHash("recipe=" + recipeConfig)
@ -174,8 +179,18 @@ function loadRecipe(browser, opName, input, args) {
*
* @param {Browser} browser - Nightwatch client
* @param {string|RegExp} expected - The expected output value
* @param {boolean} [waitNotNull=false] - Wait for the output to not be empty before testing the value
*/
function expectOutput(browser, expected) {
function expectOutput(browser, expected, waitNotNull=false) {
if (waitNotNull && expected !== "") {
browser.waitUntil(async function() {
const output = await this.execute(function() {
return window.app.manager.output.outputEditorView.state.doc.toString();
});
return output.length;
}, 1000);
}
browser.execute(expected => {
return window.app.manager.output.outputEditorView.state.doc.toString();
}, [expected], function({value}) {
@ -187,6 +202,24 @@ function expectOutput(browser, expected) {
});
}
/** @function
* Tests whether the input matches a given value
*
* @param {Browser} browser - Nightwatch client
* @param {string|RegExp} expected - The expected input value
*/
function expectInput(browser, expected) {
browser.execute(expected => {
return window.app.manager.input.inputEditorView.state.doc.toString();
}, [expected], function({value}) {
if (expected instanceof RegExp) {
browser.expect(value).match(expected);
} else {
browser.expect(value).to.be.equal(expected);
}
});
}
/** @function
* Uploads a file using the #open-file input
*
@ -246,6 +279,7 @@ module.exports = {
paste: paste,
loadRecipe: loadRecipe,
expectOutput: expectOutput,
expectInput: expectInput,
uploadFile: uploadFile,
uploadFolder: uploadFolder
};

View File

@ -14,7 +14,7 @@ import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
{
name: "GOST Encrypt: Magma",
name: "GOST Encrypt: 1989",
input: "Hello, World!",
expectedOutput: "f124ac5c0853870906dbaf9b56",
recipeConfig: [
@ -25,8 +25,7 @@ TestRegister.addTests([
{ "option": "Hex", "string": "0011223344556677" },
"Raw",
"Hex",
"GOST 28147 (Magma, 1989)",
"64",
"GOST 28147 (1989)",
"E-SC",
"OFB",
"CP",
@ -48,7 +47,6 @@ TestRegister.addTests([
"Raw",
"Hex",
"GOST R 34.12 (Kuznyechik, 2015)",
"128",
"E-SC",
"CBC",
"CP",
@ -58,7 +56,7 @@ TestRegister.addTests([
],
},
{
name: "GOST Decrypt: Magma",
name: "GOST Decrypt: 1989",
input: "f124ac5c0853870906dbaf9b56",
expectedOutput: "Hello, World!",
recipeConfig: [
@ -69,8 +67,7 @@ TestRegister.addTests([
{ "option": "Hex", "string": "0011223344556677" },
"Hex",
"Raw",
"GOST 28147 (Magma, 1989)",
"128",
"GOST 28147 (1989)",
"E-SC",
"OFB",
"CP",
@ -92,7 +89,6 @@ TestRegister.addTests([
"Hex",
"Raw",
"GOST R 34.12 (Kuznyechik, 2015)",
"128",
"E-TEST",
"CBC",
"CP",
@ -113,8 +109,7 @@ TestRegister.addTests([
{ "option": "Hex", "string": "0011223344556677" },
"Raw",
"Hex",
"GOST 28147 (Magma, 1989)",
"64",
"GOST 28147 (1989)",
"E-C",
48
]
@ -134,7 +129,6 @@ TestRegister.addTests([
{ "option": "Hex", "string": "42b77fb3d6f6bf04" },
"Raw",
"GOST R 34.12 (Kuznyechik, 2015)",
"128",
"E-TEST"
]
}
@ -152,8 +146,7 @@ TestRegister.addTests([
{ "option": "Hex", "string": "0011223344556677" },
"Raw",
"Hex",
"GOST R 34.12 (Kuznyechik, 2015)",
"64",
"GOST R 34.12 (Magma, 2015)",
"E-TEST",
"CP"
]
@ -172,8 +165,7 @@ TestRegister.addTests([
{ "option": "Latin1", "string": "00112233" },
"Hex",
"Raw",
"GOST 28147 (Magma, 1989)",
"64",
"GOST 28147 (1989)",
"E-Z",
"CP"
]