UNPKG

@coinbase/wallet-sdk

Version:
68 lines 3.29 kB
// Copyright (c) 2018-2023 Coinbase, Inc. <https://www.coinbase.com/> import { hexStringToUint8Array, uint8ArrayToHex } from '../../../../core/type/util.js'; export class WalletLinkCipher { // @param secret hex representation of 32-byte secret constructor(secret) { this.secret = secret; } /** * * @param plainText string to be encrypted * returns hex string representation of bytes in the order: initialization vector (iv), * auth tag, encrypted plaintext. IV is 12 bytes. Auth tag is 16 bytes. Remaining bytes are the * encrypted plainText. */ async encrypt(plainText) { const secret = this.secret; if (secret.length !== 64) throw Error(`secret must be 256 bits`); const ivBytes = crypto.getRandomValues(new Uint8Array(12)); const secretKey = await crypto.subtle.importKey('raw', hexStringToUint8Array(secret), { name: 'aes-gcm' }, false, ['encrypt', 'decrypt']); const enc = new TextEncoder(); // Will return encrypted plainText with auth tag (ie MAC or checksum) appended at the end const encryptedResult = await window.crypto.subtle.encrypt({ name: 'AES-GCM', iv: ivBytes, }, secretKey, enc.encode(plainText)); const tagLength = 16; const authTag = encryptedResult.slice(encryptedResult.byteLength - tagLength); const encryptedPlaintext = encryptedResult.slice(0, encryptedResult.byteLength - tagLength); const authTagBytes = new Uint8Array(authTag); const encryptedPlaintextBytes = new Uint8Array(encryptedPlaintext); const concatted = new Uint8Array([...ivBytes, ...authTagBytes, ...encryptedPlaintextBytes]); return uint8ArrayToHex(concatted); } /** * * @param cipherText hex string representation of bytes in the order: initialization vector (iv), * auth tag, encrypted plaintext. IV is 12 bytes. Auth tag is 16 bytes. */ async decrypt(cipherText) { const secret = this.secret; if (secret.length !== 64) throw Error(`secret must be 256 bits`); return new Promise((resolve, reject) => { void (async function () { const secretKey = await crypto.subtle.importKey('raw', hexStringToUint8Array(secret), { name: 'aes-gcm' }, false, ['encrypt', 'decrypt']); const encrypted = hexStringToUint8Array(cipherText); const ivBytes = encrypted.slice(0, 12); const authTagBytes = encrypted.slice(12, 28); const encryptedPlaintextBytes = encrypted.slice(28); const concattedBytes = new Uint8Array([...encryptedPlaintextBytes, ...authTagBytes]); const algo = { name: 'AES-GCM', iv: new Uint8Array(ivBytes), }; try { const decrypted = await window.crypto.subtle.decrypt(algo, secretKey, concattedBytes); const decoder = new TextDecoder(); resolve(decoder.decode(decrypted)); } catch (err) { reject(err); } })(); }); } } //# sourceMappingURL=WalletLinkCipher.js.map