From 8e832eb380d43979649b2f6b893dc74d2102cc54 Mon Sep 17 00:00:00 2001 From: afonya2 Date: Fri, 16 May 2025 18:35:35 +0200 Subject: [PATCH] do collision tests --- .gitignore | 3 +- README.md | 3 +- collision_test1.ts | 93 ++++++++++++++++++++++++++++++++++++++++++++++ collision_test2.ts | 76 +++++++++++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 collision_test1.ts create mode 100644 collision_test2.ts diff --git a/.gitignore b/.gitignore index 0f634cf..3defaaa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ package-lock.json node_modules/ -test.txt \ No newline at end of file +test.txt +collisions.json \ No newline at end of file diff --git a/README.md b/README.md index 44e7b1b..01526cb 100644 --- a/README.md +++ b/README.md @@ -13,4 +13,5 @@ console.log(IGA.verifyHash("test", hash)) - `verifyHash(input: string, inHash: string, salt: number = 0, iterations: number = 32, len: number = 32): verifyOut` - verifies the "hash", returns `{ valid: bool, reason: string }` ## DO NOT USE FOR SECURE PROJECTS - It's security has not been verified yet. -- It can't be reverted but it might collide. \ No newline at end of file +- It can't be reverted but it might collide. +- It seems like the algorithm is safe enough, however, I still don't recommend it. \ No newline at end of file diff --git a/collision_test1.ts b/collision_test1.ts new file mode 100644 index 0000000..db21b90 --- /dev/null +++ b/collision_test1.ts @@ -0,0 +1,93 @@ +import IGA from './IGA'; +import fs from 'fs'; + +type Collision = { + hash: string, + old: string, + new: string, + randomPadding: boolean +} +function sleep(ms: number): Promise { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +const len = 4 +let state = ["a"] +const alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" +let seen = {} +let counter = 0 +let collisions: Collision[] = [] +const startTime = Date.now() + +async function bruteForce(pos) { + while (true) { + if (pos != state.length - 1) { + await bruteForce(pos + 1) + } + if (pos == state.length - 1) { + let hash1 = IGA.hash(state.join("")) + let hash2 = IGA.hash(state.join(""), 0, 32, 32, 32768) + if (seen[hash1] != undefined) { + collisions.push({ + hash: hash1, + old: seen[hash1], + new: state.join(""), + randomPadding: true + }) + } else { + seen[hash1] = state.join("") + } + if (seen[hash2] != undefined) { + if (!hash1.startsWith("8000")) { + collisions.push({ + hash: hash2, + old: seen[hash2], + new: state.join(""), + randomPadding: false + }) + } + } else { + seen[hash2] = state.join("") + } + if (counter % 1000 == 0) { + let timeTook = Math.floor((Date.now() - startTime) / 100)/10 + let etaPart = 0 + for (let ln = 1; ln <= len; ln++) { + etaPart += Math.pow(alphabet.length, ln) + } + let eta = Math.max(0, Math.floor((etaPart - counter) * (timeTook / counter) * 10) / 10) + console.log("Current state: " + state.join("") + ", Last hash: " + hash1 + ", Collisions: " + collisions.length + ", Time: " + timeTook + "s, ETA: " + eta + "s"); + await sleep(1) + } + if (counter % 10000 == 0) { + fs.writeFileSync("collisions.json", JSON.stringify(collisions)) + } + counter++ + } + let currentChar = alphabet.indexOf(state[pos]) + if (currentChar == alphabet.length - 1) { + for (let i = pos; i < state.length; i++) { + state[i] = "a" + } + break + } + state[pos] = alphabet[currentChar + 1] + } + if (pos == 0 && state.length < len) { + for (let i = 0; i < state.length; i++) { + state[i] = "a" + } + state.push("a") + await bruteForce(0) + } +} + +async function main() { + await bruteForce(0) + + let tT = Math.floor((Date.now() - startTime) / 100)/10 + console.log("Done! Took " + tT + "s, Checked " + counter + " hashes, Collisions: " + collisions.length); + console.log(collisions); + fs.writeFileSync("collisions.json", JSON.stringify(collisions)) +} +main() \ No newline at end of file diff --git a/collision_test2.ts b/collision_test2.ts new file mode 100644 index 0000000..cbbe74a --- /dev/null +++ b/collision_test2.ts @@ -0,0 +1,76 @@ +import IGA from "./IGA" +import fs from "fs" + +type Collision = { + hash: string + old: string + new: string + randomPadding: boolean +} +function sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)) +} + +const len = 64 +const alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" +let seen = {} +let rawSeen = {} +let collisions: Collision[] = [] +let counter = 0 +let failCount = 0 +const startTime = Date.now() + +async function main() { + while (true) { + let str = "" + for (let i = 0; i < len; i++) { + str += alphabet[Math.floor(Math.random() * (alphabet.length - 1))] + } + let h = "" + if (rawSeen[str] == undefined) { + failCount = 0 + let hash1 = IGA.hash(str) + h = hash1 + let hash2 = IGA.hash(str, 0, 32, 32, 32768) + if (seen[hash1] != undefined) { + collisions.push({ + hash: hash1, + old: seen[hash1], + new: str, + randomPadding: true + }) + } else { + seen[hash1] = str + } + if (seen[hash2] != undefined) { + if (!hash1.startsWith("8000")) { + collisions.push({ + hash: hash2, + old: seen[hash2], + new: str, + randomPadding: false + }) + } + } else { + seen[hash2] = str + } + rawSeen[str] = true + } else { + failCount++ + if (failCount > 1000) { + console.log("Finding a qunique string took too long, exiting...") + process.exit(0) + } + } + if (counter % 1000 == 0) { + let timeTook = Math.floor((Date.now() - startTime) / 100) / 10 + console.log(`Last string: ${str}, Last hash: ${h}, Collisions: ${collisions.length}, Time: ${timeTook}s`) + await sleep(1) + } + if (counter % 10000 == 0) { + fs.writeFileSync("collisions.json", JSON.stringify(collisions)) + } + counter++ + } +} +main()