chaingate
Version:
Multi-chain cryptocurrency SDK for TypeScript — unified API for Bitcoin, Ethereum, Litecoin, Dogecoin, Bitcoin Cash, Polygon, Arbitrum, and any EVM-compatible chain. Create wallets, query balances, send transactions, and manage tokens and NFTs across UTXO
54 lines (53 loc) • 2.74 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.LegacyKeystore = void 0;
const blake2_js_1 = require("@noble/hashes/blake2.js");
const encoding_1 = require("../utils/encoding");
const errors_1 = require("../errors");
/** Legacy (V1) keystore. */
class LegacyKeystore {
constructor(keystoreData) {
this.keystoreData = keystoreData;
}
async checkPassword(password) {
const derivedKey = this._derivedKey ?? (await this.deriveKey(password));
const ciphertext = (0, encoding_1.hexToBytes)(this.keystoreData.crypto.ciphertext);
const combined = new Uint8Array(derivedKey.passwordCheck.length + ciphertext.length);
combined.set(derivedKey.passwordCheck);
combined.set(ciphertext, derivedKey.passwordCheck.length);
const mac = (0, encoding_1.bytesToHex)((0, blake2_js_1.blake2b)(combined, { dkLen: 32 }));
if (mac === this.keystoreData.crypto.mac) {
this._derivedKey = derivedKey;
return true;
}
return false;
}
async deriveKey(password) {
const salt = (0, encoding_1.hexToBytes)(this.keystoreData.crypto.kdfparams.salt);
const iterations = this.keystoreData.crypto.kdfparams.c;
const dkLen = this.keystoreData.crypto.kdfparams.dklen;
const keyMaterial = await crypto.subtle.importKey('raw', new TextEncoder().encode(password), 'PBKDF2', false, ['deriveBits']);
const derivedBits = await crypto.subtle.deriveBits({ name: 'PBKDF2', salt: salt.buffer, iterations, hash: 'SHA-256' }, keyMaterial, dkLen * 8);
const derivedKeyRaw = new Uint8Array(derivedBits);
return {
decryptKey: derivedKeyRaw.slice(0, 16),
passwordCheck: derivedKeyRaw.slice(16, 32),
};
}
async decrypt(password) {
const derivedKey = this._derivedKey ?? (await this.deriveKey(password));
if (!(await this.checkPassword(password))) {
throw new errors_1.IncorrectKeystorePasswordError();
}
const iv = (0, encoding_1.hexToBytes)(this.keystoreData.crypto.cipherparams.iv);
const encryptedData = (0, encoding_1.hexToBytes)(this.keystoreData.crypto.ciphertext);
const cryptoKey = await crypto.subtle.importKey('raw', derivedKey.decryptKey.buffer, 'AES-CTR', false, ['decrypt']);
const decrypted = await crypto.subtle.decrypt({ name: 'AES-CTR', counter: iv.buffer, length: 128 }, cryptoKey, encryptedData.buffer);
return new Uint8Array(decrypted);
}
/** Checks whether a parsed JSON object looks like a V1 keystore. */
static isKeystore(obj) {
return 'version' in obj && obj.version == 1;
}
}
exports.LegacyKeystore = LegacyKeystore;