Add sign command which can perform actions

This commit is contained in:
Kgothatso 2019-12-01 00:08:28 +02:00
parent 19dd5a2a9d
commit a05e1ba48e
3 changed files with 179 additions and 0 deletions

57
lib/commands/sign.js Normal file
View File

@ -0,0 +1,57 @@
const registrationLogic = require('../core/logic/register');
const authenticationLogic = require('../core/logic/authentication');
module.exports.description = "Sign message/challenge."
module.exports.builder = (yargs) => {
return yargs
.usage(`Usage: $0 sign [options]`)
.help(false)
.version(false)
.option('challenge', {
describe: 'Challenge to sign',
type: 'string'
})
.demandOption(['challenge'])
.argv;
}
module.exports.handler = (argv) => {
console.log("Sign challenge.");
const challengeArgument = argv["challenge"].js || argv["challenge"];
const challenge = JSON.parse(challengeArgument);
// Parse Action
try {
const request = JSON.parse(challenge.message);
if(request.action != undefined) {
switch(request.action) {
case "register":
// Ask user if they want to register with service
registrationLogic.registration(challenge, request);
break;
case "authenticate":
// Ask user if they want to authenticate with service
authenticationLogic.authenticate(challenge, request, argv)
break;
default:
// Tell user that action is unsupported
// ask if they want to sign regardless if they want to continue any way.
break;
}
} else {
// No action provided... should just sign
console.log("No action required.");
}
// TODO: Validate lock-definition is of the correct format...
} catch(e) {
// Should just be signed...
console.error("challenge.messsage isn't json Object")
}
}

View File

@ -0,0 +1,60 @@
const persistence = require("../persistence/persistence");
const cryptoUtil = require("../cryptoUtil");
module.exports.authenticate = function(challenge, authenticationRequest, argv) {
persistence().LoadDB()
.then(db => {
const url = argv.url || authenticationRequest.url;
const userIdentifier = argv.userIdentifier || authenticationRequest.userIdentifier;
// TODO validate lock definition has all the parameters we need
// TODO: validate serviceExtendedPublicKey
console.log("Looking for");
console.log("url: ", url);
console.log("userIdentifier: ", userIdentifier);
return db.Lock.findOne({
where: {
url: url,
userIdentifier: userIdentifier
},
include: [
{
association: db.Lock.ExtendedPublicKey,
require: true,
include: [
{
association: db.ExtendedPublicKey.Key, // TODO rename key to wallet
required: true
}
]
}
]
})
.then(lock => {
if(lock) {
// Sign the message with the key that corresponds with this lock...
const verification = cryptoUtil.verifyChallenge(
lock.serviceExtendedPublicKey,
challenge
);
if (verification) {
const encryptedKey = lock.extendedPublicKey.key.encryptedPrivateKey;
const iv = lock.extendedPublicKey.key.iv;
const password = "vanished";
const walletXpriv = cryptoUtil.decrypt(encryptedKey, password, iv);
var challengeDerivationPath = `${lock.extendedPublicKey.derivationPath}/${challenge.derivationPath.split("c/")[1]}`;
const signature = cryptoUtil.signMessage(walletXpriv, challengeDerivationPath, challenge.message)
console.log("Signature: ", signature.toString('hex'));
} else {
console.error("Challenge not signed by registered service.");
}
} else {
console.error("Failed to find a lock with these parameters");
}
})
})
}

View File

@ -0,0 +1,62 @@
const persistence = require("../persistence/persistence");
const cryptoUtil = require("../cryptoUtil");
module.exports.registration = function(challenge, registerationRequest) {
persistence().LoadDB()
.then(db => {
// TODO validate lock definition has all the parameters we need
// TODO: validate serviceExtendedPublicKey
const verification = cryptoUtil.verifyChallenge(
registerationRequest.serviceExtendedPublicKey,
challenge
);
if(verification) {
return db.ExtendedPublicKey.findOne({
where: {
xpub: challenge.xpub
},
include: [
{
association: db.ExtendedPublicKey.Key // TODO: update this to wallet
}
]
}).then(extendedPublicKey => {
if (extendedPublicKey) {
const encryptedKey = extendedPublicKey.key.encryptedPrivateKey;
const iv = extendedPublicKey.key.iv;
const password = "vanished";
const walletXpriv = cryptoUtil.decrypt(encryptedKey, password, iv);
var challengeDerivationPath = `${extendedPublicKey.derivationPath}/${challenge.derivationPath.split("c/")[1]}`;
const signature = cryptoUtil.signMessage(walletXpriv, challengeDerivationPath, challenge.message)
// TODO: save lock
return db.Lock.create({
userIdentifier: registerationRequest.userIdentifier,
url: registerationRequest.url,
serviceExtendedPublicKey: registerationRequest.serviceExtendedPublicKey,
signature: signature.toString('hex'),
message: challenge.message,
extendedPublicKeyId: extendedPublicKey.id
})
} else {
console.error("Sorry we can't create a lock with xpub: ", challenge.xpub);
return null;
}
}).then(lock => {
if(lock) {
console.log("Lock: ", lock.id);
console.log("Signature: ", lock.signature);
} else {
console.error("Failed to create the lock.");
}
})
} else {
console.error("Challenge not signed by service");
}
})
}