UNPKG

cyberchef

Version:

The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.

95 lines (80 loc) 3.41 kB
/** * @author PenguinGeorge [george@penguingeorge.com] * @copyright Crown Copyright 2018 * @license Apache-2.0 */ import Operation from "../Operation.mjs"; import OperationError from "../errors/OperationError.mjs"; import Utils from "../Utils.mjs"; import {alphabetName, ALPHABET_OPTIONS} from "../lib/Base85.mjs"; /** * To Base85 operation */ class ToBase85 extends Operation { /** * To Base85 constructor */ constructor() { super(); this.name = "To Base85"; this.module = "Default"; this.description = "Base85 (also called Ascii85) is a notation for encoding arbitrary byte data. It is usually more efficient that Base64.<br><br>This operation encodes data in an ASCII string (with an alphabet of your choosing, presets included).<br><br>e.g. <code>hello world</code> becomes <code>BOu!rD]j7BEbo7</code><br><br>Base85 is commonly used in Adobe's PostScript and PDF file formats.<br><br><strong>Options</strong><br><u>Alphabet</u><ul><li>Standard - The standard alphabet, referred to as Ascii85</li><li>Z85 (ZeroMQ) - A string-safe variant of Base85, which avoids quote marks and backslash characters</li><li>IPv6 - A variant of Base85 suitable for encoding IPv6 addresses (RFC 1924)</li></ul><u>Include delimiter</u><br>Adds a '<~' and '~>' delimiter to the start and end of the data. This is standard for Adobe's implementation of Base85."; this.infoURL = "https://wikipedia.org/wiki/Ascii85"; this.inputType = "ArrayBuffer"; this.outputType = "string"; this.args = [ { name: "Alphabet", type: "editableOption", value: ALPHABET_OPTIONS }, { name: "Include delimeter", type: "boolean", value: false } ]; } /** * @param {ArrayBuffer} input * @param {Object[]} args * @returns {string} */ run(input, args) { input = new Uint8Array(input); const alphabet = Utils.expandAlphRange(args[0]).join(""), encoding = alphabetName(alphabet), includeDelim = args[1]; let result = ""; if (alphabet.length !== 85 || [].unique.call(alphabet).length !== 85) { throw new OperationError("Error: Alphabet must be of length 85"); } if (input.length === 0) return ""; let block; for (let i = 0; i < input.length; i += 4) { block = ( ((input[i]) << 24) + ((input[i + 1] || 0) << 16) + ((input[i + 2] || 0) << 8) + ((input[i + 3] || 0)) ) >>> 0; if (encoding !== "Standard" || block > 0) { let digits = []; for (let j = 0; j < 5; j++) { digits.push(block % 85); block = Math.floor(block / 85); } digits = digits.reverse(); if (input.length < i + 4) { digits.splice(input.length - (i + 4), 4); } result += digits.map(digit => alphabet[digit]).join(""); } else { result += (encoding === "Standard") ? "z" : null; } } return includeDelim ? `<~${result}~>` : result; } } export default ToBase85;