initial commit

Signed-off-by: ale <ale@manalejandro.com>
Este commit está contenido en:
ale
2025-12-04 00:58:40 +01:00
padre d0c05d13b1
commit 1b51f5a171
Se han modificado 18 ficheros con 3013 adiciones y 6626 borrados

78
lib/elasticsearch.ts Archivo normal
Ver fichero

@@ -0,0 +1,78 @@
import { Client } from '@elastic/elasticsearch';
const ELASTICSEARCH_NODE = process.env.ELASTICSEARCH_NODE || 'http://localhost:9200';
const INDEX_NAME = 'hasher';
export const esClient = new Client({
node: ELASTICSEARCH_NODE,
requestTimeout: 30000,
maxRetries: 3,
});
export const INDEX_MAPPING = {
settings: {
number_of_shards: 10,
number_of_replicas: 1,
analysis: {
analyzer: {
lowercase_analyzer: {
type: 'custom',
tokenizer: 'keyword',
filter: ['lowercase']
}
}
}
},
mappings: {
properties: {
plaintext: {
type: 'text',
analyzer: 'lowercase_analyzer',
fields: {
keyword: {
type: 'keyword'
}
}
},
md5: {
type: 'keyword'
},
sha1: {
type: 'keyword'
},
sha256: {
type: 'keyword'
},
sha512: {
type: 'keyword'
},
bcrypt: {
type: 'keyword'
},
created_at: {
type: 'date'
}
}
}
};
export async function initializeIndex(): Promise<void> {
try {
const indexExists = await esClient.indices.exists({ index: INDEX_NAME });
if (!indexExists) {
await esClient.indices.create({
index: INDEX_NAME,
...INDEX_MAPPING
} as any);
console.log(`Index '${INDEX_NAME}' created successfully with 10 shards`);
} else {
console.log(`Index '${INDEX_NAME}' already exists`);
}
} catch (error) {
console.error('Error initializing Elasticsearch index:', error);
throw error;
}
}
export { INDEX_NAME };

79
lib/hash.ts Archivo normal
Ver fichero

@@ -0,0 +1,79 @@
import crypto from 'crypto';
import bcrypt from 'bcrypt';
export interface HashResult {
plaintext: string;
md5: string;
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);
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,
};
}
/**
* Detect hash type based on length and format
*/
export function detectHashType(hash: string): string | null {
const cleanHash = hash.trim().toLowerCase();
// MD5: 32 hex characters
if (/^[a-f0-9]{32}$/i.test(cleanHash)) {
return 'md5';
}
// SHA1: 40 hex characters
if (/^[a-f0-9]{40}$/i.test(cleanHash)) {
return 'sha1';
}
// SHA256: 64 hex characters
if (/^[a-f0-9]{64}$/i.test(cleanHash)) {
return 'sha256';
}
// SHA512: 128 hex characters
if (/^[a-f0-9]{128}$/i.test(cleanHash)) {
return 'sha512';
}
// BCrypt: starts with $2a$, $2b$, $2x$, or $2y$
if (/^\$2[abxy]\$/.test(cleanHash)) {
return 'bcrypt';
}
return null;
}
/**
* Check if a string is a valid hash
*/
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;
}
}