@sskmy1024y/react-native-hash
Version:
A hashing library for react-native
205 lines (182 loc) • 5.38 kB
JavaScript
/* eslint linebreak-style: ["error", "windows"] */
/* eslint-disable no-use-before-define */
import Base from './Base.js';
import Hex from './Hex.js';
/**
* An array of 32-bit words.
*
* @property {Array} words The array of 32-bit words.
* @property {number} sigBytes The number of significant bytes in this word array.
*/
export default class WordArray extends Base {
/**
* Initializes a newly created word array.
*
* @param {Array} words (Optional) An array of 32-bit words.
* @param {number} sigBytes (Optional) The number of significant bytes in the words.
*
* @example
*
* var wordArray = CryptoJS.lib.WordArray.create();
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
*/
constructor(words = [], sigBytes = words.length * 4) {
super();
let typedArray = words;
// Convert buffers to uint8
if (typedArray instanceof ArrayBuffer) {
typedArray = new Uint8Array(typedArray);
}
// Convert other array views to uint8
if (
typedArray instanceof Int8Array
|| typedArray instanceof Uint8ClampedArray
|| typedArray instanceof Int16Array
|| typedArray instanceof Uint16Array
|| typedArray instanceof Int32Array
|| typedArray instanceof Uint32Array
|| typedArray instanceof Float32Array
|| typedArray instanceof Float64Array
) {
typedArray = new Uint8Array(
typedArray.buffer,
typedArray.byteOffset,
typedArray.byteLength,
);
}
// Handle Uint8Array
if (typedArray instanceof Uint8Array) {
// Shortcut
const typedArrayByteLength = typedArray.byteLength;
// Extract bytes
const _words = [];
for (let i = 0; i < typedArrayByteLength; i += 1) {
_words[i >>> 2] |= typedArray[i] << (24 - (i % 4) * 8);
}
// Initialize this word array
this.words = _words;
this.sigBytes = typedArrayByteLength;
} else {
// Else call normal init
this.words = words;
this.sigBytes = sigBytes;
}
}
/**
* Creates a word array filled with random bytes.
*
* @param {number} nBytes The number of random bytes to generate.
*
* @return {WordArray} The random word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.lib.WordArray.random(16);
*/
static random(nBytes) {
const words = [];
const r = (m_w) => {
let _m_w = m_w;
let _m_z = 0x3ade68b1;
const mask = 0xffffffff;
return () => {
_m_z = (0x9069 * (_m_z & 0xffff) + (_m_z >> 0x10)) & mask;
_m_w = (0x4650 * (_m_w & 0xffff) + (_m_w >> 0x10)) & mask;
let result = ((_m_z << 0x10) + _m_w) & mask;
result /= 0x100000000;
result += 0.5;
return result * (Math.random() > 0.5 ? 1 : -1);
};
};
for (let i = 0, rcache; i < nBytes; i += 4) {
const _r = r((rcache || Math.random()) * 0x100000000);
rcache = _r() * 0x3ade67b7;
words.push((_r() * 0x100000000) | 0);
}
return new WordArray(words, nBytes);
}
/**
* Converts this word array to a string.
*
* @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
*
* @return {string} The stringified word array.
*
* @example
*
* var string = wordArray + '';
* var string = wordArray.toString();
* var string = wordArray.toString(CryptoJS.enc.Utf8);
*/
toString(encoder = Hex) {
return encoder.stringify(this);
}
/**
* Concatenates a word array to this word array.
*
* @param {WordArray} wordArray The word array to append.
*
* @return {WordArray} This word array.
*
* @example
*
* wordArray1.concat(wordArray2);
*/
concat(wordArray) {
// Shortcuts
const thisWords = this.words;
const thatWords = wordArray.words;
const thisSigBytes = this.sigBytes;
const thatSigBytes = wordArray.sigBytes;
// Clamp excess bits
this.clamp();
// Concat
if (thisSigBytes % 4) {
// Copy one byte at a time
for (let i = 0; i < thatSigBytes; i += 1) {
const thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
thisWords[(thisSigBytes + i) >>> 2]
|= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);
}
} else {
// Copy one word at a time
for (let i = 0; i < thatSigBytes; i += 4) {
thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2];
}
}
this.sigBytes += thatSigBytes;
// Chainable
return this;
}
/**
* Removes insignificant bits.
*
* @example
*
* wordArray.clamp();
*/
clamp() {
// Shortcuts
const { words, sigBytes } = this;
// Clamp
words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);
words.length = Math.ceil(sigBytes / 4);
}
/**
* Creates a copy of this word array.
*
* @return {WordArray} The clone.
*
* @example
*
* var clone = wordArray.clone();
*/
clone() {
const clone = super.clone.call(this);
clone.words = this.words.slice(0);
return clone;
}
}