UNPKG

keyvenant

Version:

Keyvenant is a JavaScript tool to generate and export CovenantSQL keys to facilitate key management locally and in web extensions.

138 lines 9.23 kB
import coinstring from 'coinstring'; import { string2Buffer } from './utils'; import THash from './utils/THash'; import * as keygen from './keygen'; import * as secretkey from './secretkey'; import * as symmetric from './symmetric'; /** * create CovenantSQL keystore * @param password master password user typed-in * @param salt kdf salt * @param addrVersion address version * @param privateKeyVersion private key encode version * @return keystore object */ export function createKeystore(password, salt, addrVersion, privateKeyVersion) { // generate new key pair let prvKey = keygen.createPrivateKey(); let pubKey = keygen.privateKeyToPublicKey(prvKey); console.log('Print out private key for test', prvKey); // covert to address let address = keygen.publicKeyToAddress(pubKey, addrVersion); // get derived key from password let secretKey = secretkey.derive(password, salt); // prepare iv for symmetric encryption let iv = symmetric.generateIv(); let ciphertext = symmetric.encrypt(prvKey, secretKey, iv); let mac = constructMac(secretKey, ciphertext); let keystore = marshal(address, salt, mac, ciphertext, iv, privateKeyVersion); return keystore; } /** * recover private key from keystore and password * @param password * @param keystore * @return private key string in hex */ export function recoverFromKeystore(password, salt, keystore) { // get derived key from password let secretKey = secretkey.derive(password, salt); // prepare iv for symmetric encryption let iv = keystore.crypto.iv; let ciphertext = keystore.crypto.ciphertext; // check mac let macToVerify = constructMac(secretKey, ciphertext); if (macToVerify !== keystore.mac) { throw new Error('Input password is not valid for the keystore or version not compatible'); } // decrypt private key let prvKey = symmetric.decrypt(ciphertext, secretKey, iv); return prvKey; } /** * construct keystore json * @param address wallet address * @param salt kdf salt * @param mac mac value * @param ciphertext encrypted text * @param iv symmetric iv * @param privateKeyVersion version hex * @return keystore object */ function marshal(address, salt, mac, ciphertext, iv, privateKeyVersion) { let encrypted = constructEncrypted(privateKeyVersion, iv, ciphertext); let keystore = { address, encrypted, mac, crypto: { cipher: 'aes-256', ciphertext, iv }, derivation: { kdf: 'sha256x2', salt }, version: privateKeyVersion, }; return keystore; } /** * construct Mac for password pre-check * secretKey + ciphertext as mac input * then THash convert to Mac hex string and return * @param secretKey derived key hex string * @param ciphertext encrypted hex string * @return mac as hex string */ function constructMac(secretKey, ciphertext) { let secretKeyBuf = string2Buffer(secretKey); let ciphertextBuf = string2Buffer(ciphertext); // concat buffer & THash let concated = Buffer.concat([secretKeyBuf, ciphertextBuf]); let hashedMac = THash(concated); return hashedMac.toString('hex'); } /** * construct base58 encoded string for CovenantSQL chain recover * privateKeyVersion(1B) + iv(16B) + ciphertext(48B) as concated hex * then base58 encoded the concated and return * @param privateKeyVersion 1 btye version * @param iv generated iv * @param ciphertext encrypted ciphertext * @return base58Encoded concated */ function constructEncrypted(privateKeyVersion, iv, ciphertext) { let versionBuf = Buffer.from([privateKeyVersion]); let ivBuf = string2Buffer(iv); let ciphertextBuf = string2Buffer(ciphertext); // concat buffer & base58 encode let concated = Buffer.concat([versionBuf, ivBuf, ciphertextBuf]); let base58Encoded = coinstring.encode(concated); return base58Encoded; } /** * deconstruct base58 encoded string for CovenantSQL chain recover * @param encrypted base58Encoded concated * @return { * privateKeyVersion 1 btye version * iv generated iv * ciphertext encrypted ciphertext * } */ export function deconstructEncrypted(encrypted) { let encBuf = coinstring.decode(encrypted); // 1st byte as privateKeyVersion let versionBuf = encBuf.slice(0, 1); // next 16 bytes as iv let ivBuf = encBuf.slice(1, 17); // next 48 bytes as cipher let ciphertextBuf = encBuf.slice(17, 65); return { privateKeyVersion: versionBuf.toString('hex'), iv: ivBuf.toString('hex'), ciphertext: ciphertextBuf.toString('hex') }; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5c3RvcmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL2tleXN0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sVUFBVSxNQUFNLFlBQVksQ0FBQTtBQUNuQyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sU0FBUyxDQUFBO0FBQ3ZDLE9BQU8sS0FBSyxNQUFNLGVBQWUsQ0FBQTtBQUVqQyxPQUFPLEtBQUssTUFBTSxNQUFNLFVBQVUsQ0FBQTtBQUNsQyxPQUFPLEtBQUssU0FBUyxNQUFNLGFBQWEsQ0FBQTtBQUN4QyxPQUFPLEtBQUssU0FBUyxNQUFNLGFBQWEsQ0FBQTtBQUV4Qzs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxVQUFVLGNBQWMsQ0FDNUIsUUFBZ0IsRUFDaEIsSUFBWSxFQUNaLFdBQW1CLEVBQ25CLGlCQUF5QjtJQUV6Qix3QkFBd0I7SUFDeEIsSUFBSSxNQUFNLEdBQVcsTUFBTSxDQUFDLGdCQUFnQixFQUFFLENBQUE7SUFDOUMsSUFBSSxNQUFNLEdBQVcsTUFBTSxDQUFDLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBQ3pELE9BQU8sQ0FBQyxHQUFHLENBQUMsZ0NBQWdDLEVBQUcsTUFBTSxDQUFDLENBQUE7SUFFdEQsb0JBQW9CO0lBQ3BCLElBQUksT0FBTyxHQUFXLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDLENBQUE7SUFFcEUsZ0NBQWdDO0lBQ2hDLElBQUksU0FBUyxHQUFXLFNBQVMsQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFBO0lBRXhELHNDQUFzQztJQUN0QyxJQUFJLEVBQUUsR0FBVyxTQUFTLENBQUMsVUFBVSxFQUFFLENBQUE7SUFDdkMsSUFBSSxVQUFVLEdBQVcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsU0FBUyxFQUFFLEVBQUUsQ0FBQyxDQUFBO0lBRWpFLElBQUksR0FBRyxHQUFXLFlB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