🎯 Exemples recommandés
Balanced sample collections from various categories for you to explore
Exemples de Cryptographie Web TypeScript
Exemples de cryptographie Web TypeScript incluant le calcul de hachage, le chiffrement symétrique et le codage Base64
💻 Calcul de Hachage typescript
🟢 simple
⭐⭐⭐
Calculer les valeurs de hachage MD5, SHA-1, SHA-256, SHA-384, SHA-512 en utilisant Web Crypto API
⏱️ 20 min
🏷️ typescript, web, cryptography, hash
Prerequisites:
Basic TypeScript, Web Crypto API
// Web TypeScript Hash Calculation Examples
// Using Web Crypto API for secure hash computation
// 1. SHA Hash Calculator
class SHAHashCalculator {
// Calculate SHA-256 hash
async sha256(message: string): Promise<string> {
const encoder = new TextEncoder();
const data = encoder.encode(message);
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
return this.bufferToHex(hashBuffer);
}
// Calculate SHA-384 hash
async sha384(message: string): Promise<string> {
const encoder = new TextEncoder();
const data = encoder.encode(message);
const hashBuffer = await crypto.subtle.digest('SHA-384', data);
return this.bufferToHex(hashBuffer);
}
// Calculate SHA-512 hash
async sha512(message: string): Promise<string> {
const encoder = new TextEncoder();
const data = encoder.encode(message);
const hashBuffer = await crypto.subtle.digest('SHA-512', data);
return this.bufferToHex(hashBuffer);
}
// Calculate SHA-1 hash (for legacy compatibility)
async sha1(message: string): Promise<string> {
const encoder = new TextEncoder();
const data = encoder.encode(message);
const hashBuffer = await crypto.subtle.digest('SHA-1', data);
return this.bufferToHex(hashBuffer);
}
// Convert ArrayBuffer to hex string
private bufferToHex(buffer: ArrayBuffer): string {
const bytes = new Uint8Array(buffer);
return Array.from(bytes)
.map(b => b.toString(16).padStart(2, '0'))
.join('');
}
}
// 2. File Hash Calculator
class FileHashCalculator {
private shaCalculator = new SHAHashCalculator();
// Calculate hash of file
async hashFile(file: File, algorithm: 'SHA-256' | 'SHA-384' | 'SHA-512' = 'SHA-256'): Promise<string> {
const arrayBuffer = await file.arrayBuffer();
const hashBuffer = await crypto.subtle.digest(algorithm, arrayBuffer);
return this.bufferToHex(hashBuffer);
}
// Calculate hash with progress
async hashFileWithProgress(
file: File,
algorithm: 'SHA-256' | 'SHA-384' | 'SHA-512' = 'SHA-256',
onProgress: (progress: number) => void
): Promise<string> {
const chunkSize = 1024 * 1024; // 1MB chunks
let offset = 0;
// For progress tracking, we'll read in chunks
while (offset < file.size) {
const end = Math.min(offset + chunkSize, file.size);
offset = end;
const progress = Math.floor((offset / file.size) * 100);
onProgress(progress);
}
// Actually hash the file
return this.hashFile(file, algorithm);
}
// Calculate multiple hashes
async hashMultipleAlgorithms(file: File): Promise<Record<string, string>> {
const arrayBuffer = await file.arrayBuffer();
const algorithms = ['SHA-256', 'SHA-384', 'SHA-512'] as const;
const hashes: Record<string, string> = {};
for (const algo of algorithms) {
const hashBuffer = await crypto.subtle.digest(algo, arrayBuffer);
hashes[algo] = this.bufferToHex(hashBuffer);
}
return hashes;
}
private bufferToHex(buffer: ArrayBuffer): string {
const bytes = new Uint8Array(buffer);
return Array.from(bytes)
.map(b => b.toString(16).padStart(2, '0'))
.join('');
}
}
// 3. HMAC Calculator
class HMACCalculator {
// Calculate HMAC-SHA256
async hmacSha256(message: string, key: string): Promise<string> {
const encoder = new TextEncoder();
const keyData = encoder.encode(key);
const messageData = encoder.encode(message);
const cryptoKey = await crypto.subtle.importKey(
'raw',
keyData,
{ name: 'HMAC', hash: 'SHA-256' },
false,
['sign']
);
const signature = await crypto.subtle.sign('HMAC', cryptoKey, messageData);
return this.bufferToHex(signature);
}
// Calculate HMAC-SHA512
async hmacSha512(message: string, key: string): Promise<string> {
const encoder = new TextEncoder();
const keyData = encoder.encode(key);
const messageData = encoder.encode(message);
const cryptoKey = await crypto.subtle.importKey(
'raw',
keyData,
{ name: 'HMAC', hash: 'SHA-512' },
false,
['sign']
);
const signature = await crypto.subtle.sign('HMAC', cryptoKey, messageData);
return this.bufferToHex(signature);
}
// Verify HMAC
async verifyHMAC(
message: string,
key: string,
signature: string,
algorithm: 'SHA-256' | 'SHA-512' = 'SHA-256'
): Promise<boolean> {
const encoder = new TextEncoder();
const keyData = encoder.encode(key);
const messageData = encoder.encode(message);
const cryptoKey = await crypto.subtle.importKey(
'raw',
keyData,
{ name: 'HMAC', hash: algorithm },
false,
['verify']
);
const signatureBytes = this.hexToBuffer(signature);
const isValid = await crypto.subtle.verify(
'HMAC',
cryptoKey,
signatureBytes,
messageData
);
return isValid;
}
private bufferToHex(buffer: ArrayBuffer): string {
const bytes = new Uint8Array(buffer);
return Array.from(bytes)
.map(b => b.toString(16).padStart(2, '0'))
.join('');
}
private hexToBuffer(hex: string): Uint8Array {
const bytes = new Uint8Array(hex.length / 2);
for (let i = 0; i < bytes.length; i++) {
bytes[i] = parseInt(hex.substr(i * 2, 2), 16);
}
return bytes;
}
}
// 4. Hash Comparison Utility
class HashComparison {
// Constant-time comparison to prevent timing attacks
static constantTimeCompare(hash1: string, hash2: string): boolean {
if (hash1.length !== hash2.length) {
return false;
}
let result = 0;
for (let i = 0; i < hash1.length; i++) {
result |= hash1.charCodeAt(i) ^ hash2.charCodeAt(i);
}
return result === 0;
}
// Compare hashes (case-insensitive)
static compare(hash1: string, hash2: string): boolean {
return hash1.toLowerCase() === hash2.toLowerCase();
}
// Find matching hash in list
static findMatch(targetHash: string, hashList: string[]): string | null {
const normalized = targetHash.toLowerCase();
for (const hash of hashList) {
if (hash.toLowerCase() === normalized) {
return hash;
}
}
return null;
}
}
// 5. Password Hasher (PBKDF2)
class PasswordHasher {
// Hash password with PBKDF2
async hashPassword(
password: string,
salt?: string,
iterations: number = 100000
): Promise<{ hash: string; salt: string }> {
// Generate salt if not provided
const saltBytes = salt
? this.hexToBuffer(salt)
: crypto.getRandomValues(new Uint8Array(16));
const encoder = new TextEncoder();
const passwordData = encoder.encode(password);
const importedKey = await crypto.subtle.importKey(
'raw',
passwordData,
{ name: 'PBKDF2' },
false,
['deriveBits']
);
const hashBuffer = await crypto.subtle.deriveBits(
{
name: 'PBKDF2',
salt: saltBytes,
iterations: iterations,
hash: 'SHA-256'
},
importedKey,
256
);
return {
hash: this.bufferToHex(hashBuffer),
salt: this.bufferToHex(saltBytes)
};
}
// Verify password
async verifyPassword(
password: string,
hash: string,
salt: string,
iterations: number = 100000
): Promise<boolean> {
const { hash: computedHash } = await this.hashPassword(password, salt, iterations);
return HashComparison.constantTimeCompare(hash, computedHash);
}
// Hash password with custom parameters
async hashPasswordAdvanced(
password: string,
options: {
saltLength?: number;
iterations?: number;
hashLength?: number;
} = {}
): Promise<{ hash: string; salt: string; iterations: number }> {
const {
saltLength = 16,
iterations = 100000,
hashLength = 32
} = options;
const saltBytes = crypto.getRandomValues(new Uint8Array(saltLength));
const encoder = new TextEncoder();
const passwordData = encoder.encode(password);
const importedKey = await crypto.subtle.importKey(
'raw',
passwordData,
{ name: 'PBKDF2' },
false,
['deriveBits']
);
const hashBuffer = await crypto.subtle.deriveBits(
{
name: 'PBKDF2',
salt: saltBytes,
iterations: iterations,
hash: 'SHA-256'
},
importedKey,
hashLength * 8
);
return {
hash: this.bufferToHex(hashBuffer),
salt: this.bufferToHex(saltBytes),
iterations
};
}
private bufferToHex(buffer: ArrayBuffer): string {
const bytes = new Uint8Array(buffer);
return Array.from(bytes)
.map(b => b.toString(16).padStart(2, '0'))
.join('');
}
private hexToBuffer(hex: string): Uint8Array {
const bytes = new Uint8Array(hex.length / 2);
for (let i = 0; i < bytes.length; i++) {
bytes[i] = parseInt(hex.substr(i * 2, 2), 16);
}
return bytes;
}
}
// 6. Checksum Calculator
class ChecksumCalculator {
// Simple checksum (sum of bytes)
calculateSimpleChecksum(data: string): number {
const encoder = new TextEncoder();
const bytes = encoder.encode(data);
let sum = 0;
for (const byte of bytes) {
sum += byte;
}
return sum & 0xFF; // Keep only lowest byte
}
// XOR checksum
calculateXORChecksum(data: string): number {
const encoder = new TextEncoder();
const bytes = encoder.encode(data);
let checksum = 0;
for (const byte of bytes) {
checksum ^= byte;
}
return checksum;
}
// CRC-32 checksum
calculateCRC32(data: string): number {
const encoder = new TextEncoder();
const bytes = encoder.encode(data);
let crc = 0xFFFFFFFF;
for (const byte of bytes) {
crc ^= byte;
for (let i = 0; i < 8; i++) {
if (crc & 1) {
crc = (crc >>> 1) ^ 0xEDB88320;
} else {
crc = crc >>> 1;
}
}
}
return (crc ^ 0xFFFFFFFF) >>> 0;
}
// Adler-32 checksum
calculateAdler32(data: string): number {
const encoder = new TextEncoder();
const bytes = encoder.encode(data);
let a = 1;
let b = 0;
for (const byte of bytes) {
a = (a + byte) % 65521;
b = (b + a) % 65521;
}
return (b << 16) | a;
}
}
// 7. Hash Utility Functions
class HashUtils {
// Generate random hash
static async generateRandomHash(algorithm: 'SHA-256' | 'SHA-384' | 'SHA-512' = 'SHA-256'): Promise<string> {
const randomBytes = crypto.getRandomValues(new Uint8Array(32));
const hashBuffer = await crypto.subtle.digest(algorithm, randomBytes);
return HashUtils.bufferToHex(hashBuffer);
}
// Generate hash from multiple inputs
static async combineHashes(hashes: string[]): Promise<string> {
const combined = hashes.join('');
const encoder = new TextEncoder();
const data = encoder.encode(combined);
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
return HashUtils.bufferToHex(hashBuffer);
}
// Hash object (JSON)
static async hashObject(obj: any): Promise<string> {
const json = JSON.stringify(obj);
const encoder = new TextEncoder();
const data = encoder.encode(json);
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
return HashUtils.bufferToHex(hashBuffer);
}
private static bufferToHex(buffer: ArrayBuffer): string {
const bytes = new Uint8Array(buffer);
return Array.from(bytes)
.map(b => b.toString(16).padStart(2, '0'))
.join('');
}
}
// Usage Examples
async function demonstrateHashCalculation() {
console.log('=== Web TypeScript Hash Calculation Examples ===\n');
const shaCalc = new SHAHashCalculator();
const hmacCalc = new HMACCalculator();
const passwordHasher = new PasswordHasher();
const checksumCalc = new ChecksumCalculator();
// 1. SHA hashes
console.log('--- 1. SHA Hashes ---');
const message = 'Hello, World!';
const sha256 = await shaCalc.sha256(message);
const sha384 = await shaCalc.sha384(message);
const sha512 = await shaCalc.sha512(message);
console.log(`SHA-256: ${sha256}`);
console.log(`SHA-384: ${sha384}`);
console.log(`SHA-512: ${sha512}`);
// 2. HMAC
console.log('\n--- 2. HMAC ---');
const key = 'secret-key';
const hmac = await hmacCalc.hmacSha256(message, key);
console.log(`HMAC-SHA256: ${hmac}`);
const verified = await hmacCalc.verifyHMAC(message, key, hmac);
console.log(`Verified: ${verified}`);
// 3. Password hashing
console.log('\n--- 3. Password Hashing ---');
const password = 'MySecurePassword123!';
const { hash: pwdHash, salt } = await passwordHasher.hashPassword(password);
console.log(`Password hash: ${pwdHash}`);
console.log(`Salt: ${salt}`);
const isValid = await passwordHasher.verifyPassword(password, pwdHash, salt);
console.log(`Password valid: ${isValid}`);
// 4. Checksums
console.log('\n--- 4. Checksums ---');
const data = 'The quick brown fox jumps over the lazy dog';
console.log(`Simple checksum: ${checksumCalc.calculateSimpleChecksum(data)}`);
console.log(`XOR checksum: ${checksumCalc.calculateXORChecksum(data)}`);
console.log(`CRC-32: ${checksumCalc.calculateCRC32(data)}`);
console.log(`Adler-32: ${checksumCalc.calculateAdler32(data)}`);
// 5. Hash utilities
console.log('\n--- 5. Hash Utilities ---');
const randomHash = await HashUtils.generateRandomHash();
console.log(`Random hash: ${randomHash}`);
const objHash = await HashUtils.hashObject({ name: 'Alice', age: 30 });
console.log(`Object hash: ${objHash}`);
console.log('\n=== All Hash Calculation Examples Completed ===');
}
// Export functions
export { SHAHashCalculator, FileHashCalculator, HMACCalculator, HashComparison, PasswordHasher, ChecksumCalculator, HashUtils };
export { demonstrateHashCalculation };
💻 Codage Base64 typescript
🟢 simple
⭐⭐
Coder/décoder des données depuis/vers le format Base64 avec support pour Unicode et les données binaires
⏱️ 15 min
🏷️ typescript, web, cryptography, base64
Prerequisites:
Basic TypeScript, Base64 encoding
// Web TypeScript Base64 Encoding Examples
// Encoding and decoding data to/from Base64 format
// 1. Basic Base64 Encoder/Decoder
class Base64Coder {
// Encode string to Base64
encode(input: string): string {
const encoder = new TextEncoder();
const bytes = encoder.encode(input);
return this.bufferToBase64(bytes);
}
// Decode Base64 to string
decode(input: string): string {
const bytes = this.base64ToBuffer(input);
const decoder = new TextDecoder();
return decoder.decode(bytes);
}
// Encode Uint8Array to Base64
encodeBytes(bytes: Uint8Array): string {
return this.bufferToBase64(bytes);
}
// Decode Base64 to Uint8Array
decodeBytes(input: string): Uint8Array {
return this.base64ToBuffer(input);
}
// Convert ArrayBuffer/Base64 to Base64 string
private bufferToBase64(buffer: ArrayBuffer | Uint8Array): string {
const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
let binary = '';
for (const byte of bytes) {
binary += String.fromCharCode(byte);
}
return btoa(binary);
}
// Convert Base64 string to Uint8Array
private base64ToBuffer(base64: string): Uint8Array {
const binary = atob(base64);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
return bytes;
}
}
// 2. URL-Safe Base64 Encoder/Decoder
class URLSafeBase64Coder {
// Encode to URL-safe Base64
encode(input: string): string {
const base64 = btoa(input);
return this.makeURLSafe(base64);
}
// Decode from URL-safe Base64
decode(input: string): string {
const base64 = this.makeStandard(input);
return atob(base64);
}
// Encode bytes to URL-safe Base64
encodeBytes(bytes: Uint8Array): string {
const base64 = this.bufferToBase64(bytes);
return this.makeURLSafe(base64);
}
// Decode URL-safe Base64 to bytes
decodeBytes(input: string): Uint8Array {
const base64 = this.makeStandard(input);
return this.base64ToBuffer(base64);
}
// Convert to URL-safe format
private makeURLSafe(base64: string): string {
return base64
.replace(/\+/g, '-')
.replace(///g, '_')
.replace(/=/g, '');
}
// Convert to standard format
private makeStandard(urlSafe: string): string {
let base64 = urlSafe
.replace(/-/g, '+')
.replace(/_/g, '/');
// Add padding
while (base64.length % 4) {
base64 += '=';
}
return base64;
}
private bufferToBase64(buffer: ArrayBuffer | Uint8Array): string {
const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
let binary = '';
for (const byte of bytes) {
binary += String.fromCharCode(byte);
}
return btoa(binary);
}
private base64ToBuffer(base64: string): Uint8Array {
const binary = atob(base64);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
return bytes;
}
}
// 3. Unicode Base64 Encoder/Decoder
class UnicodeBase64Coder {
// Encode Unicode string to Base64
encode(input: string): string {
// Escape Unicode characters
const escaped = encodeURIComponent(input);
const binary = unescape(escaped);
return btoa(binary);
}
// Decode Base64 to Unicode string
decode(input: string): string {
const binary = atob(input);
const escaped = escape(binary);
return decodeURIComponent(escaped);
}
// Encode using UTF-8
encodeUTF8(input: string): string {
const encoder = new TextEncoder();
const bytes = encoder.encode(input);
return this.bufferToBase64(bytes);
}
// Decode using UTF-8
decodeUTF8(input: string): string {
const bytes = this.base64ToBuffer(input);
const decoder = new TextDecoder();
return decoder.decode(bytes);
}
private bufferToBase64(buffer: ArrayBuffer | Uint8Array): string {
const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
let binary = '';
for (const byte of bytes) {
binary += String.fromCharCode(byte);
}
return btoa(binary);
}
private base64ToBuffer(base64: string): Uint8Array {
const binary = atob(base64);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
return bytes;
}
}
// 4. File Base64 Encoder/Decoder
class FileBase64Coder {
// Convert file to Base64
async fileToBase64(file: File): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
const result = reader.result as string;
// Remove data URL prefix (e.g., "data:image/png;base64,")
const base64 = result.split(',')[1];
resolve(base64);
};
reader.onerror = () => reject(reader.error);
reader.readAsDataURL(file);
});
}
// Convert file to Data URL
async fileToDataURL(file: File): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
resolve(reader.result as string);
};
reader.onerror = () => reject(reader.error);
reader.readAsDataURL(file);
});
}
// Convert Base64 to Blob
base64ToBlob(base64: string, mimeType: string = 'application/octet-stream'): Blob {
const bytes = this.base64ToBuffer(base64);
return new Blob([bytes], { type: mimeType });
}
// Convert Base64 to File
base64ToFile(base64: string, fileName: string, mimeType: string = 'application/octet-stream'): File {
const blob = this.base64ToBlob(base64, mimeType);
return new File([blob], fileName, { type: mimeType });
}
// Convert file to Base64 with progress
async fileToBase64WithProgress(
file: File,
onProgress: (progress: number) => void
): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
const result = reader.result as string;
const base64 = result.split(',')[1];
resolve(base64);
};
reader.onerror = () => reject(reader.error);
if (reader.onprogress) {
reader.onprogress = (event) => {
if (event.lengthComputable) {
const progress = Math.floor((event.loaded / event.total) * 100);
onProgress(progress);
}
};
}
reader.readAsDataURL(file);
});
}
private base64ToBuffer(base64: string): Uint8Array {
const binary = atob(base64);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
return bytes;
}
}
// 5. Image Base64 Encoder/Decoder
class ImageBase64Coder {
private fileCoder = new FileBase64Coder();
// Convert image file to Base64
async imageToBase64(file: File): Promise<{
base64: string;
dataURL: string;
mimeType: string;
}> {
const dataURL = await this.fileCoder.fileToDataURL(file);
const base64 = dataURL.split(',')[1];
const mimeType = file.type;
return { base64, dataURL, mimeType };
}
// Convert Base64 to image element
base64ToImage(base64: string, mimeType: string = 'image/png'): Promise<HTMLImageElement> {
return new Promise((resolve, reject) => {
const img = new Image();
const dataURL = `data:${mimeType};base64,${base64}`;
img.onload = () => resolve(img);
img.onerror = () => reject(new Error('Failed to load image'));
img.src = dataURL;
});
}
// Resize image and convert to Base64
async resizeAndEncode(
file: File,
maxWidth: number,
maxHeight: number
): Promise<string> {
const img = await this.fileCoder.fileToDataURL(file);
return new Promise((resolve, reject) => {
const image = new Image();
image.onload = () => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
if (!ctx) {
reject(new Error('Failed to get canvas context'));
return;
}
// Calculate new dimensions
let width = image.width;
let height = image.height;
if (width > maxWidth) {
height = (maxWidth / width) * height;
width = maxWidth;
}
if (height > maxHeight) {
width = (maxHeight / height) * width;
height = maxHeight;
}
canvas.width = width;
canvas.height = height;
ctx.drawImage(image, 0, 0, width, height);
const dataURL = canvas.toDataURL(file.type);
const base64 = dataURL.split(',')[1];
resolve(base64);
};
image.onerror = () => reject(new Error('Failed to load image'));
image.src = img;
});
}
// Get image dimensions from Base64
async getImageDimensions(base64: string): Promise<{
width: number;
height: number;
}> {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => {
resolve({ width: img.width, height: img.height });
};
img.onerror = () => reject(new Error('Failed to load image'));
img.src = `data:image/png;base64,${base64}`;
});
}
}
// 6. Base64 Utility Functions
class Base64Utils {
// Check if string is valid Base64
isValidBase64(str: string): boolean {
try {
return btoa(atob(str)) === str;
} catch (e) {
return false;
}
}
// Get Base64 string length in bytes
getByteLength(base64: string): number {
const padding = (base64.match(/=/g) || []).length;
return (base64.length * 3) / 4 - padding;
}
// Truncate Base64 string
truncate(base64: string, maxLength: number): string {
if (base64.length <= maxLength) {
return base64;
}
return base64.substring(0, maxLength) + '...';
}
// Split Base64 into chunks
chunk(base64: string, chunkSize: number): string[] {
const chunks: string[] = [];
for (let i = 0; i < base64.length; i += chunkSize) {
chunks.push(base64.substring(i, Math.min(i + chunkSize, base64.length)));
}
return chunks;
}
// Concatenate Base64 chunks
concat(chunks: string[]): string {
return chunks.join('');
}
// Calculate Base64 checksum
checksum(base64: string): number {
const bytes = this.base64ToBuffer(base64);
let sum = 0;
for (const byte of bytes) {
sum += byte;
}
return sum & 0xFF;
}
private base64ToBuffer(base64: string): Uint8Array {
const binary = atob(base64);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
return bytes;
}
}
// 7. Base64 Stream Encoder/Decoder
class Base64StreamCoder {
// Encode stream to Base64
async encodeStream(stream: ReadableStream): Promise<string> {
const reader = stream.getReader();
const chunks: Uint8Array[] = [];
while (true) {
const { done, value } = await reader.read();
if (done) break;
chunks.push(value);
}
// Combine all chunks
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
const combined = new Uint8Array(totalLength);
let offset = 0;
for (const chunk of chunks) {
combined.set(chunk, offset);
offset += chunk.length;
}
return this.bufferToBase64(combined);
}
// Decode Base64 to stream
decodeStream(base64: string): ReadableStream {
const bytes = this.base64ToBuffer(base64);
return new ReadableStream({
start(controller) {
controller.enqueue(bytes);
controller.close();
}
});
}
private bufferToBase64(buffer: ArrayBuffer | Uint8Array): string {
const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
let binary = '';
for (const byte of bytes) {
binary += String.fromCharCode(byte);
}
return btoa(binary);
}
private base64ToBuffer(base64: string): Uint8Array {
const binary = atob(base64);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
return bytes;
}
}
// Usage Examples
async function demonstrateBase64Encoding() {
console.log('=== Web TypeScript Base64 Encoding Examples ===\n');
const coder = new Base64Coder();
const urlSafeCoder = new URLSafeBase64Coder();
const unicodeCoder = new UnicodeBase64Coder();
const fileCoder = new FileBase64Coder();
const imageCoder = new ImageBase64Coder();
const utils = new Base64Utils();
// 1. Basic encoding/decoding
console.log('--- 1. Basic Encoding/Decoding ---');
const text = 'Hello, World!';
const encoded = coder.encode(text);
const decoded = coder.decode(encoded);
console.log(`Original: ${text}`);
console.log(`Encoded: ${encoded}`);
console.log(`Decoded: ${decoded}`);
// 2. URL-safe encoding
console.log('\n--- 2. URL-Safe Encoding ---');
const urlSafeEncoded = urlSafeCoder.encode(text);
console.log(`URL-safe encoded: ${urlSafeEncoded}`);
console.log(`URL-safe decoded: ${urlSafeCoder.decode(urlSafeEncoded)}`);
// 3. Unicode encoding
console.log('\n--- 3. Unicode Encoding ---');
const unicodeText = 'Hello, 世界! 🌍';
const unicodeEncoded = unicodeCoder.encodeUTF8(unicodeText);
const unicodeDecoded = unicodeCoder.decodeUTF8(unicodeEncoded);
console.log(`Unicode original: ${unicodeText}`);
console.log(`Unicode encoded: ${unicodeEncoded}`);
console.log(`Unicode decoded: ${unicodeDecoded}`);
// 4. Bytes encoding
console.log('\n--- 4. Bytes Encoding ---');
const bytes = new Uint8Array([72, 101, 108, 108, 111]);
const bytesEncoded = coder.encodeBytes(bytes);
console.log(`Bytes encoded: ${bytesEncoded}`);
// 5. Validation
console.log('\n--- 5. Validation ---');
console.log(`Is valid Base64: ${utils.isValidBase64(encoded)}`);
console.log(`Is invalid Base64: ${utils.isValidBase64('invalid!@#')}`);
// 6. Utility functions
console.log('\n--- 6. Utility Functions ---');
console.log(`Byte length: ${utils.getByteLength(encoded)}`);
console.log(`Truncated: ${utils.truncate(encoded, 10)}`);
console.log(`Checksum: ${utils.checksum(encoded)}`);
// 7. Chunks
console.log('\n--- 7. Chunks ---');
const longText = 'A'.repeat(100);
const longEncoded = coder.encode(longText);
const chunks = utils.chunk(longEncoded, 20);
console.log(`Number of chunks: ${chunks.length}`);
const concatenated = utils.concat(chunks);
console.log(`Concatenated equals original: ${concatenated === longEncoded}`);
console.log('\n=== All Base64 Encoding Examples Completed ===');
}
// Export functions
export { Base64Coder, URLSafeBase64Coder, UnicodeBase64Coder, FileBase64Coder, ImageBase64Coder, Base64Utils, Base64StreamCoder };
export { demonstrateBase64Encoding };
💻 Chiffrement Symétrique typescript
🟡 intermediate
⭐⭐⭐⭐
Chiffrer et déchiffrer des données en utilisant l'algorithme AES-GCM avec Web Crypto API
⏱️ 30 min
🏷️ typescript, web, cryptography, encryption
Prerequisites:
Intermediate TypeScript, Web Crypto API, Cryptography basics
// Web TypeScript Symmetric Encryption Examples
// Using AES-GCM algorithm with Web Crypto API
// 1. AES-GCM Encryptor
class AESGCMEncryptor {
// Generate random key
async generateKey(): Promise<CryptoKey> {
return await crypto.subtle.generateKey(
{
name: 'AES-GCM',
length: 256
},
true,
['encrypt', 'decrypt']
);
}
// Encrypt data
async encrypt(
key: CryptoKey,
data: string,
associatedData?: string
): Promise<{ ciphertext: string; iv: string; tag?: string }> {
const encoder = new TextEncoder();
const encodedData = encoder.encode(data);
// Generate random IV (Initialization Vector)
const iv = crypto.getRandomValues(new Uint8Array(12));
let encryptOptions: any = {
name: 'AES-GCM',
iv: iv
};
// Add associated data if provided (for authenticated encryption)
if (associatedData) {
encryptOptions.additionalData = encoder.encode(associatedData);
}
const encrypted = await crypto.subtle.encrypt(
encryptOptions,
key,
encodedData
);
return {
ciphertext: this.bufferToBase64(encrypted),
iv: this.bufferToHex(iv)
};
}
// Decrypt data
async decrypt(
key: CryptoKey,
ciphertext: string,
iv: string,
associatedData?: string
): Promise<string> {
const encryptedData = this.base64ToBuffer(ciphertext);
const ivBytes = this.hexToBuffer(iv);
let decryptOptions: any = {
name: 'AES-GCM',
iv: ivBytes
};
if (associatedData) {
const encoder = new TextEncoder();
decryptOptions.additionalData = encoder.encode(associatedData);
}
const decrypted = await crypto.subtle.decrypt(
decryptOptions,
key,
encryptedData
);
const decoder = new TextDecoder();
return decoder.decode(decrypted);
}
// Export key to base64
async exportKey(key: CryptoKey): Promise<string> {
const exported = await crypto.subtle.exportKey('raw', key);
return this.bufferToBase64(exported);
}
// Import key from base64
async importKey(keyData: string): Promise<CryptoKey> {
const keyBytes = this.base64ToBuffer(keyData);
return await crypto.subtle.importKey(
'raw',
keyBytes,
{
name: 'AES-GCM',
length: 256
},
true,
['encrypt', 'decrypt']
);
}
// Generate key from password
async deriveKey(
password: string,
salt?: string,
iterations: number = 100000
): Promise<{ key: CryptoKey; salt: string }> {
// Generate salt if not provided
const saltBytes = salt
? this.hexToBuffer(salt)
: crypto.getRandomValues(new Uint8Array(16));
const encoder = new TextEncoder();
const passwordData = encoder.encode(password);
const importedKey = await crypto.subtle.importKey(
'raw',
passwordData,
{ name: 'PBKDF2' },
false,
['deriveKey']
);
const key = await crypto.subtle.deriveKey(
{
name: 'PBKDF2',
salt: saltBytes,
iterations: iterations,
hash: 'SHA-256'
},
importedKey,
{
name: 'AES-GCM',
length: 256
},
true,
['encrypt', 'decrypt']
);
return {
key,
salt: this.bufferToHex(saltBytes)
};
}
private bufferToBase64(buffer: ArrayBuffer): string {
const bytes = new Uint8Array(buffer);
let binary = '';
for (const byte of bytes) {
binary += String.fromCharCode(byte);
}
return btoa(binary);
}
private base64ToBuffer(base64: string): Uint8Array {
const binary = atob(base64);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
return bytes;
}
private bufferToHex(buffer: ArrayBuffer | Uint8Array): string {
const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
return Array.from(bytes)
.map(b => b.toString(16).padStart(2, '0'))
.join('');
}
private hexToBuffer(hex: string): Uint8Array {
const bytes = new Uint8Array(hex.length / 2);
for (let i = 0; i < bytes.length; i++) {
bytes[i] = parseInt(hex.substr(i * 2, 2), 16);
}
return bytes;
}
}
// 2. Encrypted Message Formatter
class EncryptedMessageFormatter {
private encryptor: AESGCMEncryptor;
constructor() {
this.encryptor = new AESGCMEncryptor();
}
// Format encrypted message
formatMessage(
ciphertext: string,
iv: string,
salt?: string
): string {
const message: any = {
ct: ciphertext,
iv: iv
};
if (salt) {
message.salt = salt;
}
return JSON.stringify(message);
}
// Parse encrypted message
parseMessage(message: string): {
ciphertext: string;
iv: string;
salt?: string;
} {
const data = JSON.parse(message);
return {
ciphertext: data.ct,
iv: data.iv,
salt: data.salt
};
}
}
// 3. File Encryptor
class FileEncryptor {
private encryptor = new AESGCMEncryptor();
// Encrypt file
async encryptFile(
key: CryptoKey,
file: File,
chunkSize: number = 1024 * 1024 // 1MB
): Promise<{ encryptedData: Blob; iv: string }> {
const iv = crypto.getRandomValues(new Uint8Array(12));
const encryptedChunks: BlobPart[] = [];
let offset = 0;
while (offset < file.size) {
const end = Math.min(offset + chunkSize, file.size);
const chunk = file.slice(offset, end);
const arrayBuffer = await chunk.arrayBuffer();
const encrypted = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv: iv },
key,
arrayBuffer
);
encryptedChunks.push(new Uint8Array(encrypted));
offset = end;
}
const encryptedBlob = new Blob(encryptedChunks, { type: 'application/octet-stream' });
return {
encryptedData: encryptedBlob,
iv: this.bufferToHex(iv)
};
}
// Decrypt file
async decryptFile(
key: CryptoKey,
encryptedFile: File,
iv: string,
chunkSize: number = 1024 * 1024
): Promise<Blob> {
const ivBytes = this.hexToBuffer(iv);
const decryptedChunks: BlobPart[] = [];
let offset = 0;
while (offset < encryptedFile.size) {
const end = Math.min(offset + chunkSize, encryptedFile.size);
const chunk = encryptedFile.slice(offset, end);
const arrayBuffer = await chunk.arrayBuffer();
const decrypted = await crypto.subtle.decrypt(
{ name: 'AES-GCM', iv: ivBytes },
key,
arrayBuffer
);
decryptedChunks.push(new Uint8Array(decrypted));
offset = end;
}
return new Blob(decryptedChunks, { type: 'application/octet-stream' });
}
// Encrypt file with progress
async encryptFileWithProgress(
key: CryptoKey,
file: File,
onProgress: (progress: number) => void
): Promise<{ encryptedData: Blob; iv: string }> {
const iv = crypto.getRandomValues(new Uint8Array(12));
const chunkSize = 1024 * 1024;
const encryptedChunks: BlobPart[] = [];
let offset = 0;
while (offset < file.size) {
const end = Math.min(offset + chunkSize, file.size);
const chunk = file.slice(offset, end);
const arrayBuffer = await chunk.arrayBuffer();
const encrypted = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv: iv },
key,
arrayBuffer
);
encryptedChunks.push(new Uint8Array(encrypted));
offset = end;
const progress = Math.floor((offset / file.size) * 100);
onProgress(progress);
}
const encryptedBlob = new Blob(encryptedChunks, { type: 'application/octet-stream' });
return {
encryptedData: encryptedBlob,
iv: this.bufferToHex(iv)
};
}
private bufferToHex(buffer: ArrayBuffer | Uint8Array): string {
const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
return Array.from(bytes)
.map(b => b.toString(16).padStart(2, '0'))
.join('');
}
private hexToBuffer(hex: string): Uint8Array {
const bytes = new Uint8Array(hex.length / 2);
for (let i = 0; i < bytes.length; i++) {
bytes[i] = parseInt(hex.substr(i * 2, 2), 16);
}
return bytes;
}
}
// 4. Key Management
class KeyManager {
// Store key in IndexedDB
async storeKey(keyId: string, key: CryptoKey, dbName: string = 'encryptionKeys'): Promise<void> {
return new Promise((resolve, reject) => {
const request = indexedDB.open(dbName, 1);
request.onerror = () => reject(request.error);
request.onsuccess = () => {
const db = request.result;
const transaction = db.transaction(['keys'], 'readwrite');
const store = transaction.objectStore('keys');
const encryptor = new AESGCMEncryptor();
encryptor.exportKey(key).then(exportedKey => {
store.put({ id: keyId, keyData: exportedKey, created: Date.now() });
transaction.oncomplete = () => resolve();
transaction.onerror = () => reject(transaction.error);
});
};
request.onupgradeneeded = (event) => {
const db = (event.target as IDBOpenDBRequest).result;
if (!db.objectStoreNames.contains('keys')) {
db.createObjectStore('keys', { keyPath: 'id' });
}
};
});
}
// Retrieve key from IndexedDB
async retrieveKey(keyId: string, dbName: string = 'encryptionKeys'): Promise<CryptoKey | null> {
return new Promise((resolve, reject) => {
const request = indexedDB.open(dbName, 1);
request.onerror = () => reject(request.error);
request.onsuccess = () => {
const db = request.result;
const transaction = db.transaction(['keys'], 'readonly');
const store = transaction.objectStore('keys');
const getRequest = store.get(keyId);
getRequest.onsuccess = async () => {
const data = getRequest.result;
if (data) {
const encryptor = new AESGCMEncryptor();
const key = await encryptor.importKey(data.keyData);
resolve(key);
} else {
resolve(null);
}
};
getRequest.onerror = () => reject(getRequest.error);
};
request.onupgradeneeded = (event) => {
const db = (event.target as IDBOpenDBRequest).result;
if (!db.objectStoreNames.contains('keys')) {
db.createObjectStore('keys', { keyPath: 'id' });
}
};
});
}
// Delete key from storage
async deleteKey(keyId: string, dbName: string = 'encryptionKeys'): Promise<void> {
return new Promise((resolve, reject) => {
const request = indexedDB.open(dbName, 1);
request.onerror = () => reject(request.error);
request.onsuccess = () => {
const db = request.result;
const transaction = db.transaction(['keys'], 'readwrite');
const store = transaction.objectStore('keys');
store.delete(keyId);
transaction.oncomplete = () => resolve();
transaction.onerror = () => reject(transaction.error);
};
});
}
// List all stored key IDs
async listKeys(dbName: string = 'encryptionKeys'): Promise<string[]> {
return new Promise((resolve, reject) => {
const request = indexedDB.open(dbName, 1);
request.onerror = () => reject(request.error);
request.onsuccess = () => {
const db = request.result;
const transaction = db.transaction(['keys'], 'readonly');
const store = transaction.objectStore('keys');
const getAllRequest = store.getAllKeys();
getAllRequest.onsuccess = () => {
resolve(getAllRequest.result as string[]);
};
getAllRequest.onerror = () => reject(getAllRequest.error);
};
});
}
}
// 5. Secure Messaging
class SecureMessaging {
private encryptor = new AESGCMEncryptor();
private formatter = new EncryptedMessageFormatter();
// Send secure message
async sendMessage(
recipientKey: CryptoKey,
message: string,
associatedData?: string
): Promise<string> {
const encrypted = await this.encryptor.encrypt(
recipientKey,
message,
associatedData
);
return this.formatter.formatMessage(
encrypted.ciphertext,
encrypted.iv
);
}
// Receive secure message
async receiveMessage(
privateKey: CryptoKey,
encryptedMessage: string,
associatedData?: string
): Promise<string> {
const parsed = this.formatter.parseMessage(encryptedMessage);
return await this.encryptor.decrypt(
privateKey,
parsed.ciphertext,
parsed.iv,
associatedData
);
}
// Create secure conversation
async createConversation(): Promise<{
key: CryptoKey;
keyData: string;
}> {
const key = await this.encryptor.generateKey();
const keyData = await this.encryptor.exportKey(key);
return { key, keyData };
}
}
// Usage Examples
async function demonstrateSymmetricEncryption() {
console.log('=== Web TypeScript Symmetric Encryption Examples ===\n');
const encryptor = new AESGCMEncryptor();
const fileEncryptor = new FileEncryptor();
const keyManager = new KeyManager();
const messaging = new SecureMessaging();
// 1. Generate key
console.log('--- 1. Generate Key ---');
const key = await encryptor.generateKey();
const keyData = await encryptor.exportKey(key);
console.log(`Key: ${keyData.substring(0, 32)}...`);
// 2. Encrypt/Decrypt message
console.log('\n--- 2. Encrypt/Decrypt Message ---');
const message = 'This is a secret message!';
const encrypted = await encryptor.encrypt(key, message);
console.log(`Encrypted: ${encrypted.ciphertext.substring(0, 32)}...`);
const decrypted = await encryptor.decrypt(key, encrypted.ciphertext, encrypted.iv);
console.log(`Decrypted: ${decrypted}`);
// 3. Encrypt with associated data
console.log('\n--- 3. Encrypt with Associated Data ---');
const aad = 'user123';
const encryptedAAD = await encryptor.encrypt(key, message, aad);
const decryptedAAD = await encryptor.decrypt(
key,
encryptedAAD.ciphertext,
encryptedAAD.iv,
aad
);
console.log(`With AAD: ${decryptedAAD}`);
// 4. Derive key from password
console.log('\n--- 4. Derive Key from Password ---');
const password = 'MySecurePassword';
const { key: derivedKey, salt } = await encryptor.deriveKey(password);
const derivedEncrypted = await encryptor.encrypt(derivedKey, message);
console.log(`Derived key encrypted: ${derivedEncrypted.ciphertext.substring(0, 32)}...`);
// 5. Key management
console.log('\n--- 5. Key Management ---');
await keyManager.storeKey('test-key', key);
const retrievedKey = await keyManager.retrieveKey('test-key');
console.log(`Key retrieved: ${retrievedKey ? 'Yes' : 'No'}`);
const keyIds = await keyManager.listKeys();
console.log(`Stored keys: ${keyIds.join(', ')}`);
// 6. Secure messaging
console.log('\n--- 6. Secure Messaging ---');
const secureMsg = await messaging.sendMessage(key, 'Hello, secure world!');
console.log(`Secure message: ${secureMsg.substring(0, 50)}...`);
const receivedMsg = await messaging.receiveMessage(key, secureMsg);
console.log(`Received: ${receivedMsg}`);
console.log('\n=== All Symmetric Encryption Examples Completed ===');
}
// Export functions
export { AESGCMEncryptor, EncryptedMessageFormatter, FileEncryptor, KeyManager, SecureMessaging };
export { demonstrateSymmetricEncryption };