Signed-off-by: ale <ale@manalejandro.com>
Este commit está contenido en:
ale
2025-12-08 21:06:35 +01:00
padre ad7a1cf0a7
commit 8fa586731a
Se han modificado 13 ficheros con 18 adiciones y 65 borrados

1
API.md
Ver fichero

@@ -179,7 +179,6 @@ The API automatically detects hash types based on length and format:
| SHA1 | 40 | `^[a-f0-9]{40}$` |
| SHA256 | 64 | `^[a-f0-9]{64}$` |
| SHA512 | 128 | `^[a-f0-9]{128}$` |
| Bcrypt | 60 | `^\$2[abxy]\$` |
Hashes are case-insensitive.

Ver fichero

@@ -10,12 +10,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
#### Core Features
- Hash search functionality for MD5, SHA1, SHA256, SHA512, and Bcrypt
- Hash search functionality for MD5, SHA1, SHA256, and SHA512
- Hash generation from plaintext input
- Automatic detection of hash types based on length and pattern
- Real-time hash generation with instant results
- Copy to clipboard functionality for all hash values
- Bcrypt verification support
#### Backend
- Elasticsearch integration with configurable endpoint

Ver fichero

@@ -13,7 +13,7 @@
## ✨ Key Features
### 🔍 Hash Search
- Search for MD5, SHA1, SHA256, SHA512, and Bcrypt hashes
- Search for MD5, SHA1, SHA256, and SHA512 hashes
- Automatic hash type detection
- Case-insensitive matching
- Real-time results
@@ -174,7 +174,6 @@ export ELASTICSEARCH_NODE=http://localhost:9200
| SHA1 | 40 | `^[a-f0-9]{40}$` |
| SHA256 | 64 | `^[a-f0-9]{64}$` |
| SHA512 | 128 | `^[a-f0-9]{128}$` |
| Bcrypt | 60 | `^\$2[abxy]\$` |
---
@@ -245,7 +244,6 @@ export ELASTICSEARCH_NODE=http://localhost:9200
## 📈 Future Enhancements
### Planned Features
- Bcrypt hash validation
- Argon2 hash support
- Search history
- Batch lookup

Ver fichero

@@ -25,7 +25,6 @@ npm run index-file -- --help # Show help
| SHA1 | 40 | `5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8` |
| SHA256 | 64 | `5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8` |
| SHA512 | 128 | `b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb9...` |
| Bcrypt | 60 | `$2b$10$N9qo8uLOickgx2ZMRZoMye...` |
## 🔌 API Quick Reference

Ver fichero

@@ -8,7 +8,7 @@ A modern, high-performance hash search and generation tool powered by Elasticsea
## ✨ Features
- 🔍 **Hash Lookup**: Search for MD5, SHA1, SHA256, SHA512, and Bcrypt hashes
- 🔍 **Hash Lookup**: Search for MD5, SHA1, SHA256, and SHA512 hashes
- 🔑 **Hash Generation**: Generate multiple hash types from plaintext
- 💾 **Auto-Indexing**: Automatically stores searched plaintext and hashes
- 📊 **Elasticsearch Backend**: Scalable storage with 10 shards for performance
@@ -274,7 +274,6 @@ npm run lint
| SHA1 | 40 | `^[a-f0-9]{40}$` |
| SHA256 | 64 | `^[a-f0-9]{64}$` |
| SHA512 | 128 | `^[a-f0-9]{128}$` |
| Bcrypt | 60 | `^\$2[abxy]\$` |
## 🚀 Performance

Ver fichero

@@ -8,7 +8,6 @@ interface HashDocument {
sha1: string;
sha256: string;
sha512: string;
bcrypt: string;
created_at?: string;
}
@@ -44,7 +43,7 @@ export async function POST(request: NextRequest) {
index: INDEX_NAME,
query: {
term: {
[hashType]: hashType === 'bcrypt' ? cleanQuery : cleanQueryLower
[hashType]: cleanQueryLower
}
}
});
@@ -66,7 +65,6 @@ export async function POST(request: NextRequest) {
sha1: source.sha1,
sha256: source.sha256,
sha512: source.sha512,
bcrypt: source.bcrypt,
}
};
})
@@ -101,11 +99,10 @@ export async function POST(request: NextRequest) {
sha1: existingDoc.sha1,
sha256: existingDoc.sha256,
sha512: existingDoc.sha512,
bcrypt: existingDoc.bcrypt,
};
} else {
// Plaintext not found, generate hashes and check if any hash already exists
hashes = await generateHashes(cleanQuery);
hashes = generateHashes(cleanQuery);
const hashExistsResponse = await esClient.search<HashDocument>({
index: INDEX_NAME,
@@ -147,7 +144,6 @@ export async function POST(request: NextRequest) {
sha1: hashes.sha1,
sha256: hashes.sha256,
sha512: hashes.sha512,
bcrypt: hashes.bcrypt,
}
});
}

Ver fichero

@@ -14,8 +14,8 @@ const geistMono = Geist_Mono({
export const metadata: Metadata = {
title: "Hasher - Hash Search & Generator",
description: "Search for hashes or generate them from plaintext. Supports MD5, SHA1, SHA256, SHA512, and Bcrypt. Powered by Elasticsearch.",
keywords: ["hash", "md5", "sha1", "sha256", "sha512", "bcrypt", "hash generator", "hash search", "elasticsearch"],
description: "Search for hashes or generate them from plaintext. Supports MD5, SHA1, SHA256, and SHA512. Powered by Elasticsearch.",
keywords: ["hash", "md5", "sha1", "sha256", "sha512", "hash generator", "hash search", "elasticsearch"],
authors: [{ name: "Hasher" }],
creator: "Hasher",
publisher: "Hasher",
@@ -28,7 +28,7 @@ export const metadata: Metadata = {
openGraph: {
type: "website",
title: "Hasher - Hash Search & Generator",
description: "Search for hashes or generate them from plaintext. Supports MD5, SHA1, SHA256, SHA512, and Bcrypt.",
description: "Search for hashes or generate them from plaintext. Supports MD5, SHA1, SHA256, and SHA512.",
siteName: "Hasher",
images: [
{
@@ -42,7 +42,7 @@ export const metadata: Metadata = {
twitter: {
card: "summary",
title: "Hasher - Hash Search & Generator",
description: "Search for hashes or generate them from plaintext. Supports MD5, SHA1, SHA256, SHA512, and Bcrypt.",
description: "Search for hashes or generate them from plaintext. Supports MD5, SHA1, SHA256, and SHA512.",
images: ["/logo.png"],
},
viewport: {

Ver fichero

@@ -15,7 +15,6 @@ interface SearchResult {
sha1: string;
sha256: string;
sha512: string;
bcrypt: string;
};
results?: Array<{
plaintext: string;
@@ -24,7 +23,6 @@ interface SearchResult {
sha1: string;
sha256: string;
sha512: string;
bcrypt: string;
};
}>;
message?: string;
@@ -144,7 +142,7 @@ export default function Home() {
Search for hashes or generate them from plaintext
</p>
<p className="text-sm text-gray-500 mt-2">
Supports MD5, SHA1, SHA256, SHA512, and Bcrypt
Supports MD5, SHA1, SHA256, and SHA512
</p>
{stats && (
<div className="flex items-center justify-center gap-4 mt-4 text-sm text-gray-500">
@@ -214,7 +212,6 @@ export default function Home() {
<HashDisplay label="SHA1" value={result.hashes!.sha1} field="sha1-gen" />
<HashDisplay label="SHA256" value={result.hashes!.sha256} field="sha256-gen" />
<HashDisplay label="SHA512" value={result.hashes!.sha512} field="sha512-gen" />
<HashDisplay label="Bcrypt" value={result.hashes!.bcrypt} field="bcrypt-gen" />
</div>
{result.wasGenerated && (
<div className="mt-6 bg-blue-50 border border-blue-200 rounded-xl p-4">
@@ -260,7 +257,6 @@ export default function Home() {
<HashDisplay label="SHA1" value={item.hashes.sha1} field={`sha1-${idx}`} />
<HashDisplay label="SHA256" value={item.hashes.sha256} field={`sha256-${idx}`} />
<HashDisplay label="SHA512" value={item.hashes.sha512} field={`sha512-${idx}`} />
<HashDisplay label="Bcrypt" value={item.hashes.bcrypt} field={`bcrypt-${idx}`} />
</div>
</div>
))}
@@ -304,7 +300,7 @@ export default function Home() {
</div>
<h3 className="text-xl font-bold text-gray-900 mb-2">Generate Hashes</h3>
<p className="text-gray-600">
Enter any plaintext to instantly generate MD5, SHA1, SHA256, SHA512, and Bcrypt hashes. Results are saved automatically.
Enter any plaintext to instantly generate MD5, SHA1, SHA256, and SHA512 hashes. Results are saved automatically.
</p>
</div>
</div>

Ver fichero

@@ -46,9 +46,6 @@ export const INDEX_MAPPING = {
sha512: {
type: 'keyword' as const
},
bcrypt: {
type: 'keyword' as const
},
created_at: {
type: 'date' as const
}

Ver fichero

@@ -1,5 +1,4 @@
import crypto from 'crypto';
import bcrypt from 'bcrypt';
export interface HashResult {
plaintext: string;
@@ -7,22 +6,18 @@ export interface HashResult {
sha1: string;
sha256: string;
sha512: string;
bcrypt: string;
}
/**
* Generate all common hashes for a given plaintext
*/
export async function generateHashes(plaintext: string): Promise<HashResult> {
const bcryptHash = await bcrypt.hash(plaintext, 10);
export function generateHashes(plaintext: string): HashResult {
return {
plaintext,
md5: crypto.createHash('md5').update(plaintext).digest('hex'),
sha1: crypto.createHash('sha1').update(plaintext).digest('hex'),
sha256: crypto.createHash('sha256').update(plaintext).digest('hex'),
sha512: crypto.createHash('sha512').update(plaintext).digest('hex'),
bcrypt: bcryptHash,
};
}
@@ -52,11 +47,6 @@ export function detectHashType(hash: string): string | null {
return 'sha512';
}
// BCrypt: starts with $2a$, $2b$, $2x$, or $2y$
if (/^\$2[abxy]\$/.test(cleanHash)) {
return 'bcrypt';
}
return null;
}
@@ -66,14 +56,3 @@ export function detectHashType(hash: string): string | null {
export function isHash(input: string): boolean {
return detectHashType(input) !== null;
}
/**
* Verify a plaintext against a bcrypt hash
*/
export async function verifyBcrypt(plaintext: string, hash: string): Promise<boolean> {
try {
return await bcrypt.compare(plaintext, hash);
} catch (_error) {
return false;
}
}

Ver fichero

@@ -39,8 +39,6 @@
},
"dependencies": {
"@elastic/elasticsearch": "^9.2.0",
"@types/bcrypt": "^6.0.0",
"bcrypt": "^6.0.0",
"lucide-react": "^0.555.0",
"next": "15.4.8",
"react": "19.1.2",

Ver fichero

@@ -1,7 +1,7 @@
{
"name": "Hasher - Hash Search & Generator",
"short_name": "Hasher",
"description": "Search for hashes or generate them from plaintext. Supports MD5, SHA1, SHA256, SHA512, and Bcrypt.",
"description": "Search for hashes or generate them from plaintext. Supports MD5, SHA1, SHA256, and SHA512.",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",

Ver fichero

@@ -35,7 +35,6 @@ interface HashDocument {
sha1: string;
sha256: string;
sha512: string;
bcrypt: string;
created_at: string;
}
@@ -157,17 +156,13 @@ function deleteState(stateFile: string): void {
}
}
async function generateHashes(plaintext: string): Promise<HashDocument> {
const bcrypt = await import('bcrypt');
const bcryptHash = await bcrypt.default.hash(plaintext, 10);
function generateHashes(plaintext: string): HashDocument {
return {
plaintext,
md5: crypto.createHash('md5').update(plaintext).digest('hex'),
sha1: crypto.createHash('sha1').update(plaintext).digest('hex'),
sha256: crypto.createHash('sha256').update(plaintext).digest('hex'),
sha512: crypto.createHash('sha512').update(plaintext).digest('hex'),
bcrypt: bcryptHash,
created_at: new Date().toISOString()
};
}
@@ -313,12 +308,10 @@ async function indexFile(filePath: string, batchSize: number, shouldResume: bool
const bulkOperations: any[] = [];
// Generate hashes for all items in batch first
const batchWithHashes = await Promise.all(
batch.map(async (plaintext: string) => ({
plaintext,
hashes: await generateHashes(plaintext)
}))
);
const batchWithHashes = batch.map((plaintext: string) => ({
plaintext,
hashes: generateHashes(plaintext)
}));
if (checkDuplicates) {
// Check which items already exist (by plaintext or any hash)