const crypto = require('crypto'); const algorithm = 'aes256'; const bip32 = require('bip32'); // NOTE I'm not a cryptographer... so don't be reusing any code from below as I don't have no idea what I'm doing module.exports.encrypt = (plainText, password) => { const iv = crypto.randomBytes(16).toString('hex').slice(0, 16); // TODO figure out this iv stuff... const key = crypto.createHash('sha256').update(password, 'utf8').digest(); const cipher = crypto.createCipheriv(algorithm, key, iv); var cipherText = cipher.update(plainText, 'utf8', 'hex'); cipherText += cipher.final('hex'); return { cipherText: cipherText, iv: iv }; } module.exports.decrypt = (cipherText, password, iv) => { const key = crypto.createHash('sha256').update(password, 'utf8').digest(); const decipher = crypto.createDecipheriv(algorithm, key, iv); var plainText = decipher.update(cipherText, 'hex', 'utf8'); plainText += decipher.final('utf8'); return plainText; } module.exports.randomDerivationPath = function(hardenedDerivation) { // TODO harden derivation path var randomNumbers = []; for(var i = 0; i < 3; i++) { randomNumbers.push(parseInt(crypto.randomBytes(3).toString('hex'), 16)) } return randomNumbers.join('/') } module.exports.verifyChallenge = function(serviceXpub, challenge) { const requestSignature = challenge.request.signature; const requestDerivationPath = challenge.request.signatureDerivationPath; return this.verifyMessage( serviceXpub, requestDerivationPath, JSON.stringify(this.unsignedChallenge(challenge)), requestSignature ); } module.exports.verifyMessage = function(base58Key, derivationPath, message, signature) { if(derivationPath.startsWith("a/")) { derivationPath = derivationPath.split("a/")[1]; } if(derivationPath.startsWith("c/")) { derivationPath = derivationPath.split("c/")[1]; } const verificationNode = bip32.fromBase58(base58Key).derivePath(derivationPath); const hash = crypto.createHash('sha256').update(message, 'utf8').digest(); return verificationNode.verify(hash, Buffer.from(signature, 'hex')); } module.exports.unsignedChallenge = function(challenge) { return { // keys must be alphabetically ordered derivationPath: challenge.derivationPath, message: challenge.message, xpub: challenge.xpub } } module.exports.signMessage = function(base58Key, derivationPath, message) { let signingNode = bip32.fromBase58(base58Key).derivePath(derivationPath); var hash = crypto.createHash('sha256').update(message, 'utf8').digest(); return signingNode.sign(hash); }