2018-05-23 18:59:57 +01:00
/ * *
* @ author n1474335 [ n1474335 @ gmail . com ]
* @ copyright Crown Copyright 2016
* @ license Apache - 2.0
* /
2019-07-09 12:23:59 +01:00
import Operation from "../Operation.mjs" ;
import Utils from "../Utils.mjs" ;
2023-03-30 23:51:19 -07:00
import { bitOp , xor , add , BITWISE _OP _DELIMS } from "../lib/BitwiseOp.mjs" ;
2018-05-23 18:59:57 +01:00
/ * *
* XOR operation
* /
class XOR extends Operation {
/ * *
* XOR constructor
* /
constructor ( ) {
super ( ) ;
this . name = "XOR" ;
this . module = "Default" ;
2023-03-30 23:51:19 -07:00
this . description = "XOR the input with the given key.<br>e.g. <code>fe023da5</code><br><br><strong>Options</strong><br><u>Null preserving:</u> If the current byte is 0x00 or the same as the key, skip it.<br><br><u>Scheme:</u><ul><li>Standard - key is unchanged after each round</li><li>Input differential - key is set to the value of the previous unprocessed byte</li><li>Output differential - key is set to the value of the previous processed byte</li><li>Cascade - key is set to the input byte shifted by one</li><li>Rolling - key is set to the value of itself added with the current position in the bytes</li>Rolling cumulative - key is set to the value of itself added with a cumulative addition of the position in the bytes<li></li><li>Rolling cumulative (self) - key is set to the value of itself XOR'd with the previous chunk of bytes (where the chunk size is equal to key size)</li></ul>" ;
2018-08-21 19:07:13 +01:00
this . infoURL = "https://wikipedia.org/wiki/XOR" ;
2019-07-29 17:09:46 +01:00
this . inputType = "ArrayBuffer" ;
2018-05-23 18:59:57 +01:00
this . outputType = "byteArray" ;
this . args = [
{
"name" : "Key" ,
"type" : "toggleString" ,
"value" : "" ,
2018-11-09 15:25:16 +00:00
"toggleValues" : BITWISE _OP _DELIMS
2018-05-23 18:59:57 +01:00
} ,
{
"name" : "Scheme" ,
"type" : "option" ,
2023-03-30 23:51:19 -07:00
"value" : [ "Standard" , "Input differential" , "Output differential" , "Cascade" , "Rolling" , "Rolling cumulative" , "Rolling cumulative (self)" ]
2018-05-23 18:59:57 +01:00
} ,
{
"name" : "Null preserving" ,
"type" : "boolean" ,
"value" : false
}
] ;
}
/ * *
2019-07-29 17:09:46 +01:00
* @ param { ArrayBuffer } input
2018-05-23 18:59:57 +01:00
* @ param { Object [ ] } args
* @ returns { byteArray }
* /
run ( input , args ) {
2019-07-29 17:09:46 +01:00
input = new Uint8Array ( input ) ;
2018-05-23 18:59:57 +01:00
const key = Utils . convertToByteArray ( args [ 0 ] . string || "" , args [ 0 ] . option ) ,
[ , scheme , nullPreserving ] = args ;
2023-03-30 23:51:19 -07:00
if ( scheme . startswith ( "Rolling" ) && key . length ) {
const inputChunks = Utils . chunked ( input , key . length ) ;
let runningIndex = 0 ;
let runningKey = key ;
let xorred = null ;
return inputChunks . reduce ( ( result , current , index ) => {
runningIndex += index ;
switch ( scheme ) {
case "Rolling" : // key = key + index
return result . concat ( bitOp ( current , key . map ( x => add ( x , index ) ) , xor , nullPreserving , scheme ) ) ;
case "Rolling cumulative" : // key = key + index + previous
return result . concat ( bitOp ( current , key . map ( x => add ( x , runningIndex ) ) , xor , nullPreserving , scheme ) ) ;
case "Rolling cumulative (self)" : // key = key XOR previous chunk
// Xor this chunk
xorred = bitOp ( current , runningKey , xor , nullPreserving , scheme ) ) ;
// Update the running key for next part of loop
runningKey = bitOp ( runningKey , current , xor , nullPreserving , scheme ) ) ;
// Return the result with the newest xor'd chunk
return result . concat ( xorred ) ;
}
} , Utils . strToByteArray ( "" ) ) ;
}
2018-05-23 18:59:57 +01:00
return bitOp ( input , key , xor , nullPreserving , scheme ) ;
}
/ * *
* Highlight XOR
*
* @ param { Object [ ] } pos
* @ param { number } pos [ ] . start
* @ param { number } pos [ ] . end
* @ param { Object [ ] } args
* @ returns { Object [ ] } pos
* /
highlight ( pos , args ) {
return pos ;
}
/ * *
* Highlight XOR in reverse
*
* @ param { Object [ ] } pos
* @ param { number } pos [ ] . start
* @ param { number } pos [ ] . end
* @ param { Object [ ] } args
* @ returns { Object [ ] } pos
* /
highlightReverse ( pos , args ) {
return pos ;
}
}
export default XOR ;