redesign algorithm

This commit is contained in:
afonya2 2025-05-17 15:17:08 +02:00
parent 2c447c9381
commit 667452c49e
Signed by: afonya
GPG key ID: EBB9C4CAFAAFB2DC

142
IGA.ts
View file

@ -55,10 +55,14 @@ function generatePadding(len: number, seed?: number): padding {
}
}
function copy(input: number[]): number[] {
let out: number[] = []
function copy(input: any[], deep: boolean): any[] {
let out: any[] = []
for (let i = 0; i < input.length; i++) {
out[i] = input[i]
if (deep && typeof input[i] == "object") {
out[i] = copy(input[i], deep)
} else {
out[i] = input[i]
}
}
return out
}
@ -120,83 +124,137 @@ function checksum(input: string) {
return state.join("")
}
function hash(input: string, salt: number = 0, iterations: number = 32, len: number = 32, seed?: number): string {
function hashBlock(block: number[][], salt: number, iterations: number): number[][] {
for (let it = 0; it < iterations; it++) {
let state: number[][] = copy(block, true)
//Add columns
for (let i = 0; i < block.length; i++) {
for (let ii = 0; ii < block[i].length; ii++) {
let temp = state[i][ii]+(state[i][ii+1] ? state[i][ii+1] : (state[i+1] ? state[i+1][0] : state[0][0]))
while (temp > 65536) {
temp -= it==0 ? 2411 : state[i][ii-1] ? state[i][ii-1] : (state[i-1] ? state[i-1][state[i-1].length-1] : state[state.length-1][state[state.length-1].length-1])
}
block[i][ii] = temp
}
}
state = copy(block, true)
//Add rows
for (let i = 0; i < block.length; i++) {
for (let ii = 0; ii < block[i].length; ii++) {
let temp = state[i][ii]+(state[i+1] ? state[i+1][ii] : (state[0][ii+1] ? state[0][ii+1] : state[0][0]))
while (temp > 65536) {
temp -= it==0 ? 2411 : state[i-1] ? state[i-1][ii] : (state[state.length-1][ii-1] ? state[state.length-1][ii-1] : state[state.length-1][state[state.length-1].length-1])
}
block[i][ii] = temp
}
}
}
return block
}
function hash(input: string, salt: number = 0, len: number = 32, seed?: number): string {
if (len*4%16 != 0) {
throw new Error("Invalid length")
}
if (len < 16) {
throw new Error("Length must be at least 16")
}
if (len > 512) {
throw new Error("Length must be at most 512")
}
if (seed != undefined) {
if (seed < 0 || seed > 65535) {
throw new Error("Invalid seed")
}
}
const iterations = len*2
const padding = generatePadding(len, seed);
let hash: number[] = []
for (let i = 0; i < padding.padding.length; i++) {
hash[i] = padding.padding[i]
let blocks: number[][][] = [[[]]] // len x 16
for (let ip = 0; ip < padding.padding.length; ip++) {
if (blocks[blocks.length-1][blocks[blocks.length-1].length-1].length == len) {
blocks[blocks.length-1].push([])
}
blocks[blocks.length-1][blocks[blocks.length-1].length-1].push(padding.padding[ip])
}
let plus = hash.length
for (let i = 0; i < input.length; i++) {
if (input.charCodeAt(i) < 0 || input.charCodeAt(i) > 50000) {
throw new Error("Character at index " + i + " is not a valid character")
}
hash[plus+i] = input.charCodeAt(i)
}
for (let i = 0; i < iterations; i++) {
let state = copy(hash)
for (let ii = 0; ii < hash.length; ii++) {
let temp = state[ii] + (state[ii+1] ? state[ii+1] : state[0]) + salt
while (temp > 65536) {
temp -= i==0 ? 2411 : (state[ii-1] ? state[ii-1] : state[state.length-1])
if (blocks[blocks.length-1].length == 16 && blocks[blocks.length-1][blocks[blocks.length-1].length-1].length == len) {
blocks.push([[]])
for (let ip = 0; ip < padding.padding.length; ip++) {
if (blocks[blocks.length-1][blocks[blocks.length-1].length-1].length == len) {
blocks[blocks.length-1].push([])
}
blocks[blocks.length-1][blocks[blocks.length-1].length-1].push(padding.padding[ip])
}
hash[ii] = temp
}
if (blocks[blocks.length-1][blocks[blocks.length-1].length-1].length == len) {
blocks[blocks.length-1].push([])
}
blocks[blocks.length-1][blocks[blocks.length-1].length-1].push(input.charCodeAt(i))
}
let pPos = 0
while (blocks[blocks.length-1].length != 16 || blocks[blocks.length-1][blocks[blocks.length-1].length-1].length != len) {
if (blocks[blocks.length-1][blocks[blocks.length-1].length-1].length == len) {
blocks[blocks.length-1].push([])
}
blocks[blocks.length-1][blocks[blocks.length-1].length-1].push(padding.padding[pPos])
pPos++
if (pPos >= padding.padding.length) {
pPos = 0
}
}
const pSeed = fixbin(dec2bin(padding.seed), 16)
let sumAdd = ""
for (let i = 0; sumAdd.length < 16 && i < padding.padding.length; i++) {
sumAdd += padding.padding[i].toString(16)
for (let i = 0; i < blocks.length; i++) {
blocks[i] = hashBlock(blocks[i], salt, iterations)
}
sumAdd = sumAdd.substring(0, 16).toUpperCase()
const sum = checksum(input + sumAdd)
let bin = ""
for (let i = 0; bin.length < len*4-32; i++) {
bin += hash[i] ? fixbin(dec2bin(hash[i]), 16) : "0000000000000000"
const pBin = fixbin(dec2bin(padding.seed), 16)
let dataBins: string[] = []
for (let i = 0; i < blocks.length; i++) {
dataBins[i] = ""
for (let ii = 0; dataBins[i].length < len*4-32; ii++) {
dataBins[i] += fixbin(dec2bin(blocks[i][0][ii]), 16)
}
}
let hashes: string[] = []
for (let i = 0; i < dataBins.length; i++) {
let hsh = bin2hex(pBin+dataBins[i])
const crc = checksum(hsh)
hsh += bin2hex(crc)
hashes.push(hsh)
}
//console.log(hashes);
if (hashes.length == 1) {
return hashes[0]
} else {
return hash(hashes.join(""), salt, len, padding.seed)
}
const outBin = pSeed + bin + sum
const out = bin2hex(outBin)
return out
}
function verifyHash(input: string, inHash: string, salt: number = 0, iterations: number = 32, len: number = 32): verifyOut {
function verifyHash(input: string, inHash: string, salt: number = 0, len: number = 32): verifyOut {
if (len*4%16 != 0) {
throw new Error("Invalid length")
}
if (len < 16) {
throw new Error("Length must be at least 16")
}
if (len > 512) {
throw new Error("Length must be at most 512")
}
if (inHash.length != len) {
throw new Error("The hash is not " + len + " long")
}
const hBin = hex2bin(inHash)
const pSeed = bin2dec(hBin.substring(0, 16))
const inSum = hBin.substring(hBin.length-16, hBin.length)
const padding = generatePadding(len, pSeed);
let sumAdd = ""
for (let i = 0; sumAdd.length < 16 && i < padding.padding.length; i++) {
sumAdd += padding.padding[i].toString(16)
}
sumAdd = sumAdd.substring(0, 16).toUpperCase()
const sum = checksum(input + sumAdd)
if (inSum != sum) {
const inCRC = hBin.substring(hBin.length-16, hBin.length)
const crc = checksum(inHash.substring(0, inHash.length-4))
if (inCRC != crc) {
return {
valid: false,
reason: "Checksum does not match"
}
}
const verifyHash = hash(input, salt, iterations, len, pSeed)
const verifyHash = hash(input, salt, len, pSeed)
if (inHash == verifyHash) {
return {
valid: true,
@ -210,6 +268,10 @@ function verifyHash(input: string, inHash: string, salt: number = 0, iterations:
}
}
/*let hsh = hash("test")
console.log(hsh)
console.log(verifyHash("test", hsh))*/
export default {
hash,
verifyHash