mirror of
https://github.com/kccleoc/seedpgp-web.git
synced 2026-03-07 09:57:50 +08:00
feat: Add integration tests and memory encryption strategy
This commit is contained in:
@@ -179,6 +179,100 @@ if (typeof document !== 'undefined') {
|
||||
});
|
||||
}
|
||||
|
||||
// --- Encrypted State Utilities ---
|
||||
|
||||
/**
|
||||
* Represents an encrypted state value with decryption capability.
|
||||
* Used internally by useEncryptedState hook.
|
||||
*/
|
||||
export interface EncryptedStateContainer<T> {
|
||||
/**
|
||||
* The encrypted blob containing the value and all necessary metadata.
|
||||
*/
|
||||
blob: EncryptedBlob | null;
|
||||
|
||||
/**
|
||||
* Decrypts and returns the current value.
|
||||
* Throws if key is not available.
|
||||
*/
|
||||
decrypt(): Promise<T>;
|
||||
|
||||
/**
|
||||
* Encrypts a new value and updates the internal blob.
|
||||
*/
|
||||
update(value: T): Promise<void>;
|
||||
|
||||
/**
|
||||
* Clears the encrypted blob from memory.
|
||||
* The value becomes inaccessible until update() is called again.
|
||||
*/
|
||||
clear(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an encrypted state container for storing a value.
|
||||
* The value is always stored encrypted and can only be accessed
|
||||
* by calling decrypt().
|
||||
*
|
||||
* @param initialValue The initial value to encrypt
|
||||
* @returns An EncryptedStateContainer that manages encryption/decryption
|
||||
*
|
||||
* @example
|
||||
* const container = await createEncryptedState({ seed: 'secret' });
|
||||
* const value = await container.decrypt(); // { seed: 'secret' }
|
||||
* await container.update({ seed: 'new-secret' });
|
||||
* container.clear(); // Remove from memory
|
||||
*/
|
||||
export async function createEncryptedState<T>(
|
||||
initialValue: T
|
||||
): Promise<EncryptedStateContainer<T>> {
|
||||
let blob: EncryptedBlob | null = null;
|
||||
|
||||
// Encrypt the initial value
|
||||
if (initialValue !== null && initialValue !== undefined) {
|
||||
blob = await encryptJsonToBlob(initialValue);
|
||||
}
|
||||
|
||||
return {
|
||||
async decrypt(): Promise<T> {
|
||||
if (!blob) {
|
||||
throw new Error('Encrypted state is empty or has been cleared');
|
||||
}
|
||||
return await decryptBlobToJson<T>(blob);
|
||||
},
|
||||
|
||||
async update(value: T): Promise<void> {
|
||||
blob = await encryptJsonToBlob(value);
|
||||
},
|
||||
|
||||
clear(): void {
|
||||
blob = null;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility to safely update encrypted state with a transformation function.
|
||||
* This decrypts the current value, applies a transformation, and re-encrypts.
|
||||
*
|
||||
* @param container The encrypted state container
|
||||
* @param transform Function that receives current value and returns new value
|
||||
*
|
||||
* @example
|
||||
* await updateEncryptedState(container, (current) => ({
|
||||
* ...current,
|
||||
* updated: true
|
||||
* }));
|
||||
*/
|
||||
export async function updateEncryptedState<T>(
|
||||
container: EncryptedStateContainer<T>,
|
||||
transform: (current: T) => T | Promise<T>
|
||||
): Promise<void> {
|
||||
const current = await container.decrypt();
|
||||
const updated = await Promise.resolve(transform(current));
|
||||
await container.update(updated);
|
||||
}
|
||||
|
||||
/**
|
||||
* A standalone test function that can be run in the browser console
|
||||
* to verify the complete encryption and decryption lifecycle.
|
||||
|
||||
Reference in New Issue
Block a user