fy-convertor
Version:
Convert excel/xml/json/bin/protocl/ts/as ...
224 lines • 9.13 kB
JavaScript
"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