UNPKG

cerceis-lib

Version:

Contains list of quality of life functions that is written in TypeScript and es6

215 lines (205 loc) 8.08 kB
import { primeConst, compressionHash } from "./constants.js" export const Sha256 = (inputStr: string) => { const _toBinary = (text: string): string => { let rs: string = "" for (let i = 0; i < text.length; i++) { rs += text[i].charCodeAt(0).toString(2).padStart(8, "0") } return rs } //Shift right //Rotate right //XOR //ADD <= remember to keep it in 32 bit range const _rotr = (arr: string[], attempt: number = 1): string[] => { let tmp: any[] = [...arr] for (let i = 0; i < attempt; i++) { tmp = [tmp.pop(), ...tmp] } return tmp } const _shr = (arr: string[], attempt: number = 1): string[] => { let tmp: any[] = [...arr] for (let i = 0; i < attempt; i++) { tmp.pop() tmp.unshift("0") } return tmp } const _xor = (arrA: string[], arrB: string[], arrC: string[]): string[] => { const tmp: string[] = [] arrA.forEach((bit, index) => { tmp[index] = String(Number(bit) ^ Number(arrB[index]) ^ Number(arrC[index])) }) return tmp } const _add = (arrA: string[], arrB: string[]): string[] => { const tmp: string[] = [] const len: number = arrA.length; let extra: number = 0 for (let i = arrA.length - 1; i >= 0; i--) { const bitValue: number = Number(arrA[i]) + Number(arrB[i]) + extra tmp[i] = bitValue > 1 ? String(bitValue - 2) : String(bitValue) extra = bitValue > 1 ? 1 : 0 } return tmp } /** * Functions * choice, given x,y,z. If x = 1 takes y, if x = 0 takes z * major, given x,y,z. If numbers of 1 > 0 then 1. else 0. */ const _choice = (arrA: string[], arrB: string[], arrC: string[]): string[] => { let tmp: string[] = [] arrA.forEach((bit, index) => { tmp[index] = bit === "1" ? arrB[index] : arrC[index]; }) return tmp; } const _major = (arrA: string[], arrB: string[], arrC: string[]): string[] => { let tmp: string[] = [] arrA.forEach((bit, index) => { const val: string = bit + arrB[index] + arrC[index] if ( val === "000" || val === "001" || val === "010" || val === "100" ) tmp[index] = "0" else if ( val === "111" || val === "110" || val === "101" || val === "011" ) tmp[index] = "1" }) return tmp; } /** * Compound movements * sigZero = ROTR 7, ROTR 18, SHR 3, XOR * sigOne = ROTR 17, ROTR 19, SHR 10, XOR * uSigZero = ROTR 2, ROTR 13, ROTR 22, XOR * uSigOne = ROTR 6, ROTR 11, ROTR 25, XOR */ const _sigZero = (arr: string[]): string[] => { const rotr7 = _rotr(arr, 7) const rotr18 = _rotr(arr, 18) const shr3: string[] = _shr(arr, 3) return _xor(rotr7, rotr18, shr3) } const _sigOne = (arr: string[]): string[] => { const rotr17 = _rotr(arr, 17) const rotr19 = _rotr(arr, 19) const shr10: string[] = _shr(arr, 10) return _xor(rotr17, rotr19, shr10) } const _uSigZero = (arr: string[]): string[] => { const rotr2 = _rotr(arr, 2) const rotr13 = _rotr(arr, 13) const rotr22 = _rotr(arr, 22) return _xor(rotr2, rotr13, rotr22) } const _uSigOne = (arr: string[]): string[] => { const rotr6 = _rotr(arr, 6) const rotr11 = _rotr(arr, 11) const rotr25 = _rotr(arr, 25) return _xor(rotr6, rotr11, rotr25) } const shiftCompressionMap = (compressionMap: {[key: string]: string[]}): void => { compressionMap["h"] = [...compressionMap["g"]]; compressionMap["g"] = [...compressionMap["f"]]; compressionMap["f"] = [...compressionMap["e"]]; compressionMap["e"] = [...compressionMap["d"]]; compressionMap["d"] = [...compressionMap["c"]]; compressionMap["c"] = [...compressionMap["b"]]; compressionMap["b"] = [...compressionMap["a"]]; compressionMap["a"] = [] } /** * Structure will be: * The binary of the message + 1 as separator + padding of 0 until 448 bits + length of the message with start padding of 0. * End result will be total of 512 in length */ let messageBin: string = _toBinary(inputStr) const messageBlocks: string[] = []; const messageLengthBin = messageBin.length.toString(2).padStart(64, "0") const blockCount: number = Math.ceil((messageBin.length + 1 + 64) / 512) const finalLength = blockCount * 512 /* messageBin += "1" //Separator messageBin = messageBin.padEnd(512 * blockCount - 64, "0") //padding of 0 until 448 bits messageBin += messageLengthBin //Remaining 64 with length of the message with start padding of 0. */ // 𝑘=512𝑖+447−𝑚 /** * k = paddings * i = blockCount * m = input length * Pre-processing (Padding): begin with the original message of length L bits append a single '1' bit append K '0' bits, where K is the minimum number >= 0 such that L + 1 + K + 64 is a multiple of 512 append L as a 64-bit big-endian integer, making the total post-processed length a multiple of 512 bits such that the bits in the message are L 1 00..<K 0's>..00 <L as 64 bit integer> = k*512 total bits */ messageBin += "1" //Separator messageBin = messageBin.padEnd(finalLength-64, "0") //padding of 0 until 448 bits messageBin += messageLengthBin //Remaining 64 with length of the message with start padding of 0. for (let i = 0; i < blockCount; i++) { let messageChunks = messageBin.slice(i * 512, i * 512 + 512) //Add padding to last block messageBlocks.push(messageChunks) } let finalCompression = {...compressionHash} //message schedule messageBlocks.forEach((block, bi) => { let localCompression = {...finalCompression} const words: string[][] = []; for (let i = 0; i < 16; i++) { words.push(block.slice(i * 32, i * 32 + 32).split("")) } //Words need to be 64 in length, so we gonna expand it //sigOne(-2) + (-7) + sigZero(-15) + (-16) while(words.length < 64){ words.push( _add( _add( _add(_sigOne(words[words.length-2]), words[words.length-7]), _sigZero(words[words.length-15]) ), words[words.length-16] ) ) } //Compression /** * T1 = uSigOne(e) + choice(e,f,g) + h + K0 + W0 * T2 = uSigZero(a) + major(a,b,c) */ words.forEach((word, index) => { const t1: string[] = _add( _add( _add( _add(_uSigOne(localCompression.e), _choice(localCompression.e, localCompression.f, localCompression.g)), localCompression.h ), primeConst[index] ), word ) const t2: string[] = _add( _uSigZero(localCompression.a), _major(localCompression.a, localCompression.b, localCompression.c) ) shiftCompressionMap(localCompression) localCompression.a = _add(t1, t2) localCompression.e = _add(localCompression.e, t1) }) for(let id in localCompression){ if(bi === 0) finalCompression[id] = _add(compressionHash[id], localCompression[id]) else finalCompression[id] = _add(finalCompression[id], localCompression[id]) } }) let result: string = "" for(let id in finalCompression) result += parseInt(finalCompression[id].join(""), 2).toString(16) return result }