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/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..5a845c70 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 @@ -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; 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"] } + ] + }, +]);