secureweb/sweb/src/services/content-processor.service.ts
Mahmoud Emad 773fd2e2bf feat: Add implementation details and dependencies
- Added a detailed implementation status report (impl.md).
- Added the `@noble/hashes` dependency for Blake3 hashing.
- Updated package.json and pnpm-lock.yaml accordingly.
- Created a new component for Blake3 hashing demo.
2025-05-13 10:42:18 +03:00

169 lines
6.0 KiB
TypeScript

/**
* Content Processing Service
* Implements the content processing pipeline as described in the specs
* Uses Blake hashing for content integrity and encryption key generation
*/
import { cryptoService } from './crypto.service';
import { ipfsService } from './ipfs.service';
/**
* Interface for processed content metadata
*/
interface ProcessedContentMetadata {
originalFilename: string;
normalizedFilename: string;
blakeHash: string;
ipfsCid: string;
combinedKey: string;
contentType: string;
size: number;
timestamp: number;
}
/**
* Service for processing content files
* Implements the content processing pipeline:
* 1. File discovery
* 2. Filename normalization
* 3. Original content hashing (Blake)
* 4. Content encryption
* 5. Encrypted content upload to IPFS
*/
class ContentProcessorService {
/**
* Process a file through the content processing pipeline
* @param file - File to process
* @returns Promise<ProcessedContentMetadata> - Metadata of the processed content
*/
async processFile(file: File): Promise<ProcessedContentMetadata> {
try {
// Step 1: Get file information
const originalFilename = file.name;
// Step 2: Normalize filename (lowercase and snake_case)
const normalizedFilename = this.normalizeFilename(originalFilename);
// Step 3: Hash the original content using Blake3
const blakeHash = await cryptoService.hashFileBlake3AsHex(file);
// Step 4: Encrypt the content using the Blake hash as the key
// Note: This is a placeholder for actual encryption implementation
const encryptedContent = await this.encryptContent(file, blakeHash);
// Step 5: Upload the encrypted content to IPFS
const ipfsCid = await ipfsService.uploadContent(encryptedContent);
// Create the combined key (Blake hash + IPFS CID)
const combinedKey = cryptoService.combineBlakeHashAndIpfsCid(blakeHash, ipfsCid);
// Return the metadata
return {
originalFilename,
normalizedFilename,
blakeHash,
ipfsCid,
combinedKey,
contentType: file.type,
size: file.size,
timestamp: Date.now()
};
} catch (error) {
console.error('Error processing file:', error);
throw error;
}
}
/**
* Normalize a filename to lowercase and snake_case
* @param filename - Original filename
* @returns Normalized filename
*/
normalizeFilename(filename: string): string {
// Remove file extension
const parts = filename.split('.');
const extension = parts.pop() || '';
let name = parts.join('.');
// Convert to lowercase
name = name.toLowerCase();
// Replace spaces and special characters with underscores
name = name.replace(/[^a-z0-9]/g, '_');
// Replace multiple underscores with a single one
name = name.replace(/_+/g, '_');
// Remove leading and trailing underscores
name = name.replace(/^_+|_+$/g, '');
// Add extension back if it exists
if (extension) {
name = `${name}.${extension.toLowerCase()}`;
}
return name;
}
/**
* Encrypt content using the Blake hash as the key
* This is a placeholder for actual encryption implementation
* @param file - File to encrypt
* @param key - Encryption key (Blake hash)
* @returns Promise<string> - Encrypted content as string
*/
async encryptContent(file: File, key: string): Promise<string> {
// TODO: Implement actual encryption
// For now, we'll just return a mock encrypted content
// This should be replaced with actual encryption using the Blake hash as the key
// Convert the file to a string
const arrayBuffer = await file.arrayBuffer();
const contentBytes = new Uint8Array(arrayBuffer);
// Mock encryption by XORing with the key bytes
// This is NOT secure and is only for demonstration purposes
const keyBytes = cryptoService.hexToBytes(key);
const encryptedBytes = new Uint8Array(contentBytes.length);
for (let i = 0; i < contentBytes.length; i++) {
encryptedBytes[i] = contentBytes[i] ^ keyBytes[i % keyBytes.length];
}
// Convert to base64 for storage
return btoa(String.fromCharCode.apply(null, Array.from(encryptedBytes)));
}
/**
* Decrypt content using the Blake hash as the key
* This is a placeholder for actual decryption implementation
* @param encryptedContent - Encrypted content as string
* @param key - Decryption key (Blake hash)
* @returns Promise<Uint8Array> - Decrypted content as Uint8Array
*/
async decryptContent(encryptedContent: string, key: string): Promise<Uint8Array> {
// TODO: Implement actual decryption
// For now, we'll just return a mock decrypted content
// This should be replaced with actual decryption using the Blake hash as the key
// Convert the base64 string to bytes
const encryptedBytes = new Uint8Array(
atob(encryptedContent).split('').map(c => c.charCodeAt(0))
);
// Mock decryption by XORing with the key bytes
// This is NOT secure and is only for demonstration purposes
const keyBytes = cryptoService.hexToBytes(key);
const decryptedBytes = new Uint8Array(encryptedBytes.length);
for (let i = 0; i < encryptedBytes.length; i++) {
decryptedBytes[i] = encryptedBytes[i] ^ keyBytes[i % keyBytes.length];
}
return decryptedBytes;
}
}
// Create a singleton instance
export const contentProcessorService = new ContentProcessorService();