This commit is contained in:
Ryan Chernoff 2025-05-16 11:18:15 -04:00 committed by GitHub
commit 50db810c6c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 45 additions and 7 deletions

View file

@ -327,6 +327,8 @@ class Utils {
*
* @param {string} str
* @param {string} type - One of "Binary", "Hex", "Decimal", "Base64", "UTF8" or "Latin1"
* @param {string} [delim="Auto"] - (Hex only) Delimiter used to split the input string. Set to "Auto" by default.
* @param {boolean} [throwError=false] - (Hex only) Whether to throw an error on invalid input. Defaults to false.
* @returns {byteArray}
*
* @example
@ -339,12 +341,12 @@ class Utils {
* // returns [208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130]
* Utils.convertToByteArray("0JfQtNGA0LDQstGB0YLQstGD0LnRgtC1", "base64");
*/
static convertToByteArray(str, type) {
static convertToByteArray(str, type, delim = "Auto", throwError = false) {
switch (type.toLowerCase()) {
case "binary":
return fromBinary(str);
case "hex":
return fromHex(str);
return fromHex(str, delim, 2, throwError);
case "decimal":
return fromDecimal(str);
case "base64":

View file

@ -91,6 +91,7 @@ export function toHexFast(data) {
* @param {string} data
* @param {string} [delim]
* @param {number} [byteLen=2]
* @param {boolean} [throwError=false]
* @returns {byteArray}
*
* @example
@ -100,7 +101,7 @@ export function toHexFast(data) {
* // returns [10,20,30]
* fromHex("0a:14:1e", "Colon");
*/
export function fromHex(data, delim="Auto", byteLen=2) {
export function fromHex(data, delim="Auto", byteLen=2, throwError=false) {
if (byteLen < 1 || Math.round(byteLen) !== byteLen)
throw new OperationError("Byte length must be a positive integer");
@ -114,7 +115,11 @@ export function fromHex(data, delim="Auto", byteLen=2) {
const output = [];
for (let i = 0; i < data.length; i++) {
for (let j = 0; j < data[i].length; j += byteLen) {
output.push(parseInt(data[i].substr(j, byteLen), 16));
const chunk = data[i].substr(j, byteLen);
if (throwError && /[^a-f\d]/i.test(chunk)) {
throw new OperationError(`Invalid hex character in chunk "${chunk}"`);
}
output.push(parseInt(chunk, 16));
}
}
return output;

View file

@ -5,6 +5,7 @@
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils.mjs";
import { bitOp, xor, BITWISE_OP_DELIMS } from "../lib/BitwiseOp.mjs";
@ -41,6 +42,11 @@ class XOR extends Operation {
"name": "Null preserving",
"type": "boolean",
"value": false
},
{
"name": "Filter Key",
"type": "boolean",
"value": true
}
];
}
@ -52,10 +58,14 @@ class XOR extends Operation {
*/
run(input, args) {
input = new Uint8Array(input);
const key = Utils.convertToByteArray(args[0].string || "", args[0].option),
[, scheme, nullPreserving] = args;
try {
const key = Utils.convertToByteArray(args[0].string || "", args[0].option, args[3] ? "Auto" : "None", true),
[, scheme, nullPreserving] = args;
return bitOp(input, key, xor, nullPreserving, scheme);
return bitOp(input, key, xor, nullPreserving, scheme);
} catch (error) {
throw new OperationError("Invalid Characters in key");
}
}
/**

View file

@ -989,6 +989,27 @@ smothering ampersand abreast`;
"QV\u0010\u0004UDWQ");
}),
it("XOR: should throw 'Invalid Characters in key' error when key contains invalid characters", () => {
const invalidKeys = [
{ string: "zz 00 11", option: "Hex" },
{ string: "4~ 00 11", option: "Hex" }
];
invalidKeys.forEach(invalidKey => {
assert.throws(() => {
chef.XOR("fe023da5", { key: invalidKey, filterKey: false });
}, /Invalid Characters in key/);
});
}),
it("XOR: should not throw 'Invalid Characters in key' error when key contains only valid characters", () => {
assert.strictEqual(chef.XOR("fe023da5", {
key: "736f6d65",
filterKey: false
}).toString(),
"\u0015\n]W@\u000b\fP");
}),
it("XPath expression", () => {
assert.strictEqual(
chef.XPathExpression("<contact-info><company>abc</company></contact-info>", {xPath: "contact-info/company"}).toString(),