keyvenant
Version:
Keyvenant is a JavaScript tool to generate and export CovenantSQL keys to facilitate key management locally and in web extensions.
153 lines • 9.88 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const coinstring_1 = __importDefault(require("coinstring"));
const utils_1 = require("./utils");
const THash_1 = __importDefault(require("./utils/THash"));
const keygen = __importStar(require("./keygen"));
const secretkey = __importStar(require("./secretkey"));
const symmetric = __importStar(require("./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
*/
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;
}
exports.createKeystore = createKeystore;
/**
* recover private key from keystore and password
* @param password
* @param keystore
* @return private key string in hex
*/
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;
}
exports.recoverFromKeystore = recoverFromKeystore;
/**
* 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 = utils_1.string2Buffer(secretKey);
let ciphertextBuf = utils_1.string2Buffer(ciphertext);
// concat buffer & THash
let concated = Buffer.concat([secretKeyBuf, ciphertextBuf]);
let hashedMac = THash_1.default(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 = utils_1.string2Buffer(iv);
let ciphertextBuf = utils_1.string2Buffer(ciphertext);
// concat buffer & base58 encode
let concated = Buffer.concat([versionBuf, ivBuf, ciphertextBuf]);
let base58Encoded = coinstring_1.default.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
* }
*/
function deconstructEncrypted(encrypted) {
let encBuf = coinstring_1.default.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')
};
}
exports.deconstructEncrypted = deconstructEncrypted;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5c3RvcmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL2tleXN0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQUFBLDREQUFtQztBQUNuQyxtQ0FBdUM7QUFDdkMsMERBQWlDO0FBRWpDLGlEQUFrQztBQUNsQyx1REFBd0M7QUFDeEMsdURBQXdDO0FBRXhDOzs7Ozs7O0dBT0c7QUFDSCxTQUFnQixjQUFjLENBQzVCLFFBQWdCLEVBQ2hCLElBQVksRUFDWixXQUFtQixFQUNuQixpQkFBeUI7SUFFekIsd0JBQXdCO0lBQ3hCLElBQUksTUFBTSxHQUFXLE1BQU0sQ0FBQyxnQkFBZ0IsRUFBRSxDQUFBO0lBQzlDLElBQUksTUFBTSxHQUFXLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLENBQUMsQ0FBQTtJQUN6RCxPQUFPLENBQUMsR0FBRyxDQUFDLGdDQUFnQyxFQUFHLE1BQU0sQ0FBQyxDQUFBO0lBRXRELG9CQUFvQjtJQUNwQixJQUFJLE9BQU8sR0FBVyxNQUFNLENBQUMsa0JBQWtCLENBQUMsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFBO0lBRXBFLGdDQUFnQztJQUNoQyxJQUFJLFNBQVMsR0FBVyxTQUFTLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQTtJQUV4RCxzQ0FBc0M7SUFDdEMsSUFBSSxFQUFFLEdBQVcsU0FBUyxDQUFDLFVBQVUsRUFBRSxDQUFBO0lBQ3ZDLElBQUksVUFBVSxHQUFXLFNBQVMsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxFQUFFLENBQUMsQ0FBQTtJQUVqRSxJQUFJLEdBQUcsR0FBVyxZQUFZLENBQUMsU0FBUyxFQUFFLFVBQVUsQ0FBQyxDQUFBO0lBQ3JELElBQUksUUFBUSxHQUFHLE9BQU8sQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFFLGlCQUFpQixDQUFD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