UNPKG

fy-convertor

Version:

Convert excel/xml/json/bin/protocl/ts/as ...

224 lines 9.13 kB
"use strict"; // To ensure cross-browser support even without a proper SubtleCrypto // impelmentation (or without access to the impelmentation, as is the case with // Chrome loaded over HTTP instead of HTTPS), this library can create SHA-256 // HMAC signatures using nothing but raw JavaScript Object.defineProperty(exports, "__esModule", { value: true }); exports.hash = exports.hex = exports.sign = void 0; /* eslint-disable no-magic-numbers, id-length, no-param-reassign, new-cap */ // By giving internal functions names that we can mangle, future calls to // them are reduced to a single byte (minor space savings in minified file) var uint8Array = Uint8Array; var uint32Array = Uint32Array; var pow = Math.pow; // Will be initialized below // Using a Uint32Array instead of a simple array makes the minified code // a bit bigger (we lose our `unshift()` hack), but comes with huge // performance gains var DEFAULT_STATE = new uint32Array(8); var ROUND_CONSTANTS = []; // Reusable object for expanded message // Using a Uint32Array instead of a simple array makes the minified code // 7 bytes larger, but comes with huge performance gains var M = new uint32Array(64); // After minification the code to compute the default state and round // constants is smaller than the output. More importantly, this serves as a // good educational aide for anyone wondering where the magic numbers come // from. No magic numbers FTW! function getFractionalBits(n) { return ((n - (n | 0)) * pow(2, 32)) | 0; } var n = 2, nPrime = 0; while (nPrime < 64) { // isPrime() was in-lined from its original function form to save // a few bytes var isPrime = true; // Math.sqrt() was replaced with pow(n, 1/2) to save a few bytes // var sqrtN = pow(n, 1 / 2); // So technically to determine if a number is prime you only need to // check numbers up to the square root. However this function only runs // once and we're only computing the first 64 primes (up to 311), so on // any modern CPU this whole function runs in a couple milliseconds. // By going to n / 2 instead of sqrt(n) we net 8 byte savings and no // scaling performance cost for (var factor = 2; factor <= n / 2; factor++) { if (n % factor === 0) { isPrime = false; } } if (isPrime) { if (nPrime < 8) { DEFAULT_STATE[nPrime] = getFractionalBits(pow(n, 1 / 2)); } ROUND_CONSTANTS[nPrime] = getFractionalBits(pow(n, 1 / 3)); nPrime++; } n++; } // For cross-platform support we need to ensure that all 32-bit words are // in the same endianness. A UTF-8 _TextEncoder will return BigEndian data, // so upon reading or writing to our ArrayBuffer we'll only swap the bytes // if our system is LittleEndian (which is about 99% of CPUs) var LittleEndian = !!new uint8Array(new uint32Array([1]).buffer)[0]; // Simple _TextEncoder implementation for UTF-8 encoding function CustomTextEncoder() { this.encode = function (input) { const bytes = []; for (let i = 0; i < input.length; i++) { const char = input.charCodeAt(i); if (char < 0x80) { bytes.push(char); } else if (char < 0x800) { bytes.push((char >> 6) | 0xC0); bytes.push((char & 0x3F) | 0x80); } else if (char < 0x10000) { bytes.push((char >> 12) | 0xE0); bytes.push(((char >> 6) & 0x3F) | 0x80); bytes.push((char & 0x3F) | 0x80); } else { bytes.push((char >> 18) | 0xF0); bytes.push(((char >> 12) & 0x3F) | 0x80); bytes.push(((char >> 6) & 0x3F) | 0x80); bytes.push((char & 0x3F) | 0x80); } } return new Uint8Array(bytes); }; } // 创建CustomTextEncoder实例 const _TextEncoder = new CustomTextEncoder(); // 使用CustomTextEncoder进行UTF-8编码 function convertEndian(word) { if (LittleEndian) { return ( // byte 1 -> byte 4 (word >>> 24) | // byte 2 -> byte 3 (((word >>> 16) & 0xff) << 8) | // byte 3 -> byte 2 ((word & 0xff00) << 8) | // byte 4 -> byte 1 (word << 24)); } else { return word; } } function rightRotate(word, bits) { return (word >>> bits) | (word << (32 - bits)); } function sha256(data) { // Copy default state var STATE = DEFAULT_STATE.slice(); // Caching this reduces occurrences of ".length" in minified JavaScript // 3 more byte savings! :D var legth = data.length; // Pad data var bitLength = legth * 8; var newBitLength = (512 - ((bitLength + 64) % 512) - 1) + bitLength + 65; // "bytes" and "words" are stored BigEndian var bytes = new uint8Array(newBitLength / 8); var words = new uint32Array(bytes.buffer); bytes.set(data, 0); // Append a 1 bytes[legth] = 0b10000000; // Store length in BigEndian words[words.length - 1] = convertEndian(bitLength); // Loop iterator (avoid two instances of "var") -- saves 2 bytes var round; // Process blocks (512 bits / 64 bytes / 16 words at a time) for (var block = 0; block < newBitLength / 32; block += 16) { var workingState = STATE.slice(); // Rounds for (round = 0; round < 64; round++) { var MRound; // Expand message if (round < 16) { // Convert to platform Endianness for later math MRound = convertEndian(words[block + round]); } else { var gamma0x = M[round - 15]; var gamma1x = M[round - 2]; MRound = M[round - 7] + M[round - 16] + (rightRotate(gamma0x, 7) ^ rightRotate(gamma0x, 18) ^ (gamma0x >>> 3)) + (rightRotate(gamma1x, 17) ^ rightRotate(gamma1x, 19) ^ (gamma1x >>> 10)); } // M array matches platform endianness M[round] = MRound |= 0; // Computation var t1 = (rightRotate(workingState[4], 6) ^ rightRotate(workingState[4], 11) ^ rightRotate(workingState[4], 25)) + ((workingState[4] & workingState[5]) ^ (~workingState[4] & workingState[6])) + workingState[7] + MRound + ROUND_CONSTANTS[round]; var t2 = (rightRotate(workingState[0], 2) ^ rightRotate(workingState[0], 13) ^ rightRotate(workingState[0], 22)) + ((workingState[0] & workingState[1]) ^ (workingState[2] & (workingState[0] ^ workingState[1]))); for (var i = 7; i > 0; i--) { workingState[i] = workingState[i - 1]; } workingState[0] = (t1 + t2) | 0; workingState[4] = (workingState[4] + t1) | 0; } // Update state for (round = 0; round < 8; round++) { STATE[round] = (STATE[round] + workingState[round]) | 0; } } // Finally the state needs to be converted to BigEndian for output // And we want to return a Uint8Array, not a Uint32Array return new uint8Array(new uint32Array(STATE.map(function (val) { return convertEndian(val); })).buffer); } function hmac(key, data) { if (key.length > 64) key = sha256(key); if (key.length < 64) { const tmp = new Uint8Array(64); tmp.set(key, 0); key = tmp; } // Generate inner and outer keys var innerKey = new Uint8Array(64); var outerKey = new Uint8Array(64); for (var i = 0; i < 64; i++) { innerKey[i] = 0x36 ^ key[i]; outerKey[i] = 0x5c ^ key[i]; } // Append the innerKey var msg = new Uint8Array(data.length + 64); msg.set(innerKey, 0); msg.set(data, 64); // Has the previous message and append the outerKey var result = new Uint8Array(64 + 32); result.set(outerKey, 0); result.set(sha256(msg), 64); // Hash the previous message return sha256(result); } // Convert a string to a Uint8Array, SHA-256 it, and convert back to string // const encoder = new _TextEncoder("utf-8"); function sign(inputKey, inputData) { const key = typeof inputKey === "string" ? _TextEncoder.encode(inputKey) : inputKey; const data = typeof inputData === "string" ? _TextEncoder.encode(inputData) : inputData; return hmac(key, data); } exports.sign = sign; function hex(bin) { return bin.reduce((acc, val) => acc + ("00" + val.toString(16)).substring(-2), ""); } exports.hex = hex; function hash(str) { return hex(sha256(_TextEncoder.encode(str))); } exports.hash = hash; //# sourceMappingURL=hmacSHA256.js.map