From 1b628ac2130565c8107177c4b3155757d417e62a Mon Sep 17 00:00:00 2001 From: n1474335 Date: Tue, 5 Sep 2017 14:26:09 +0000 Subject: [PATCH 1/2] Added 'Bit shift left' and 'Bit shift right' operations --- src/core/config/Categories.js | 2 ++ src/core/config/OperationConfig.js | 52 +++++++++++++++++++++++++----- src/core/operations/BitwiseOp.js | 40 +++++++++++++++++++++++ src/core/operations/ByteRepr.js | 2 +- src/core/operations/Rotate.js | 10 +++--- test/index.js | 1 + test/tests/operations/BitwiseOp.js | 50 ++++++++++++++++++++++++++++ 7 files changed, 143 insertions(+), 14 deletions(-) create mode 100644 test/tests/operations/BitwiseOp.js diff --git a/src/core/config/Categories.js b/src/core/config/Categories.js index 07664f87..93b57a19 100755 --- a/src/core/config/Categories.js +++ b/src/core/config/Categories.js @@ -122,6 +122,8 @@ const Categories = [ "AND", "ADD", "SUB", + "Bit shift left", + "Bit shift right", "Rotate left", "Rotate right", "ROT13", diff --git a/src/core/config/OperationConfig.js b/src/core/config/OperationConfig.js index e4210db2..cd7ca35c 100755 --- a/src/core/config/OperationConfig.js +++ b/src/core/config/OperationConfig.js @@ -1595,7 +1595,7 @@ const OperationConfig = { args: [] }, "Rotate right": { - description: "Rotates each byte to the right by the number of bits specified. Currently only supports 8-bit values.", + description: "Rotates each byte to the right by the number of bits specified, optionally carrying the excess bits over to the next byte. Currently only supports 8-bit values.", run: Rotate.runRotr, highlight: true, highlightReverse: true, @@ -1603,19 +1603,19 @@ const OperationConfig = { outputType: "byteArray", args: [ { - name: "Number of bits", + name: "Amount", type: "number", value: Rotate.ROTATE_AMOUNT }, { - name: "Rotate as a whole", + name: "Carry through", type: "boolean", - value: Rotate.ROTATE_WHOLE + value: Rotate.ROTATE_CARRY } ] }, "Rotate left": { - description: "Rotates each byte to the left by the number of bits specified. Currently only supports 8-bit values.", + description: "Rotates each byte to the left by the number of bits specified, optionally carrying the excess bits over to the next byte. Currently only supports 8-bit values.", run: Rotate.runRotl, highlight: true, highlightReverse: true, @@ -1623,14 +1623,14 @@ const OperationConfig = { outputType: "byteArray", args: [ { - name: "Number of bits", + name: "Amount", type: "number", value: Rotate.ROTATE_AMOUNT }, { - name: "Rotate as a whole", + name: "Carry through", type: "boolean", - value: Rotate.ROTATE_WHOLE + value: Rotate.ROTATE_CARRY } ] }, @@ -3600,6 +3600,42 @@ const OperationConfig = { ] }, + "Bit shift left": { + description: "Shifts the bits in each byte towards the left by the specified amount.", + run: BitwiseOp.runBitShiftLeft, + inputType: "byteArray", + outputType: "byteArray", + highlight: true, + highlightReverse: true, + args: [ + { + name: "Amount", + type: "number", + value: 1 + }, + ] + }, + "Bit shift right": { + description: "Shifts the bits in each byte towards the right by the specified amount.

Logical shifts replace the leftmost bits with zeros.
Arithmetic shifts preserve the most significant bit (MSB) of the original byte keeping the sign the same (positive or negative).", + run: BitwiseOp.runBitShiftRight, + inputType: "byteArray", + outputType: "byteArray", + highlight: true, + highlightReverse: true, + args: [ + { + name: "Amount", + type: "number", + value: 1 + }, + { + name: "Type", + type: "option", + value: BitwiseOp.BIT_SHIFT_TYPE + } + ] + }, + }; export default OperationConfig; diff --git a/src/core/operations/BitwiseOp.js b/src/core/operations/BitwiseOp.js index 15d778c7..bc971136 100755 --- a/src/core/operations/BitwiseOp.js +++ b/src/core/operations/BitwiseOp.js @@ -228,6 +228,46 @@ const BitwiseOp = { }, + /** + * Bit shift left operation. + * + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + runBitShiftLeft: function(input, args) { + const amount = args[0]; + + return input.map(b => { + return (b << amount) & 0xff; + }); + }, + + + /** + * @constant + * @default + */ + BIT_SHIFT_TYPE: ["Logical shift", "Arithmetic shift"], + + /** + * Bit shift right operation. + * + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + runBitShiftRight: function(input, args) { + const amount = args[0], + type = args[1], + mask = type === "Logical shift" ? 0 : 0x80; + + return input.map(b => { + return (b >>> amount) ^ (b & mask); + }); + }, + + /** * XOR bitwise calculation. * diff --git a/src/core/operations/ByteRepr.js b/src/core/operations/ByteRepr.js index 5e6f2aa8..4554d8ef 100755 --- a/src/core/operations/ByteRepr.js +++ b/src/core/operations/ByteRepr.js @@ -196,7 +196,7 @@ const ByteRepr = { /** - * Highlight to hex + * Highlight from hex * * @param {Object[]} pos * @param {number} pos[].start diff --git a/src/core/operations/Rotate.js b/src/core/operations/Rotate.js index d66dbdae..9125e575 100755 --- a/src/core/operations/Rotate.js +++ b/src/core/operations/Rotate.js @@ -20,7 +20,7 @@ const Rotate = { * @constant * @default */ - ROTATE_WHOLE: false, + ROTATE_CARRY: false, /** * Runs rotation operations across the input data. @@ -53,7 +53,7 @@ const Rotate = { */ runRotr: function(input, args) { if (args[1]) { - return Rotate._rotrWhole(input, args[0]); + return Rotate._rotrCarry(input, args[0]); } else { return Rotate._rot(input, args[0], Rotate._rotr); } @@ -69,7 +69,7 @@ const Rotate = { */ runRotl: function(input, args) { if (args[1]) { - return Rotate._rotlWhole(input, args[0]); + return Rotate._rotlCarry(input, args[0]); } else { return Rotate._rot(input, args[0], Rotate._rotl); } @@ -197,7 +197,7 @@ const Rotate = { * @param {number} amount * @returns {byteArray} */ - _rotrWhole: function(data, amount) { + _rotrCarry: function(data, amount) { let carryBits = 0, newByte, result = []; @@ -223,7 +223,7 @@ const Rotate = { * @param {number} amount * @returns {byteArray} */ - _rotlWhole: function(data, amount) { + _rotlCarry: function(data, amount) { let carryBits = 0, newByte, result = []; diff --git a/test/index.js b/test/index.js index 91c0410e..9d9824d6 100644 --- a/test/index.js +++ b/test/index.js @@ -13,6 +13,7 @@ import "babel-polyfill"; import TestRegister from "./TestRegister.js"; import "./tests/operations/Base58.js"; import "./tests/operations/BCD.js"; +import "./tests/operations/BitwiseOp.js"; import "./tests/operations/ByteRepr.js"; import "./tests/operations/CharEnc.js"; import "./tests/operations/Cipher.js"; diff --git a/test/tests/operations/BitwiseOp.js b/test/tests/operations/BitwiseOp.js new file mode 100644 index 00000000..ba196be2 --- /dev/null +++ b/test/tests/operations/BitwiseOp.js @@ -0,0 +1,50 @@ +/** + * BitwiseOp tests + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ +import TestRegister from "../../TestRegister.js"; + +TestRegister.addTests([ + { + name: "Bit shift left", + input: "01010101 10101010 11111111 00000000 11110000 00001111 00110011 11001100", + expectedOutput: "10101010 01010100 11111110 00000000 11100000 00011110 01100110 10011000", + recipeConfig: [ + { "op": "From Binary", + "args": ["Space"] }, + { "op": "Bit shift left", + "args": [1] }, + { "op": "To Binary", + "args": ["Space"] } + ] + }, + { + name: "Bit shift right: Logical shift", + input: "01010101 10101010 11111111 00000000 11110000 00001111 00110011 11001100", + expectedOutput: "00101010 01010101 01111111 00000000 01111000 00000111 00011001 01100110", + recipeConfig: [ + { "op": "From Binary", + "args": ["Space"] }, + { "op": "Bit shift right", + "args": [1, "Logical shift"] }, + { "op": "To Binary", + "args": ["Space"] } + ] + }, + { + name: "Bit shift right: Arithmetic shift", + input: "01010101 10101010 11111111 00000000 11110000 00001111 00110011 11001100", + expectedOutput: "00101010 11010101 11111111 00000000 11111000 00000111 00011001 11100110", + recipeConfig: [ + { "op": "From Binary", + "args": ["Space"] }, + { "op": "Bit shift right", + "args": [1, "Arithmetic shift"] }, + { "op": "To Binary", + "args": ["Space"] } + ] + }, +]); From d4d12c3db01d9bb1cb0c75a78493fb29a0c57b47 Mon Sep 17 00:00:00 2001 From: n1474335 Date: Tue, 5 Sep 2017 14:30:06 +0000 Subject: [PATCH 2/2] Whitespace is now removed from hex and binary even when the delimiter is set to 'None' --- src/core/Utils.js | 3 ++- src/core/operations/ByteRepr.js | 6 ++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/core/Utils.js b/src/core/Utils.js index b5caf0b9..508c8e07 100755 --- a/src/core/Utils.js +++ b/src/core/Utils.js @@ -1235,7 +1235,8 @@ const Utils = { "Forward slash": /\//g, "Backslash": /\\/g, "0x": /0x/g, - "\\x": /\\x/g + "\\x": /\\x/g, + "None": /\s+/g // Included here to remove whitespace when there shouldn't be any }, diff --git a/src/core/operations/ByteRepr.js b/src/core/operations/ByteRepr.js index 4554d8ef..5a845c70 100755 --- a/src/core/operations/ByteRepr.js +++ b/src/core/operations/ByteRepr.js @@ -288,10 +288,8 @@ const ByteRepr = { * @returns {byteArray} */ runFromBinary: function(input, args) { - if (args[0] !== "None") { - const delimRegex = Utils.regexRep[args[0] || "Space"]; - input = input.replace(delimRegex, ""); - } + const delimRegex = Utils.regexRep[args[0] || "Space"]; + input = input.replace(delimRegex, ""); const output = []; const byteLen = 8;