UNPKG

@bitblit/ratchet-common

Version:

Common tools for general use

56 lines 2.57 kB
import { RequireRatchet } from "./require-ratchet.js"; import { NumberRatchet } from "./number-ratchet.js"; import { Base64Ratchet } from "./base64-ratchet.js"; export class SimpleEncryptionRatchet { urlSafe; ivLength; sharedKey; constructor(sharedRawKey, urlSafe = false, ivLength = 12) { this.urlSafe = urlSafe; this.ivLength = ivLength; RequireRatchet.notNullOrUndefined(sharedRawKey); RequireRatchet.true(ivLength >= 12, 'ivLength must be at least 12'); this.sharedKey = this.createSharedKey(sharedRawKey); } strToBuf(str) { return new TextEncoder().encode(str); } bufToBase64(buf) { return btoa(String.fromCharCode(...new Uint8Array(buf))); } base64ToBuf(base64) { return new Uint8Array(atob(base64).split('').map(c => c.charCodeAt(0))); } async encrypt(data) { const iv = crypto.getRandomValues(new Uint8Array(this.ivLength)); const encoded = this.strToBuf(data); const key = await this.sharedKey; const ciphertext = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, key, encoded); const ivMsg = this.bufToBase64(iv.buffer); const dataMsg = this.bufToBase64(ciphertext); let rval = ivMsg.length + 'K' + ivMsg + dataMsg; if (this.urlSafe) { rval = Base64Ratchet.encodeStringToBase64UrlString(rval); } return rval; } async decrypt(encryptedValueIn) { const encryptedValue = this.urlSafe ? Base64Ratchet.decodeBase64UrlStringToString(encryptedValueIn) : encryptedValueIn; const split = encryptedValue?.indexOf('K'); if (!split || split < 1) { throw new Error('Invalid split : ' + split); } const ivLen = NumberRatchet.safeNumber(encryptedValue.substring(0, split)); const iv = encryptedValue.substring(split + 1, split + 1 + ivLen); const data = encryptedValue.substring(split + 1 + ivLen); const key = await this.sharedKey; const decrypted = await crypto.subtle.decrypt({ name: "AES-GCM", iv: this.base64ToBuf(iv) }, key, this.base64ToBuf(data)); return new TextDecoder().decode(decrypted); } async createSharedKey(rawKeyIn) { const rawKey = typeof rawKeyIn === 'string' ? rawKeyIn : await rawKeyIn; const keyMaterial = this.strToBuf(rawKey.padEnd(32, '0').slice(0, 32)); return crypto.subtle.importKey("raw", keyMaterial, "AES-GCM", false, ["encrypt", "decrypt"]); } } //# sourceMappingURL=simple-encryption-ratchet.js.map