diff --git a/package.json b/package.json index d727bd0..05ff857 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mytaskapplication", - "version": "1.7.0", + "version": "1.7.1", "main": "app.js", "author": { "name": "Maik Roland Damm", diff --git a/src/app/components/task-add/task-add.component.ts b/src/app/components/task-add/task-add.component.ts index ac9db9c..2a41187 100644 --- a/src/app/components/task-add/task-add.component.ts +++ b/src/app/components/task-add/task-add.component.ts @@ -6,6 +6,7 @@ import {DarkModeService} from '../../services/dark-mode.service'; import {NgClass} from '@angular/common'; import {NgbDatepickerModule, NgbTooltip} from '@ng-bootstrap/ng-bootstrap'; import {ModalService} from '../../services/modal.service'; +import {AccountService} from '../../services/account.service'; @Component({ @@ -25,7 +26,8 @@ export class TaskAddComponent { modalService = inject(ModalService) constructor(private tasksService: TasksService, - private darkModeService: DarkModeService) { + private darkModeService: DarkModeService, + private accountService: AccountService) { } get isDarkMode(): boolean { @@ -38,7 +40,90 @@ export class TaskAddComponent { //return new Date(date.getTime() + date.getTimezoneOffset() * 60000); } - addTask(taskDescription:string) { + /** + * Encrypts a string with a given secret key + * @param text The string to encrypt + * @returns Promise with the encrypted string (base64 encoded) + */ + private async encryptTaskDesk(text: string): Promise { + + const secretKey = this.accountService.getSecret() || ''; + + if (!text) return ''; + + try { + // Convert strings to proper format for encryption + const textEncoder = new TextEncoder(); + const encodedText = textEncoder.encode(text); + + // Create a key from the secret + const keyMaterial = await this.getKeyMaterial(secretKey); + const key = await this.deriveKey(keyMaterial); + + // Generate a random initialization vector + const iv = crypto.getRandomValues(new Uint8Array(12)); + + // Encrypt the text + const encryptedContent = await crypto.subtle.encrypt( + { + name: 'AES-GCM', + iv + }, + key, + encodedText + ); + + // Combine the IV and encrypted content into a single array + const encryptedContentArray = new Uint8Array(iv.length + encryptedContent.byteLength); + encryptedContentArray.set(iv, 0); + encryptedContentArray.set(new Uint8Array(encryptedContent), iv.length); + + // Convert to Base64 string for storage + return btoa(String.fromCharCode(...encryptedContentArray)); + } catch (error) { + console.error('Encryption error:', error); + return ''; + } + } + + /** + * Helper function to generate key material from a password + */ + private async getKeyMaterial(password: string): Promise { + const textEncoder = new TextEncoder(); + return await crypto.subtle.importKey( + 'raw', + textEncoder.encode(password), + { name: 'PBKDF2' }, + false, + ['deriveBits', 'deriveKey'] + ); + } + + /** + * Helper function to derive an AES-GCM key from key material + */ + private async deriveKey(keyMaterial: CryptoKey): Promise { + // Use a salt (can be a fixed value as long as it's consistent) + const textEncoder = new TextEncoder(); // Fixed: Define textEncoder here + const salt = textEncoder.encode('this-is-a-fixed-salt'); + + return await crypto.subtle.deriveKey( + { + name: 'PBKDF2', + salt, + iterations: 100000, + hash: 'SHA-256' + }, + keyMaterial, + { name: 'AES-GCM', length: 256 }, + false, + ['encrypt', 'decrypt'] + ); + } + + + async addTask(taskDescription:string) { if(taskDescription.length === 0) { // console.log("Empty task description"); @@ -54,6 +139,8 @@ export class TaskAddComponent { // Convert the datetime string to timestamp (without timezone issues) const timestamp = this.dateStringToTimestamp(this.selectedDateTime); + const encryptedDescription = await this.encryptTaskDesk(taskDescription); + const options = { notify: false, notified: false, @@ -62,7 +149,7 @@ export class TaskAddComponent { let task: Task = { id: new_id, - description: taskDescription, + description: encryptedDescription, completed: false, dueDate: timestamp, options: options,