| "use strict"; | ||
| const isPrimitive = (seed) => typeof seed !== "object" && seed !== null; | ||
| module.exports = { | ||
| isPrimitive, | ||
| }; |
| "use strict"; | ||
| const { isPrimitive } = require("./checkers"); | ||
| const getOptions = (seed, defaultEncoding) => ({ | ||
| seed, | ||
| encoding: defaultEncoding, | ||
| }); | ||
| const getNormalizedParams = (params, defaultEncoding) => { | ||
| if (isPrimitive(params)) { | ||
| return getOptions(params, defaultEncoding); | ||
| } else { | ||
| return { | ||
| ...params, | ||
| seed: params.seed || 0, | ||
| }; | ||
| } | ||
| }; | ||
| module.exports = { | ||
| getNormalizedParams, | ||
| }; |
+51
-58
| "use strict"; | ||
| const huffman = require("./lib/huffman"); | ||
| const { getNormalizedParams } = require("./lib/formatters"); | ||
| const enums = { | ||
| DEFAULT: 2 << 0, | ||
| HUFFMAN: 2 << 1, | ||
| HUFFMAN_COMPRESSED: 2 << 2, | ||
| }; | ||
| class cipherio { | ||
| static DEFAULT = 2 << 0; | ||
| static HUFFMAN = 2 << 1; | ||
| static HUFFMAN_COMPRESSED = 2 << 2; | ||
| const cipherio = { | ||
| compile: (code, seed) => { | ||
| if (isPrimitive(seed)) { | ||
| seed = getOptions(seed); | ||
| } else { | ||
| seed.seed = seed.seed || 0; | ||
| } | ||
| static #BIT_SHIFT_AMOUNT = 8; | ||
| static #SEED_MODIFIER = 0xff; | ||
| cipherio.throwIfUnknownEncoding(seed.encoding); | ||
| static compile(code, params) { | ||
| params = getNormalizedParams(params, this.DEFAULT); | ||
| if (seed.encoding === cipherio.HUFFMAN) { | ||
| return huffman.encode(code, seed.seed); | ||
| switch (params.encoding) { | ||
| case this.HUFFMAN: { | ||
| return huffman.encode(code, params.seed); | ||
| } | ||
| case this.HUFFMAN_COMPRESSED: { | ||
| return huffman.encode(code, params.seed, { compressed: true }); | ||
| } | ||
| case this.DEFAULT: | ||
| return this.#shuffle(code, params, this.#disorder.bind(this)); | ||
| default: | ||
| this.#throw(); | ||
| } | ||
| } | ||
| if (seed.encoding === cipherio.HUFFMAN_COMPRESSED) { | ||
| return huffman.encode(code, seed.seed, { compressed: true }); | ||
| } | ||
| return cipherio.shuffle(code, seed, cipherio.avalanche); | ||
| }, | ||
| read: (code) => { | ||
| static read(code) { | ||
| let compiledCode = code; | ||
@@ -36,5 +36,5 @@ let seed = 0; | ||
| while (1) { | ||
| const decodedCode = cipherio.decode(compiledCode, seed); | ||
| const decodedCode = this.#decode(compiledCode, seed); | ||
| const reEncodedCode = cipherio.compile(decodedCode, seed); | ||
| const reEncodedCode = this.compile(decodedCode, seed); | ||
@@ -61,23 +61,19 @@ if (code === reEncodedCode) { | ||
| } | ||
| } catch (_) { | ||
| console.log(_); | ||
| } | ||
| } catch {} | ||
| seed++; | ||
| } | ||
| }, | ||
| decode: (binary, seed) => { | ||
| if (isPrimitive(seed)) { | ||
| seed = getOptions(seed); | ||
| } else { | ||
| seed.seed = seed.seed || 0; | ||
| } | ||
| } | ||
| if (seed.encoding === cipherio.HUFFMAN) { | ||
| return huffman.decode(binary, seed); | ||
| static #decode(binary, params) { | ||
| params = getNormalizedParams(params); | ||
| if (params.encoding === this.HUFFMAN) { | ||
| return huffman.decode(binary, params); | ||
| } | ||
| return cipherio.shuffle(binary, seed, cipherio.unavalanche); | ||
| }, | ||
| shuffle: (text, { seed }, shuffleFunction) => { | ||
| return this.#shuffle(binary, params, this.#restore.bind(this)); | ||
| } | ||
| static #shuffle(text, { seed }, shuffleFunction) { | ||
| let shuffled = ""; | ||
@@ -100,25 +96,22 @@ | ||
| return shuffled; | ||
| }, | ||
| avalanche: ({ code, index, seed }) => { | ||
| return code ^ ((code << 8) | (seed & 0xff) | (index & 0xff)); | ||
| }, | ||
| } | ||
| unavalanche: ({ code, index, seed }) => { | ||
| return (code ^ seed ^ index) >> 8; | ||
| }, | ||
| ...enums, | ||
| throwIfUnknownEncoding: (encoding) => { | ||
| if (!Object.values(enums).includes(encoding)) { | ||
| throw new Error(`Encoding ${encoding} not supported`); | ||
| } | ||
| }, | ||
| }; | ||
| static #disorder({ code, index, seed }) { | ||
| return ( | ||
| code ^ | ||
| ((code << this.#BIT_SHIFT_AMOUNT) | | ||
| (seed & this.#SEED_MODIFIER) | | ||
| (index & this.#SEED_MODIFIER)) | ||
| ); | ||
| } | ||
| const isPrimitive = (seed) => typeof seed !== "object" && seed !== null; | ||
| static #restore({ code, index, seed }) { | ||
| return (code ^ seed ^ index) >> this.#BIT_SHIFT_AMOUNT; | ||
| } | ||
| const getOptions = (seed) => ({ | ||
| seed, | ||
| encoding: cipherio.DEFAULT, | ||
| }); | ||
| static #throw(encoding) { | ||
| throw new Error(`Encoding ${encoding} not supported`); | ||
| } | ||
| } | ||
| module.exports = cipherio; |
+1
-1
| { | ||
| "name": "cipherio", | ||
| "version": "1.2.2", | ||
| "version": "1.2.3", | ||
| "description": "Make secure parts in shared code", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
+23
-0
@@ -23,2 +23,25 @@ # cipherio | ||
| Encoding types | ||
| ```js | ||
| cipherio.DEFAULT; // disorders text in the idempotent way | ||
| cipherio.HUFFMAN; // disorders text using huffman algorithm | ||
| cipherio.HUFFMAN_COMPRESSED; // disorders text using huffman algorithm with smaller letter count of the resulting decoded text | ||
| ``` | ||
| ```js | ||
| const code = `actual = 1;`; | ||
| const options1 = { encoding: cipherio.HUFFMAN, seed: 0 }; | ||
| const options2 = { encoding: cipherio.HUFFMAN_COMPRESSED, seed: 1 }; | ||
| const encoded1 = cipherio.compile(code, options1); | ||
| const ecnoded2 = cipherio.compile(code, options2); | ||
| const decoded1 = cipherio.read(encoded1); | ||
| const decoded2 = cipherio.read(ecnoded2); | ||
| ``` | ||
| `seed` defaults to 0 | ||
| `encoding` defaults to `cipherio.DEFAULT` | ||
| ## Test | ||
@@ -25,0 +48,0 @@ |
7360
17.82%6
50%213
8.12%51
82.14%