hashmsg 15. Mai 2024
Message Hashing & Encryption
Client-side Message Hashing mit Web Crypto API — SHA-256, AES-GCM Verschlüsselung für sichere E-Mails.
typescriptcryptoweb-apisecurity
SHA-256 Hashing
Browser-native Hashing ohne externe Dependencies via Web Crypto API.
export async function hashMessage(message: string): Promise<string> {
const encoder = new TextEncoder();
const data = encoder.encode(message);
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
const hashArray = Array.from(new Uint8Array(hashBuffer));
return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
}
// Usage
const hash = await hashMessage('Hello World');
// => "a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e"
AES-GCM Verschlüsselung
End-to-End Encryption für Nachrichten mit Key-Derivation aus Passwort.
export async function deriveKey(password: string, salt: Uint8Array): Promise<CryptoKey> {
const encoder = new TextEncoder();
const keyMaterial = await crypto.subtle.importKey(
'raw',
encoder.encode(password),
'PBKDF2',
false,
['deriveKey']
);
return crypto.subtle.deriveKey(
{ name: 'PBKDF2', salt, iterations: 100000, hash: 'SHA-256' },
keyMaterial,
{ name: 'AES-GCM', length: 256 },
false,
['encrypt', 'decrypt']
);
}
export async function encryptMessage(message: string, password: string): Promise<string> {
const salt = crypto.getRandomValues(new Uint8Array(16));
const iv = crypto.getRandomValues(new Uint8Array(12));
const key = await deriveKey(password, salt);
const encoder = new TextEncoder();
const encrypted = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv },
key,
encoder.encode(message)
);
// Pack salt + iv + ciphertext into one base64 string
const packed = new Uint8Array([...salt, ...iv, ...new Uint8Array(encrypted)]);
return btoa(String.fromCharCode(...packed));
}
export async function decryptMessage(packed: string, password: string): Promise<string> {
const data = Uint8Array.from(atob(packed), (c) => c.charCodeAt(0));
const salt = data.slice(0, 16);
const iv = data.slice(16, 28);
const ciphertext = data.slice(28);
const key = await deriveKey(password, salt);
const decrypted = await crypto.subtle.decrypt(
{ name: 'AES-GCM', iv },
key,
ciphertext
);
return new TextDecoder().decode(decrypted);
}