CyberChef/src/core/lib/Rotate.mjs

104 lines
2.3 KiB
JavaScript

/**
* Bit rotation functions.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2016
* @license Apache-2.0
*
* @todo Support for UTF16
*/
/**
* Runs rotation operations across the input data.
*
* @param {byteArray} data
* @param {number} amount
* @param {function} algo - The rotation operation to carry out
* @returns {byteArray}
*/
export function rot(data, amount, algo) {
const result = [];
for (let i = 0; i < data.length; i++) {
let b = data[i];
for (let j = 0; j < amount; j++) {
b = algo(b);
}
result.push(b);
}
return result;
}
/**
* Rotate right bitwise op.
*
* @param {byte} b
* @returns {byte}
*/
export function rotr(b) {
const bit = (b & 1) << 7;
return (b >> 1) | bit;
}
/**
* Rotate left bitwise op.
*
* @param {byte} b
* @returns {byte}
*/
export function rotl(b) {
const bit = (b >> 7) & 1;
return ((b << 1) | bit) & 0xFF;
}
/**
* Rotates a byte array to the right by a specific amount as a whole, so that bits are wrapped
* from the end of the array to the beginning.
*
* @param {byteArray} data
* @param {number} amount
* @returns {byteArray}
*/
export function rotrCarry(data, amount) {
const result = [];
let carryBits = 0,
newByte;
amount = amount % 8;
for (let i = 0; i < data.length; i++) {
const oldByte = data[i] >>> 0;
newByte = (oldByte >> amount) | carryBits;
carryBits = (oldByte & (Math.pow(2, amount)-1)) << (8-amount);
result.push(newByte);
}
result[0] |= carryBits;
return result;
}
/**
* Rotates a byte array to the left by a specific amount as a whole, so that bits are wrapped
* from the beginning of the array to the end.
*
* @param {byteArray} data
* @param {number} amount
* @returns {byteArray}
*/
export function rotlCarry(data, amount) {
const result = [];
let carryBits = 0,
newByte;
amount = amount % 8;
for (let i = data.length-1; i >= 0; i--) {
const oldByte = data[i];
newByte = ((oldByte << amount) | carryBits) & 0xFF;
carryBits = (oldByte >> (8-amount)) & (Math.pow(2, amount)-1);
result[i] = (newByte);
}
result[data.length-1] = result[data.length-1] | carryBits;
return result;
}