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-31 00:11:22 -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 = [
{
2023-03-31 00:11:22 -07:00
name : "Key" ,
type : "toggleString" ,
value : "" ,
toggleValues : BITWISE _OP _DELIMS ,
2018-05-23 18:59:57 +01:00
} ,
{
2023-03-31 00:11:22 -07:00
name : "Scheme" ,
type : "option" ,
value : [
"Standard" ,
"Input differential" ,
"Output differential" ,
"Cascade" ,
"Rolling" ,
"Rolling cumulative" ,
"Rolling cumulative (self)" ,
] ,
2018-05-23 18:59:57 +01:00
} ,
{
2023-03-31 00:11:22 -07:00
name : "Null preserving" ,
type : "boolean" ,
value : false ,
} ,
2018-05-23 18:59:57 +01:00
] ;
}
/ * *
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 ) ;
2023-03-31 00:11:22 -07:00
const key = Utils . convertToByteArray (
args [ 0 ] . string || "" ,
args [ 0 ] . option
) ,
2018-05-23 18:59:57 +01:00
[ , scheme , nullPreserving ] = args ;
2023-03-31 00:11:22 -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 ) {
// key = key + index
case "Rolling" :
return result . concat (
bitOp (
current ,
key . map ( ( x ) => add ( x , index ) ) ,
xor ,
nullPreserving ,
scheme
)
) ;
// key = key + index + previous
case "Rolling cumulative" :
return result . concat (
bitOp (
current ,
key . map ( ( x ) => add ( x , runningIndex ) ) ,
xor ,
nullPreserving ,
scheme
)
) ;
2023-03-30 23:51:19 -07:00
2023-03-31 00:11:22 -07:00
// key = key XOR previous chunk
case "Rolling cumulative (self)" :
// Xor this chunk
xorred = bitOp (
current ,
runningKey ,
xor ,
nullPreserving ,
scheme
) ;
2023-03-30 23:51:19 -07:00
2023-03-31 00:11:22 -07:00
// 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 ( "" ) ) ; // Start our reduction with an empty byte array
}
2023-03-30 23:51:19 -07:00
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 ;