Skip to content

Instantly share code, notes, and snippets.

@AvocadoVenom
Created February 9, 2023 10:05
Show Gist options
  • Save AvocadoVenom/983124aa397accc864360bf896eb978b to your computer and use it in GitHub Desktop.
Save AvocadoVenom/983124aa397accc864360bf896eb978b to your computer and use it in GitHub Desktop.
A wrapper service for SubtleCrypto Browser API
import TextManipulationHelper from './text-manipulation';
import type { CryptographyManager, EncryptionKeyManager, EncryptionPayload } from './cryptography.model';
class CryptographyService<T extends AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params = AesKeyGenParams>
implements EncryptionKeyManager, CryptographyManager
{
public readonly algorithm: T;
constructor(algo: T) {
// See: https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts
if (window.isSecureContext) this.algorithm = algo;
else throw new Error('Impossible to use cryptography service due to non-secured context');
}
// IV: Initial Vector
public generateIv = (): Uint8Array => window.crypto.getRandomValues(new Uint8Array(12));
// Encryption Key
private generateKey = async (): Promise<CryptoKey> =>
window.crypto.subtle.generateKey(this.algorithm, true, ['encrypt', 'decrypt']);
public parseKey = async (key: ArrayBuffer) =>
window.crypto.subtle.importKey('raw', key, this.algorithm, true, ['encrypt', 'decrypt']);
public readKey = async (key: CryptoKey): Promise<ArrayBuffer> => window.crypto.subtle.exportKey('raw', key);
// Data encryption
public encrypt = async (data: string): Promise<EncryptionPayload> => {
const cryptoKey = await this.generateKey();
const encoded = TextManipulationHelper.encode(data);
const iv = this.generateIv();
const algo = { ...this.algorithm, iv };
const cipher = await window.crypto.subtle.encrypt(algo, cryptoKey, encoded);
const key = await this.readKey(cryptoKey);
return { key, cipher, iv };
}
// Data decryption
public decrypt = async (cipher: ArrayBuffer, key: CryptoKey, iv: Uint8Array): Promise<string> => {
const algo = { ...this.algorithm, iv };
const encoded: ArrayBuffer = await window.crypto.subtle.decrypt(algo, key, cipher);
return TextManipulationHelper.decode(encoded);
}
}
const AES_CGM_ALGORITHM: AesKeyGenParams = { name: 'AES-GCM', length: 256 };
export default new CryptographyService(AES_CGM_ALGORITHM);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment