From 1d3dd86cebadf5597e3846c81b2fa4013438ce15 Mon Sep 17 00:00:00 2001 From: Diya Maheshwari Date: Wed, 24 Jun 2026 14:06:32 +0530 Subject: [PATCH] feat: add Bcrypt Generator & Validator tool --- package.json | 2 + pnpm-lock.yaml | 21 +++ pnpm-workspace.yaml | 4 +- src/constants/tools.ts | 7 + .../bcrypt-generator/BcryptGeneratorTool.tsx | 158 ++++++++++++++++++ src/pages/tools/bcrypt-generator.astro | 18 ++ 6 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 src/features/bcrypt-generator/BcryptGeneratorTool.tsx create mode 100644 src/pages/tools/bcrypt-generator.astro diff --git a/package.json b/package.json index f8085f7..0a125f4 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", "astro": "^6.1.9", + "bcryptjs": "^3.0.3", "curlconverter": "^4.12.0", "dompurify": "^3.4.7", "fuse.js": "^7.3.0", @@ -36,6 +37,7 @@ "vite": "^7" }, "devDependencies": { + "@types/bcryptjs": "^3.0.0", "@types/dompurify": "^3.2.0", "@types/papaparse": "^5.5.2" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 337db37..1c62aac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,9 @@ importers: astro: specifier: ^6.1.9 version: 6.1.9(@types/node@25.9.1)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.60.2)(yaml@2.9.0) + bcryptjs: + specifier: ^3.0.3 + version: 3.0.3 curlconverter: specifier: ^4.12.0 version: 4.12.0 @@ -66,6 +69,9 @@ importers: specifier: ^2.9.0 version: 2.9.0 devDependencies: + '@types/bcryptjs': + specifier: ^3.0.0 + version: 3.0.0 '@types/dompurify': specifier: ^3.2.0 version: 3.2.0 @@ -812,6 +818,10 @@ packages: '@types/babel__traverse@7.28.0': resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + '@types/bcryptjs@3.0.0': + resolution: {integrity: sha512-WRZOuCuaz8UcZZE4R5HXTco2goQSI2XxjGY3hbM/xDvwmqFWd4ivooImsMx65OKM6CtNKbnZ5YL+YwAwK7c1dg==} + deprecated: This is a stub types definition. bcryptjs provides its own type definitions, so you do not need this installed. + '@types/debug@4.1.13': resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} @@ -901,6 +911,10 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + bcryptjs@3.0.3: + resolution: {integrity: sha512-GlF5wPWnSa/X5LKM1o0wz0suXIINz1iHRLvTS+sLyi7XPbe5ycmYI3DlZqVGZZtDgl4DmasFg7gOB3JYbphV5g==} + hasBin: true + boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -1774,6 +1788,7 @@ packages: tsconfck@3.1.6: resolution: {integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==} engines: {node: ^18 || >=20} + deprecated: unmaintained hasBin: true peerDependencies: typescript: ^5.0.0 @@ -2611,6 +2626,10 @@ snapshots: dependencies: '@babel/types': 7.29.0 + '@types/bcryptjs@3.0.0': + dependencies: + bcryptjs: 3.0.3 + '@types/debug@4.1.13': dependencies: '@types/ms': 2.1.0 @@ -2786,6 +2805,8 @@ snapshots: baseline-browser-mapping@2.10.23: {} + bcryptjs@3.0.3: {} + boolbase@1.0.0: {} brace-expansion@1.1.15: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 29c6001..45b2385 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,5 +1,5 @@ allowBuilds: esbuild: true sharp: true - tree-sitter: set this to true or false - tree-sitter-bash: set this to true or false + tree-sitter: false + tree-sitter-bash: false diff --git a/src/constants/tools.ts b/src/constants/tools.ts index 626c63d..eb58a2c 100644 --- a/src/constants/tools.ts +++ b/src/constants/tools.ts @@ -270,4 +270,11 @@ export const tools: Tool[] = [ href: "/tools/jwt-generator-validator", icon: ``, }, + { + name: "Bcrypt Generator & Validator", + description: + "Generate bcrypt hashes with configurable salt rounds and validate plaintext against existing hashes. Runs entirely in your browser.", + href: "/tools/bcrypt-generator", + icon: ``, +}, ]; diff --git a/src/features/bcrypt-generator/BcryptGeneratorTool.tsx b/src/features/bcrypt-generator/BcryptGeneratorTool.tsx new file mode 100644 index 0000000..dff36ea --- /dev/null +++ b/src/features/bcrypt-generator/BcryptGeneratorTool.tsx @@ -0,0 +1,158 @@ +import { useState } from "react"; +import * as bcrypt from "bcryptjs"; +import ToolTextarea from "../../components/tool/ToolTextarea"; +import CopyButton from "../../ui/CopyButton"; +import ToolActions from "../../components/tool/ToolActions"; +import Button from "../../ui/Button"; +import SampleButton from "../../ui/SampleButton"; + +export default function BcryptGeneratorTool() { + const [genInput, setGenInput] = useState(""); + const [saltRounds, setSaltRounds] = useState(10); + const [genOutput, setGenOutput] = useState(""); + const [isGenerating, setIsGenerating] = useState(false); + + const [valPlaintext, setValPlaintext] = useState(""); + const [valHash, setValHash] = useState(""); + const [valResult, setValResult] = useState<"match" | "no-match" | null>(null); + const [isValidating, setIsValidating] = useState(false); + + async function handleGenerate() { + if (!genInput) return; + setIsGenerating(true); + try { + const hash = await bcrypt.hash(genInput, saltRounds); + setGenOutput(hash); + } catch { + setGenOutput("Error generating hash"); + } finally { + setIsGenerating(false); + } + } + + async function handleValidate() { + if (!valPlaintext || !valHash) return; + setIsValidating(true); + try { + const match = await bcrypt.compare(valPlaintext, valHash); + setValResult(match ? "match" : "no-match"); + } catch { + setValResult("no-match"); + } finally { + setIsValidating(false); + } + } + + function clearGenerator() { + setGenInput(""); + setGenOutput(""); + } + + function clearValidator() { + setValPlaintext(""); + setValHash(""); + setValResult(null); + } + + function loadSample() { + setGenInput("mypassword123"); + setSaltRounds(10); + } + + return ( +
+
+

Generator

+
+ Salt Rounds: +
+ {[8, 10, 12, 14].map((r) => ( + + ))} +
+ Higher = more secure but slower +
+
+ } + /> + + {genOutput && !genOutput.startsWith("Error") && ( + + )} + +
+ + + + +
+ +
+ +
+

Validator

+
+ + +
+ {valResult && ( +
+ {valResult === "match" + ? "✅ Match — plaintext matches the hash" + : "❌ No Match — plaintext does not match the hash"} +
+ )} + + + + +
+ +
+

+ Security Note: All hashing and validation is performed locally in your browser using bcryptjs. Your data never leaves your device. +

+
+
+ ); +} \ No newline at end of file diff --git a/src/pages/tools/bcrypt-generator.astro b/src/pages/tools/bcrypt-generator.astro new file mode 100644 index 0000000..72718c7 --- /dev/null +++ b/src/pages/tools/bcrypt-generator.astro @@ -0,0 +1,18 @@ +--- +import BaseLayout from "../../layouts/BaseLayout.astro"; +import BcryptGeneratorTool from "../../features/bcrypt-generator/BcryptGeneratorTool"; +--- + + +
+

Bcrypt Generator & Validator

+

+ Generate bcrypt hashes with configurable salt rounds and validate plaintext against existing hashes. Runs entirely in your browser. +

+
+ + +
\ No newline at end of file