@coinbase/wallet-sdk
Version:
Coinbase Wallet JavaScript SDK
68 lines • 3.29 kB
JavaScript
// 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