Created
February 9, 2023 10:05
-
-
Save AvocadoVenom/983124aa397accc864360bf896eb978b to your computer and use it in GitHub Desktop.
A wrapper service for SubtleCrypto Browser API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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