From 30349dbcb90156b98365462dcd93b6dabb540b9d Mon Sep 17 00:00:00 2001 From: Oshawk Date: Mon, 21 Oct 2019 20:44:57 +0100 Subject: [PATCH 01/15] Add operation Added 'Drop nth bytes' operation. --- src/core/config/Categories.json | 3 +- src/core/operations/DropNthBytes.mjs | 79 ++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 src/core/operations/DropNthBytes.mjs diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index db2ab3a6..9cfeb7fe 100755 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -238,7 +238,8 @@ "Escape string", "Unescape string", "Pseudo-Random Number Generator", - "Sleep" + "Sleep", + "Drop nth bytes" ] }, { diff --git a/src/core/operations/DropNthBytes.mjs b/src/core/operations/DropNthBytes.mjs new file mode 100644 index 00000000..e6bac1cd --- /dev/null +++ b/src/core/operations/DropNthBytes.mjs @@ -0,0 +1,79 @@ +/** + * @author Oshawk [oshawk@protonmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Drop nth bytes operation + */ +class DropNthBytes extends Operation { + + /** + * DropNthBytes constructor + */ + constructor() { + super(); + + this.name = "Drop nth bytes"; + this.module = "Default"; + this.description = "Drops every nth byte starting with a given byte."; + this.infoURL = ""; + this.inputType = "byteArray"; + this.outputType = "byteArray"; + this.args = [ + { + name: "Drop every", + type: "number", + value: 4 + }, + { + name: "Starting at", + type: "number", + value: 0 + }, + { + name: "Apply to each line", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const n = args[0]; + const start = args[1]; + const eachLine = args[2]; + + if (parseInt(n, 10) !== n || n <= 0) { + throw new OperationError("'Drop every' must be a positive integer."); + } + if (parseInt(start, 10) !== start || start < 0) { + throw new OperationError("'Starting at' must be a positive or zero integer."); + } + + let offset = 0; + const output = []; + for (let i = 0; i < input.length; i++) { + if (eachLine && input[i] === 0x0a) { + output.push(0x0a); + offset = i + 1; + } else if (i - offset < start || (i - (start + offset)) % n !== 0) { + output.push(input[i]); + } + } + + return output; + } + +} + +export default DropNthBytes; From b125f82784274b3d68eb0a1e2777c63bbf68f205 Mon Sep 17 00:00:00 2001 From: Oshawk Date: Mon, 21 Oct 2019 20:59:04 +0100 Subject: [PATCH 02/15] Add tests Added tests for 'Drop nth bytes' operation. --- tests/operations/index.mjs | 1 + tests/operations/tests/DropNthBytes.mjs | 123 ++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 tests/operations/tests/DropNthBytes.mjs diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs index d64a7737..046a0b79 100644 --- a/tests/operations/index.mjs +++ b/tests/operations/index.mjs @@ -91,6 +91,7 @@ import "./tests/Protobuf.mjs"; import "./tests/ParseSSHHostKey.mjs"; import "./tests/DefangIP.mjs"; import "./tests/ParseUDP.mjs"; +import "./tests/DropNthBytes.mjs"; // Cannot test operations that use the File type yet // import "./tests/SplitColourChannels.mjs"; diff --git a/tests/operations/tests/DropNthBytes.mjs b/tests/operations/tests/DropNthBytes.mjs new file mode 100644 index 00000000..00d4e0ab --- /dev/null +++ b/tests/operations/tests/DropNthBytes.mjs @@ -0,0 +1,123 @@ +/** + * @author Oshawk [oshawk@protonmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + */ + +import TestRegister from "../../lib/TestRegister.mjs"; + +/** + * Drop nth bytes tests + */ +TestRegister.addTests([ + { + name: "Drop nth bytes: Nothing", + input: "", + expectedOutput: "", + recipeConfig: [ + { + op: "Drop nth bytes", + args: [4, 0, false], + }, + ], + }, + { + name: "Drop nth bytes: Nothing (apply to each line)", + input: "", + expectedOutput: "", + recipeConfig: [ + { + op: "Drop nth bytes", + args: [4, 0, true], + }, + ], + }, + { + name: "Drop nth bytes: Basic single line", + input: "0123456789", + expectedOutput: "1235679", + recipeConfig: [ + { + op: "Drop nth bytes", + args: [4, 0, false], + }, + ], + }, + { + name: "Drop nth bytes: Basic single line (apply to each line)", + input: "0123456789", + expectedOutput: "1235679", + recipeConfig: [ + { + op: "Drop nth bytes", + args: [4, 0, true], + }, + ], + }, + { + name: "Drop nth bytes: Complex single line", + input: "0123456789", + expectedOutput: "01234678", + recipeConfig: [ + { + op: "Drop nth bytes", + args: [4, 5, false], + }, + ], + }, + { + name: "Drop nth bytes: Complex single line (apply to each line)", + input: "0123456789", + expectedOutput: "01234678", + recipeConfig: [ + { + op: "Drop nth bytes", + args: [4, 5, true], + }, + ], + }, + { + name: "Drop nth bytes: Basic multi line", + input: "01234\n56789", + expectedOutput: "123\n5689", + recipeConfig: [ + { + op: "Drop nth bytes", + args: [4, 0, false], + }, + ], + }, + { + name: "Drop nth bytes: Basic multi line (apply to each line)", + input: "01234\n56789", + expectedOutput: "123\n678", + recipeConfig: [ + { + op: "Drop nth bytes", + args: [4, 0, true], + }, + ], + }, + { + name: "Drop nth bytes: Complex multi line", + input: "01234\n56789", + expectedOutput: "012345679", + recipeConfig: [ + { + op: "Drop nth bytes", + args: [4, 5, false], + }, + ], + }, + { + name: "Drop nth bytes: Complex multi line (apply to each line)", + input: "012345\n6789ab", + expectedOutput: "01234\n6789a", + recipeConfig: [ + { + op: "Drop nth bytes", + args: [4, 5, true], + }, + ], + } +]); From 3ca4c2fd453f9698b93f762b98b2117c141297b9 Mon Sep 17 00:00:00 2001 From: jb30795 Date: Thu, 4 Apr 2024 15:54:43 +0100 Subject: [PATCH 03/15] Initial commit for new IPv6 Transition operation --- src/core/config/Categories.json | 1 + .../operations/IPv6TransitionAddresses.mjs | 147 ++++++++++++++++++ tests/operations/tests/IPv6Transition.mjs | 43 +++++ 3 files changed, 191 insertions(+) create mode 100644 src/core/operations/IPv6TransitionAddresses.mjs create mode 100644 tests/operations/tests/IPv6Transition.mjs diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index e483c747..0c7442d1 100644 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -224,6 +224,7 @@ "Parse User Agent", "Parse IP range", "Parse IPv6 address", + "IPv6 Transition Addresses", "Parse IPv4 header", "Parse TCP", "Parse UDP", diff --git a/src/core/operations/IPv6TransitionAddresses.mjs b/src/core/operations/IPv6TransitionAddresses.mjs new file mode 100644 index 00000000..becafa71 --- /dev/null +++ b/src/core/operations/IPv6TransitionAddresses.mjs @@ -0,0 +1,147 @@ +/** + * @author jb30795 [jb30795@proton.me] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; + +/** + * IPv6 Transition Addresses operation + */ +class IPv6TransitionAddresses extends Operation { + + /** + * IPv6TransitionAddresses constructor + */ + constructor() { + super(); + + this.name = "IPv6 Transition Addresses"; + this.module = "Default"; + this.description = "Converts IPv4 addresses to their IPv6 Transition addresses. IPv6 Transition addresses can also be converted back into their original IPv4 address. MAC addresses can also be converted into the EUI-64 format, this can them be appended to your IPv6 /64 range to obtain a full /128 address.

Transition technologies enable translation between IPv4 and IPv6 addresses or tunneling to allow traffic to pass through the incompatible network, allowing the two standards to coexist."; + this.infoURL = "https://wikipedia.org/wiki/IPv6_transition_mechanism"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const XOR = {"0": "2", "1": "3", "2": "0", "3": "1", "4": "6", "5": "7", "6": "4", "7": "5", "8": "A", "9": "B", "A": "8", "B": "9", "C": "E", "D": "F", "E": "C", "F": "D"}; + + /** + * Function to convert to hex + */ + function hexify(octet) { + return Number(octet).toString(16).padStart(2, "0"); + } + + /** + * Function to convert Hex to Int + */ + function intify(hex) { + return parseInt(hex, 16); + } + + /** + * Function converts IPv4 to IPv6 Transtion address + */ + function ipTransition(input) { + let output = ""; + const HEXIP = input.split("."); + + /** + * 6to4 + */ + output += "6to4: " + "2002:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "::/48\n"; + + /** + * Mapped + */ + output += "IPv4 Mapped: " + "::ffff:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; + + /** + * Translated + */ + output += "IPv4 Translated: " + "::ffff:0:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; + + /** + * Nat64 + */ + output += "Nat 64: " + "64:ff9b::" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; + + + return output; + } + + /** + * Convert MAC to EUI-64 + */ + function macTransition(input) { + let output = ""; + const MACPARTS = input.split(":"); + output += "EUI-64 Interface ID: "; + const MAC = MACPARTS[0] + MACPARTS[1] + ":" + MACPARTS[2] + "ff:fe" + MACPARTS[3] + ":" + MACPARTS[4] + MACPARTS[5]; + output += MAC.slice(0, 1) + XOR[MAC.slice(1, 2).toUpperCase()].toLowerCase() + MAC.slice(2); + + return output; + } + + + /** + * Convert IPv6 address to its original IPv4 or MAC address + */ + function unTransition(input) { + let output = ""; + let hextets = ""; + + /** + * 6to4 + */ + if (input.startsWith("2002:")) { + output += "IPv4: " + String(intify(input.slice(5, 7))) + "." + String(intify(input.slice(7, 9)))+ "." + String(intify(input.slice(10, 12)))+ "." + String(intify(input.slice(12, 14))); + } else if (input.startsWith("::ffff:") || input.startsWith("0000:0000:0000:0000:0000:ffff:") || input.startsWith("::ffff:0000:") || input.startsWith("0000:0000:0000:0000:ffff:0000:") || input.startsWith("64:ff9b::") || input.startsWith("0064:ff9b:0000:0000:0000:0000:")) { + /** + * Mapped/Translated/Nat64 + */ + hextets = /:([0-9a-z]{1,4}):[0-9a-z]{1,4}$/.exec(input)[1].padStart(4, "0") + /:([0-9a-z]{1,4})$/.exec(input)[1].padStart(4, "0"); + output += "IPv4: " + intify(hextets.slice(-8, -7) + hextets.slice(-7, -6)) + "." +intify(hextets.slice(-6, -5) + hextets.slice(-5, -4)) + "." +intify(hextets.slice(-4, -3) + hextets.slice(-3, -2)) + "." +intify(hextets.slice(-2, -1) + hextets.slice(-1,)); + } else if (input.slice(-12, -7).toUpperCase() === "FF:FE") { + /** + * EUI-64 + */ + output += "Mac Address: "; + const MAC = (input.slice(-19, -17) + ":" + input.slice(-17, -15) + ":" + input.slice(-14, -12) + ":" + input.slice(-7, -5) + ":" + input.slice(-4, -2) + ":" + input.slice(-2,)).toUpperCase(); + output += MAC.slice(0, 1) + XOR[MAC.slice(1, 2)] + MAC.slice(2); + } + + return output; + } + + + /** + * Main + */ + let output = ""; + if (/^[0-9]{1,3}(?:\.[0-9]{1,3}){3}$/.test(input)) { + output = ipTransition(input); + } else if (/^([0-9A-F]{2}:){5}[0-9A-F]{2}$/.test(input.toUpperCase())) { + output = macTransition(input.toLowerCase()); + } else if (/^((?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/.test(input)) { + output = unTransition(input); + } else { + output = "Enter a compressed or expanded IPv6 address, IPv4 address or MAC Address."; + } + + + return output; + } + +} + +export default IPv6TransitionAddresses; diff --git a/tests/operations/tests/IPv6Transition.mjs b/tests/operations/tests/IPv6Transition.mjs new file mode 100644 index 00000000..4e5c0e63 --- /dev/null +++ b/tests/operations/tests/IPv6Transition.mjs @@ -0,0 +1,43 @@ +/** + * IPv6Transition tests. + * + * @author jb30795 + * + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + */ +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + name: "IPv6 Transition: IPv4 to IPv6", + input: "198.51.100.7", + expectedOutput: "6to4: 2002:c633:6407::/48\nIPv4 Mapped: ::ffff:c633:6407\nIPv4 Translated: ::ffff:0:c633:6407\nNat 64: 64:ff9b::c633:6407", + recipeConfig: [ + { + op: "IPv6 Transition Addresses", + args: [], + }, + ], + }, { + name: "IPv6 Transition: IPv6 to IPv4", + input: "64:ff9b::c633:6407", + expectedOutput: "IPv4: 198.51.100.7", + recipeConfig: [ + { + op: "IPv6 Transition Addresses", + args: [], + }, + ], + }, { + name: "IPv6 Transition: MAC to EUI-64", + input: "a1:b2:c3:d4:e5:f6", + expectedOutput: "EUI-64 Interface ID: a3b2:c3ff:fed4:e5f6", + recipeConfig: [ + { + op: "IPv6 Transition Addresses", + args: [], + }, + ], + }, +]); From 036f80d7349f024c7aaffcda235afe39e2be9de2 Mon Sep 17 00:00:00 2001 From: jb30795 <> Date: Thu, 4 Apr 2024 17:00:14 +0100 Subject: [PATCH 04/15] indentation --- src/core/config/Categories.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index 0c7442d1..45622ded 100644 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -224,7 +224,7 @@ "Parse User Agent", "Parse IP range", "Parse IPv6 address", - "IPv6 Transition Addresses", + "IPv6 Transition Addresses", "Parse IPv4 header", "Parse TCP", "Parse UDP", From b090ce0428f55ef4db0abf6c354acf1261daf1a9 Mon Sep 17 00:00:00 2001 From: jb30795 <> Date: Wed, 7 Aug 2024 17:06:15 +0100 Subject: [PATCH 05/15] Update to accept multiple inputs --- .../operations/IPv6TransitionAddresses.mjs | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/core/operations/IPv6TransitionAddresses.mjs b/src/core/operations/IPv6TransitionAddresses.mjs index becafa71..a574b8cd 100644 --- a/src/core/operations/IPv6TransitionAddresses.mjs +++ b/src/core/operations/IPv6TransitionAddresses.mjs @@ -23,10 +23,16 @@ class IPv6TransitionAddresses extends Operation { this.infoURL = "https://wikipedia.org/wiki/IPv6_transition_mechanism"; this.inputType = "string"; this.outputType = "string"; - this.args = []; + this.args = [ + { + "name": "Ignore ranges", + "type": "boolean", + "value": true + } + ]; } - /** + /** * @param {string} input * @param {Object[]} args * @returns {string} @@ -128,17 +134,19 @@ class IPv6TransitionAddresses extends Operation { * Main */ let output = ""; - if (/^[0-9]{1,3}(?:\.[0-9]{1,3}){3}$/.test(input)) { - output = ipTransition(input); - } else if (/^([0-9A-F]{2}:){5}[0-9A-F]{2}$/.test(input.toUpperCase())) { - output = macTransition(input.toLowerCase()); - } else if (/^((?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/.test(input)) { - output = unTransition(input); - } else { - output = "Enter a compressed or expanded IPv6 address, IPv4 address or MAC Address."; + const inputs = input.split("\n"); + for (let input = 0; input < inputs.length; input++){ + if (/^[0-9]{1,3}(?:\.[0-9]{1,3}){3}$/.test(inputs[input])) { + output += ipTransition(inputs[input]); + } else if (/^([0-9A-F]{2}:){5}[0-9A-F]{2}$/.test(inputs[input].toUpperCase())) { + output += macTransition(input.toLowerCase()); + } else if (/^((?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/.test(inputs[input])) { + output += unTransition(inputs[input]); + } else { + output = "Enter a compressed or expanded IPv6 address, IPv4 address or MAC Address."; + } } - return output; } From 5e763b86dc42e26cf3a7baedacf2abc036be8ccf Mon Sep 17 00:00:00 2001 From: jb30795 <> Date: Wed, 7 Aug 2024 18:17:00 +0100 Subject: [PATCH 06/15] Option to remove headers and ignore blank input rows --- .../operations/IPv6TransitionAddresses.mjs | 52 +++++++++++++++---- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/src/core/operations/IPv6TransitionAddresses.mjs b/src/core/operations/IPv6TransitionAddresses.mjs index a574b8cd..c5290735 100644 --- a/src/core/operations/IPv6TransitionAddresses.mjs +++ b/src/core/operations/IPv6TransitionAddresses.mjs @@ -28,7 +28,12 @@ class IPv6TransitionAddresses extends Operation { "name": "Ignore ranges", "type": "boolean", "value": true - } + }, + { + "name": "Remove headers", + "type": "boolean", + "value": false + } ]; } @@ -39,6 +44,7 @@ class IPv6TransitionAddresses extends Operation { */ run(input, args) { const XOR = {"0": "2", "1": "3", "2": "0", "3": "1", "4": "6", "5": "7", "6": "4", "7": "5", "8": "A", "9": "B", "A": "8", "B": "9", "C": "E", "D": "F", "E": "C", "F": "D"}; + const [ignoreRanges, removeHeaders] = args; /** * Function to convert to hex @@ -64,22 +70,34 @@ class IPv6TransitionAddresses extends Operation { /** * 6to4 */ - output += "6to4: " + "2002:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "::/48\n"; + if (!args[1]){ + output += "6to4: "; + } + output += "2002:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "::/48\n"; /** * Mapped */ - output += "IPv4 Mapped: " + "::ffff:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; + if (!args[1]){ + output += "IPv4 Mapped: "; + } + output += "::ffff:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; /** * Translated */ - output += "IPv4 Translated: " + "::ffff:0:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; + if (!args[1]){ + output += "IPv4 Translated: "; + } + output += "::ffff:0:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; /** * Nat64 */ - output += "Nat 64: " + "64:ff9b::" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; + if (!args[1]){ + output += "Nat 64: "; + } + output += "64:ff9b::" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; return output; @@ -91,7 +109,9 @@ class IPv6TransitionAddresses extends Operation { function macTransition(input) { let output = ""; const MACPARTS = input.split(":"); - output += "EUI-64 Interface ID: "; + if (!args[1]){ + output += "EUI-64 Interface ID: "; + } const MAC = MACPARTS[0] + MACPARTS[1] + ":" + MACPARTS[2] + "ff:fe" + MACPARTS[3] + ":" + MACPARTS[4] + MACPARTS[5]; output += MAC.slice(0, 1) + XOR[MAC.slice(1, 2).toUpperCase()].toLowerCase() + MAC.slice(2); @@ -110,20 +130,28 @@ class IPv6TransitionAddresses extends Operation { * 6to4 */ if (input.startsWith("2002:")) { - output += "IPv4: " + String(intify(input.slice(5, 7))) + "." + String(intify(input.slice(7, 9)))+ "." + String(intify(input.slice(10, 12)))+ "." + String(intify(input.slice(12, 14))); + if (!args[1]){ + output += "IPv4: "; + } + output += String(intify(input.slice(5, 7))) + "." + String(intify(input.slice(7, 9)))+ "." + String(intify(input.slice(10, 12)))+ "." + String(intify(input.slice(12, 14))) + "\n"; } else if (input.startsWith("::ffff:") || input.startsWith("0000:0000:0000:0000:0000:ffff:") || input.startsWith("::ffff:0000:") || input.startsWith("0000:0000:0000:0000:ffff:0000:") || input.startsWith("64:ff9b::") || input.startsWith("0064:ff9b:0000:0000:0000:0000:")) { /** * Mapped/Translated/Nat64 */ hextets = /:([0-9a-z]{1,4}):[0-9a-z]{1,4}$/.exec(input)[1].padStart(4, "0") + /:([0-9a-z]{1,4})$/.exec(input)[1].padStart(4, "0"); - output += "IPv4: " + intify(hextets.slice(-8, -7) + hextets.slice(-7, -6)) + "." +intify(hextets.slice(-6, -5) + hextets.slice(-5, -4)) + "." +intify(hextets.slice(-4, -3) + hextets.slice(-3, -2)) + "." +intify(hextets.slice(-2, -1) + hextets.slice(-1,)); + if (!args[1]){ + output += "IPv4: "; + } + output += intify(hextets.slice(-8, -7) + hextets.slice(-7, -6)) + "." +intify(hextets.slice(-6, -5) + hextets.slice(-5, -4)) + "." +intify(hextets.slice(-4, -3) + hextets.slice(-3, -2)) + "." +intify(hextets.slice(-2, -1) + hextets.slice(-1,)) + "\n"; } else if (input.slice(-12, -7).toUpperCase() === "FF:FE") { /** * EUI-64 */ - output += "Mac Address: "; + if (!args[1]){ + output += "Mac Address: "; + } const MAC = (input.slice(-19, -17) + ":" + input.slice(-17, -15) + ":" + input.slice(-14, -12) + ":" + input.slice(-7, -5) + ":" + input.slice(-4, -2) + ":" + input.slice(-2,)).toUpperCase(); - output += MAC.slice(0, 1) + XOR[MAC.slice(1, 2)] + MAC.slice(2); + output += MAC.slice(0, 1) + XOR[MAC.slice(1, 2)] + MAC.slice(2) + "\n"; } return output; @@ -134,7 +162,9 @@ class IPv6TransitionAddresses extends Operation { * Main */ let output = ""; - const inputs = input.split("\n"); + let inputs = input.split("\n"); + //Remove blank rows + inputs = inputs.filter(Boolean); for (let input = 0; input < inputs.length; input++){ if (/^[0-9]{1,3}(?:\.[0-9]{1,3}){3}$/.test(inputs[input])) { output += ipTransition(inputs[input]); From 51a07a27dba4fe724015124fa4d86a3ee75020a2 Mon Sep 17 00:00:00 2001 From: jb30795 <> Date: Wed, 7 Aug 2024 18:49:58 +0100 Subject: [PATCH 07/15] Formatting updates --- .../operations/IPv6TransitionAddresses.mjs | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/core/operations/IPv6TransitionAddresses.mjs b/src/core/operations/IPv6TransitionAddresses.mjs index c5290735..d6eb903d 100644 --- a/src/core/operations/IPv6TransitionAddresses.mjs +++ b/src/core/operations/IPv6TransitionAddresses.mjs @@ -31,20 +31,19 @@ class IPv6TransitionAddresses extends Operation { }, { "name": "Remove headers", - "type": "boolean", - "value": false + "type": "boolean", + "value": false } - ]; + ]; } - /** + /** * @param {string} input * @param {Object[]} args * @returns {string} */ run(input, args) { const XOR = {"0": "2", "1": "3", "2": "0", "3": "1", "4": "6", "5": "7", "6": "4", "7": "5", "8": "A", "9": "B", "A": "8", "B": "9", "C": "E", "D": "F", "E": "C", "F": "D"}; - const [ignoreRanges, removeHeaders] = args; /** * Function to convert to hex @@ -70,7 +69,7 @@ class IPv6TransitionAddresses extends Operation { /** * 6to4 */ - if (!args[1]){ + if (!args[1]) { output += "6to4: "; } output += "2002:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "::/48\n"; @@ -78,7 +77,7 @@ class IPv6TransitionAddresses extends Operation { /** * Mapped */ - if (!args[1]){ + if (!args[1]) { output += "IPv4 Mapped: "; } output += "::ffff:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; @@ -86,7 +85,7 @@ class IPv6TransitionAddresses extends Operation { /** * Translated */ - if (!args[1]){ + if (!args[1]) { output += "IPv4 Translated: "; } output += "::ffff:0:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; @@ -94,7 +93,7 @@ class IPv6TransitionAddresses extends Operation { /** * Nat64 */ - if (!args[1]){ + if (!args[1]) { output += "Nat 64: "; } output += "64:ff9b::" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; @@ -109,7 +108,7 @@ class IPv6TransitionAddresses extends Operation { function macTransition(input) { let output = ""; const MACPARTS = input.split(":"); - if (!args[1]){ + if (!args[1]) { output += "EUI-64 Interface ID: "; } const MAC = MACPARTS[0] + MACPARTS[1] + ":" + MACPARTS[2] + "ff:fe" + MACPARTS[3] + ":" + MACPARTS[4] + MACPARTS[5]; @@ -130,7 +129,7 @@ class IPv6TransitionAddresses extends Operation { * 6to4 */ if (input.startsWith("2002:")) { - if (!args[1]){ + if (!args[1]) { output += "IPv4: "; } output += String(intify(input.slice(5, 7))) + "." + String(intify(input.slice(7, 9)))+ "." + String(intify(input.slice(10, 12)))+ "." + String(intify(input.slice(12, 14))) + "\n"; @@ -139,7 +138,7 @@ class IPv6TransitionAddresses extends Operation { * Mapped/Translated/Nat64 */ hextets = /:([0-9a-z]{1,4}):[0-9a-z]{1,4}$/.exec(input)[1].padStart(4, "0") + /:([0-9a-z]{1,4})$/.exec(input)[1].padStart(4, "0"); - if (!args[1]){ + if (!args[1]) { output += "IPv4: "; } output += intify(hextets.slice(-8, -7) + hextets.slice(-7, -6)) + "." +intify(hextets.slice(-6, -5) + hextets.slice(-5, -4)) + "." +intify(hextets.slice(-4, -3) + hextets.slice(-3, -2)) + "." +intify(hextets.slice(-2, -1) + hextets.slice(-1,)) + "\n"; @@ -147,7 +146,7 @@ class IPv6TransitionAddresses extends Operation { /** * EUI-64 */ - if (!args[1]){ + if (!args[1]) { output += "Mac Address: "; } const MAC = (input.slice(-19, -17) + ":" + input.slice(-17, -15) + ":" + input.slice(-14, -12) + ":" + input.slice(-7, -5) + ":" + input.slice(-4, -2) + ":" + input.slice(-2,)).toUpperCase(); @@ -162,10 +161,10 @@ class IPv6TransitionAddresses extends Operation { * Main */ let output = ""; - let inputs = input.split("\n"); - //Remove blank rows + let inputs = input.split("\n"); + // Remove blank rows inputs = inputs.filter(Boolean); - for (let input = 0; input < inputs.length; input++){ + for (let input = 0; input < inputs.length; input++) { if (/^[0-9]{1,3}(?:\.[0-9]{1,3}){3}$/.test(inputs[input])) { output += ipTransition(inputs[input]); } else if (/^([0-9A-F]{2}:){5}[0-9A-F]{2}$/.test(inputs[input].toUpperCase())) { From 9169254fff375b7393210e9ce5eb104a38dcbd0e Mon Sep 17 00:00:00 2001 From: jb30795 <> Date: Wed, 7 Aug 2024 19:13:44 +0100 Subject: [PATCH 08/15] minor wording update --- src/core/operations/IPv6TransitionAddresses.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/operations/IPv6TransitionAddresses.mjs b/src/core/operations/IPv6TransitionAddresses.mjs index d6eb903d..bb06e5a7 100644 --- a/src/core/operations/IPv6TransitionAddresses.mjs +++ b/src/core/operations/IPv6TransitionAddresses.mjs @@ -172,7 +172,7 @@ class IPv6TransitionAddresses extends Operation { } else if (/^((?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/.test(inputs[input])) { output += unTransition(inputs[input]); } else { - output = "Enter a compressed or expanded IPv6 address, IPv4 address or MAC Address."; + output = "Enter compressed or expanded IPv6 address, IPv4 address or MAC Address."; } } From 660069865aa0798fd1ddcbefb818433a0a992789 Mon Sep 17 00:00:00 2001 From: jb30795 <> Date: Wed, 7 Aug 2024 21:02:00 +0100 Subject: [PATCH 09/15] Updating description --- src/core/operations/IPv6TransitionAddresses.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/operations/IPv6TransitionAddresses.mjs b/src/core/operations/IPv6TransitionAddresses.mjs index bb06e5a7..cfc81071 100644 --- a/src/core/operations/IPv6TransitionAddresses.mjs +++ b/src/core/operations/IPv6TransitionAddresses.mjs @@ -19,7 +19,7 @@ class IPv6TransitionAddresses extends Operation { this.name = "IPv6 Transition Addresses"; this.module = "Default"; - this.description = "Converts IPv4 addresses to their IPv6 Transition addresses. IPv6 Transition addresses can also be converted back into their original IPv4 address. MAC addresses can also be converted into the EUI-64 format, this can them be appended to your IPv6 /64 range to obtain a full /128 address.

Transition technologies enable translation between IPv4 and IPv6 addresses or tunneling to allow traffic to pass through the incompatible network, allowing the two standards to coexist."; + this.description = "Converts IPv4 addresses to their IPv6 Transition addresses. IPv6 Transition addresses can also be converted back into their original IPv4 address. MAC addresses can also be converted into the EUI-64 format, this can them be appended to your IPv6 /64 range to obtain a full /128 address.

Transition technologies enable translation between IPv4 and IPv6 addresses or tunneling to allow traffic to pass through the incompatible network, allowing the two standards to coexist.

Remove headers to easily copy out results."; this.infoURL = "https://wikipedia.org/wiki/IPv6_transition_mechanism"; this.inputType = "string"; this.outputType = "string"; From 752ce789c21ffa07c8e40c40749e590739f11969 Mon Sep 17 00:00:00 2001 From: jb30795 <> Date: Wed, 7 Aug 2024 21:19:13 +0100 Subject: [PATCH 10/15] Updating tests --- tests/operations/tests/IPv6Transition.mjs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/operations/tests/IPv6Transition.mjs b/tests/operations/tests/IPv6Transition.mjs index 4e5c0e63..c658f0fb 100644 --- a/tests/operations/tests/IPv6Transition.mjs +++ b/tests/operations/tests/IPv6Transition.mjs @@ -16,7 +16,7 @@ TestRegister.addTests([ recipeConfig: [ { op: "IPv6 Transition Addresses", - args: [], + args: [true, false], }, ], }, { @@ -26,7 +26,7 @@ TestRegister.addTests([ recipeConfig: [ { op: "IPv6 Transition Addresses", - args: [], + args: [true, false], }, ], }, { @@ -36,7 +36,7 @@ TestRegister.addTests([ recipeConfig: [ { op: "IPv6 Transition Addresses", - args: [], + args: [true, false], }, ], }, From a616e46b507607716c7e2bd2f934d81a43427da7 Mon Sep 17 00:00:00 2001 From: jb30795 <> Date: Fri, 9 Aug 2024 14:28:50 +0100 Subject: [PATCH 11/15] Handling of /24 ranges --- .../operations/IPv6TransitionAddresses.mjs | 54 +++++++++++++------ 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/src/core/operations/IPv6TransitionAddresses.mjs b/src/core/operations/IPv6TransitionAddresses.mjs index cfc81071..813224bd 100644 --- a/src/core/operations/IPv6TransitionAddresses.mjs +++ b/src/core/operations/IPv6TransitionAddresses.mjs @@ -19,7 +19,7 @@ class IPv6TransitionAddresses extends Operation { this.name = "IPv6 Transition Addresses"; this.module = "Default"; - this.description = "Converts IPv4 addresses to their IPv6 Transition addresses. IPv6 Transition addresses can also be converted back into their original IPv4 address. MAC addresses can also be converted into the EUI-64 format, this can them be appended to your IPv6 /64 range to obtain a full /128 address.

Transition technologies enable translation between IPv4 and IPv6 addresses or tunneling to allow traffic to pass through the incompatible network, allowing the two standards to coexist.

Remove headers to easily copy out results."; + this.description = "Converts IPv4 addresses to their IPv6 Transition addresses. IPv6 Transition addresses can also be converted back into their original IPv4 address. MAC addresses can also be converted into the EUI-64 format, this can them be appended to your IPv6 /64 range to obtain a full /128 address.

Transition technologies enable translation between IPv4 and IPv6 addresses or tunneling to allow traffic to pass through the incompatible network, allowing the two standards to coexist.

Only /24 ranges and currently handled. Remove headers to easily copy out results."; this.infoURL = "https://wikipedia.org/wiki/IPv6_transition_mechanism"; this.inputType = "string"; this.outputType = "string"; @@ -62,7 +62,7 @@ class IPv6TransitionAddresses extends Operation { /** * Function converts IPv4 to IPv6 Transtion address */ - function ipTransition(input) { + function ipTransition(input, range) { let output = ""; const HEXIP = input.split("."); @@ -72,7 +72,12 @@ class IPv6TransitionAddresses extends Operation { if (!args[1]) { output += "6to4: "; } - output += "2002:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "::/48\n"; + output += "2002:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]); + if (range) { + output += "00::/40\n"; + } else { + output += hexify(HEXIP[3]) + "::/48\n"; + } /** * Mapped @@ -80,7 +85,12 @@ class IPv6TransitionAddresses extends Operation { if (!args[1]) { output += "IPv4 Mapped: "; } - output += "::ffff:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; + output += "::ffff:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]); + if (range) { + output += "00/120\n"; + } else { + output += hexify(HEXIP[3]) + "\n"; + } /** * Translated @@ -88,7 +98,12 @@ class IPv6TransitionAddresses extends Operation { if (!args[1]) { output += "IPv4 Translated: "; } - output += "::ffff:0:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; + output += "::ffff:0:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]); + if (range) { + output += "00/120\n"; + } else { + output += hexify(HEXIP[3]) + "\n"; + } /** * Nat64 @@ -96,8 +111,12 @@ class IPv6TransitionAddresses extends Operation { if (!args[1]) { output += "Nat 64: "; } - output += "64:ff9b::" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; - + output += "64:ff9b::" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]); + if (range) { + output += "00/120\n"; + } else { + output += hexify(HEXIP[3]) + "\n"; + } return output; } @@ -165,14 +184,19 @@ class IPv6TransitionAddresses extends Operation { // Remove blank rows inputs = inputs.filter(Boolean); for (let input = 0; input < inputs.length; input++) { - if (/^[0-9]{1,3}(?:\.[0-9]{1,3}){3}$/.test(inputs[input])) { - output += ipTransition(inputs[input]); - } else if (/^([0-9A-F]{2}:){5}[0-9A-F]{2}$/.test(inputs[input].toUpperCase())) { - output += macTransition(input.toLowerCase()); - } else if (/^((?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/.test(inputs[input])) { - output += unTransition(inputs[input]); - } else { - output = "Enter compressed or expanded IPv6 address, IPv4 address or MAC Address."; + // if ignore ranges is checked and input is a range, skip + if ((args[0] && !inputs[input].includes("\/")) || (!args[0])) { + if (/^[0-9]{1,3}(?:\.[0-9]{1,3}){3}$/.test(inputs[input])) { + output += ipTransition(inputs[input], false); + } else if (/\/24$/.test(inputs[input])) { + output += ipTransition(inputs[input], true); + } else if (/^([0-9A-F]{2}:){5}[0-9A-F]{2}$/.test(inputs[input].toUpperCase())) { + output += macTransition(input.toLowerCase()); + } else if (/^((?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/.test(inputs[input])) { + output += unTransition(inputs[input]); + } else { + output = "Enter compressed or expanded IPv6 address, IPv4 address or MAC Address."; + } } } From a80b1568acbbf8d722c667b77381e1810429a387 Mon Sep 17 00:00:00 2001 From: jb30795 <> Date: Fri, 9 Aug 2024 14:32:31 +0100 Subject: [PATCH 12/15] Lint errors --- src/core/operations/IPv6TransitionAddresses.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/operations/IPv6TransitionAddresses.mjs b/src/core/operations/IPv6TransitionAddresses.mjs index 813224bd..7f2f05c5 100644 --- a/src/core/operations/IPv6TransitionAddresses.mjs +++ b/src/core/operations/IPv6TransitionAddresses.mjs @@ -185,10 +185,10 @@ class IPv6TransitionAddresses extends Operation { inputs = inputs.filter(Boolean); for (let input = 0; input < inputs.length; input++) { // if ignore ranges is checked and input is a range, skip - if ((args[0] && !inputs[input].includes("\/")) || (!args[0])) { + if ((args[0] && !inputs[input].includes("/")) || (!args[0])) { if (/^[0-9]{1,3}(?:\.[0-9]{1,3}){3}$/.test(inputs[input])) { output += ipTransition(inputs[input], false); - } else if (/\/24$/.test(inputs[input])) { + } else if (/\/24$/.test(inputs[input])) { output += ipTransition(inputs[input], true); } else if (/^([0-9A-F]{2}:){5}[0-9A-F]{2}$/.test(inputs[input].toUpperCase())) { output += macTransition(input.toLowerCase()); From 1fce8e51125fc416d12713e38d02e51fd2c8b696 Mon Sep 17 00:00:00 2001 From: Francisco Pombal Date: Sun, 15 Sep 2024 22:18:49 +0100 Subject: [PATCH 13/15] fix: Blowfish - ignore IV length in ECB mode Fixes https://github.com/gchq/CyberChef/issues/1895. --- src/core/operations/BlowfishDecrypt.mjs | 4 ++-- src/core/operations/BlowfishEncrypt.mjs | 6 +++--- tests/operations/tests/Crypt.mjs | 20 ++++++++++++++++---- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/core/operations/BlowfishDecrypt.mjs b/src/core/operations/BlowfishDecrypt.mjs index 43d6718a..afb26007 100644 --- a/src/core/operations/BlowfishDecrypt.mjs +++ b/src/core/operations/BlowfishDecrypt.mjs @@ -76,8 +76,8 @@ class BlowfishDecrypt extends Operation { Blowfish's key length needs to be between 4 and 56 bytes (32-448 bits).`); } - if (iv.length !== 8) { - throw new OperationError(`Invalid IV length: ${iv.length} bytes. Expected 8 bytes`); + if (mode !== "ECB" && iv.length !== 8) { + throw new OperationError(`Invalid IV length: ${iv.length} bytes. Expected 8 bytes.`); } input = Utils.convertToByteString(input, inputType); diff --git a/src/core/operations/BlowfishEncrypt.mjs b/src/core/operations/BlowfishEncrypt.mjs index eab3d286..1d5dcf02 100644 --- a/src/core/operations/BlowfishEncrypt.mjs +++ b/src/core/operations/BlowfishEncrypt.mjs @@ -72,12 +72,12 @@ class BlowfishEncrypt extends Operation { if (key.length < 4 || key.length > 56) { throw new OperationError(`Invalid key length: ${key.length} bytes - + Blowfish's key length needs to be between 4 and 56 bytes (32-448 bits).`); } - if (iv.length !== 8) { - throw new OperationError(`Invalid IV length: ${iv.length} bytes. Expected 8 bytes`); + if (mode !== "ECB" && iv.length !== 8) { + throw new OperationError(`Invalid IV length: ${iv.length} bytes. Expected 8 bytes.`); } input = Utils.convertToByteString(input, inputType); diff --git a/tests/operations/tests/Crypt.mjs b/tests/operations/tests/Crypt.mjs index 69123d66..caaf27fc 100644 --- a/tests/operations/tests/Crypt.mjs +++ b/tests/operations/tests/Crypt.mjs @@ -1579,19 +1579,31 @@ DES uses a key length of 8 bytes (64 bits).`, from Crypto.Cipher import Blowfish import binascii - input_data = b"The quick brown fox jumps over the lazy dog." + # Blowfish cipher parameters - key, mode, iv, segment_size, nonce key = binascii.unhexlify("0011223344556677") - iv = binascii.unhexlify("0000000000000000") mode = Blowfish.MODE_CBC + kwargs = {} + iv = binascii.unhexlify("ffeeddccbbaa9988") + if mode in [Blowfish.MODE_CBC, Blowfish.MODE_CFB, Blowfish.MODE_OFB]: + kwargs = {"iv": iv} + if mode == Blowfish.MODE_CFB: + kwargs["segment_size"] = 64 + if mode == Blowfish.MODE_CTR: + nonce = binascii.unhexlify("0000000000000000") + nonce = nonce[:7] + kwargs["nonce"] = nonce + cipher = Blowfish.new(key, mode, **kwargs) + + # Input data and padding + input_data = b"The quick brown fox jumps over the lazy dog." if mode == Blowfish.MODE_ECB or mode == Blowfish.MODE_CBC: padding_len = 8-(len(input_data) & 7) for i in range(padding_len): input_data += bytes([padding_len]) - cipher = Blowfish.new(key, mode) # set iv, nonce, segment_size etc. here + # Encrypted text cipher_text = cipher.encrypt(input_data) - cipher_text = binascii.hexlify(cipher_text).decode("UTF-8") print("Encrypted: {}".format(cipher_text)) From 488c458720bd2c5ab2d2933eab9075a4afbee323 Mon Sep 17 00:00:00 2001 From: jb30795 <> Date: Fri, 20 Sep 2024 10:46:09 +0100 Subject: [PATCH 14/15] updates to operation and addition of more tests --- .../operations/IPv6TransitionAddresses.mjs | 26 ++++++++++--------- tests/operations/tests/IPv6Transition.mjs | 20 ++++++++++++++ 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/core/operations/IPv6TransitionAddresses.mjs b/src/core/operations/IPv6TransitionAddresses.mjs index 7f2f05c5..4af5eb72 100644 --- a/src/core/operations/IPv6TransitionAddresses.mjs +++ b/src/core/operations/IPv6TransitionAddresses.mjs @@ -43,7 +43,7 @@ class IPv6TransitionAddresses extends Operation { * @returns {string} */ run(input, args) { - const XOR = {"0": "2", "1": "3", "2": "0", "3": "1", "4": "6", "5": "7", "6": "4", "7": "5", "8": "A", "9": "B", "A": "8", "B": "9", "C": "E", "D": "F", "E": "C", "F": "D"}; + const XOR = {"0": "2", "1": "3", "2": "0", "3": "1", "4": "6", "5": "7", "6": "4", "7": "5", "8": "a", "9": "b", "a": "8", "b": "9", "c": "e", "d": "f", "e": "c", "f": "d"}; /** * Function to convert to hex @@ -126,12 +126,13 @@ class IPv6TransitionAddresses extends Operation { */ function macTransition(input) { let output = ""; + console.log(input); const MACPARTS = input.split(":"); if (!args[1]) { output += "EUI-64 Interface ID: "; } const MAC = MACPARTS[0] + MACPARTS[1] + ":" + MACPARTS[2] + "ff:fe" + MACPARTS[3] + ":" + MACPARTS[4] + MACPARTS[5]; - output += MAC.slice(0, 1) + XOR[MAC.slice(1, 2).toUpperCase()].toLowerCase() + MAC.slice(2); + output += MAC.slice(0, 1) + XOR[MAC.slice(1, 2)] + MAC.slice(2); return output; } @@ -183,17 +184,18 @@ class IPv6TransitionAddresses extends Operation { let inputs = input.split("\n"); // Remove blank rows inputs = inputs.filter(Boolean); - for (let input = 0; input < inputs.length; input++) { + + for (let i = 0; i < inputs.length; i++) { // if ignore ranges is checked and input is a range, skip - if ((args[0] && !inputs[input].includes("/")) || (!args[0])) { - if (/^[0-9]{1,3}(?:\.[0-9]{1,3}){3}$/.test(inputs[input])) { - output += ipTransition(inputs[input], false); - } else if (/\/24$/.test(inputs[input])) { - output += ipTransition(inputs[input], true); - } else if (/^([0-9A-F]{2}:){5}[0-9A-F]{2}$/.test(inputs[input].toUpperCase())) { - output += macTransition(input.toLowerCase()); - } else if (/^((?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/.test(inputs[input])) { - output += unTransition(inputs[input]); + if ((args[0] && !inputs[i].includes("/")) || (!args[0])) { + if (/^[0-9]{1,3}(?:\.[0-9]{1,3}){3}$/.test(inputs[i])) { + output += ipTransition(inputs[i], false); + } else if (/\/24$/.test(inputs[i])) { + output += ipTransition(inputs[i], true); + } else if (/^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$/.test(inputs[i])) { + output += macTransition(inputs[i]); + } else if (/^((?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/.test(inputs[i])) { + output += unTransition(inputs[i]); } else { output = "Enter compressed or expanded IPv6 address, IPv4 address or MAC Address."; } diff --git a/tests/operations/tests/IPv6Transition.mjs b/tests/operations/tests/IPv6Transition.mjs index c658f0fb..f7558c31 100644 --- a/tests/operations/tests/IPv6Transition.mjs +++ b/tests/operations/tests/IPv6Transition.mjs @@ -19,6 +19,26 @@ TestRegister.addTests([ args: [true, false], }, ], + }, { + name: "IPv6 Transition: IPv4 /24 Range to IPv6", + input: "198.51.100.0/24", + expectedOutput: "6to4: 2002:c633:6400::/40\nIPv4 Mapped: ::ffff:c633:6400/120\nIPv4 Translated: ::ffff:0:c633:6400/120\nNat 64: 64:ff9b::c633:6400/120", + recipeConfig: [ + { + op: "IPv6 Transition Addresses", + args: [false, false], + }, + ], + }, { + name: "IPv6 Transition: IPv4 to IPv6 Remove headers", + input: "198.51.100.7", + expectedOutput: "2002:c633:6407::/48\n::ffff:c633:6407\n::ffff:0:c633:6407\n64:ff9b::c633:6407", + recipeConfig: [ + { + op: "IPv6 Transition Addresses", + args: [true, true], + }, + ], }, { name: "IPv6 Transition: IPv6 to IPv4", input: "64:ff9b::c633:6407", From 9229fe9ac784cce3166208da5d414a942e70d875 Mon Sep 17 00:00:00 2001 From: jb30795 <> Date: Fri, 20 Sep 2024 10:49:13 +0100 Subject: [PATCH 15/15] Remove console.log statement --- src/core/operations/IPv6TransitionAddresses.mjs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/operations/IPv6TransitionAddresses.mjs b/src/core/operations/IPv6TransitionAddresses.mjs index 4af5eb72..80d03fd0 100644 --- a/src/core/operations/IPv6TransitionAddresses.mjs +++ b/src/core/operations/IPv6TransitionAddresses.mjs @@ -126,7 +126,6 @@ class IPv6TransitionAddresses extends Operation { */ function macTransition(input) { let output = ""; - console.log(input); const MACPARTS = input.split(":"); if (!args[1]) { output += "EUI-64 Interface ID: ";