2023-05-12 05:59:32 +00:00
|
|
|
/*eslint no-undef:0*/
|
|
|
|
/*eslint-env browser*/
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
var pagans = pagans || {};
|
|
|
|
/**
|
|
|
|
* pagans.generateKey(params) create a public/private key compatible with apXtrib backend and store it in apx.data
|
|
|
|
* pagans.detachedSignature(params) generate a detachedSignature for a Message that backend can check with the publicKey of the alias
|
|
|
|
* pagans.checkdetachedSignature(params) check a detachedSignature for a Message (used on the backend as well)
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
pagans.loadtpldata = () => {
|
|
|
|
// adapte tpldata to template tpl
|
|
|
|
// get list of tribes from nationchains/towns/idx/townId_all.json
|
|
|
|
const datacreatepagan = { tribes: [] };
|
|
|
|
|
|
|
|
apx.data.towns.idxtownId_all[apx.data.tpldata.setup.townId].tribes.forEach(
|
|
|
|
(t) => {
|
|
|
|
if (t == apx.data.tpldata.setup.tribeId) {
|
|
|
|
datacreatepagan.tribes.push({ selected: true, tribeId: t });
|
|
|
|
} else {
|
|
|
|
datacreatepagan.tribes.push({ tribeId: t });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
return datacreatepagan;
|
|
|
|
};
|
|
|
|
|
|
|
|
pagans.generateKey = async (alias, passphrase) => {
|
|
|
|
/**
|
|
|
|
* @param {string} alias a unique alias that identify an identity
|
|
|
|
* @param {string} passphrase a string to cipher the publicKey (can be empty, less secure but simpler)
|
|
|
|
* @return {publicKey,privateKey} with userIds = [{alias}]
|
|
|
|
*/
|
|
|
|
const pgpparam = {
|
|
|
|
type: "ecc", // Type of the key, defaults to ECC
|
|
|
|
curve: "curve25519", // ECC curve name, defaults to curve25519
|
|
|
|
userIDs: [{ alias: alias }], // you can pass multiple user IDs
|
|
|
|
passphrase: passphrase, // protects the private key
|
|
|
|
format: "armored", // output key format, defaults to 'armored' (other options: 'binary' or 'object')
|
|
|
|
};
|
|
|
|
const { privateKey, publicKey } = await openpgp.generateKey(pgpparam);
|
|
|
|
// key start by '-----BEGIN PGP PRIVATE KEY BLOCK ... '
|
|
|
|
// get liste of alias:pubklickey await axios.get('api/v0/pagans')
|
|
|
|
// check alias does not exist
|
|
|
|
return { alias, privateKey, publicKey };
|
|
|
|
};
|
|
|
|
pagans.detachedSignature = async (pubK, privK, passphrase, message) => {
|
|
|
|
/**
|
|
|
|
* @pubK {string} a text public key
|
|
|
|
* @privK {string} a test priv key
|
|
|
|
* @passphrase {string} used to read privK
|
|
|
|
* @message {string} message to sign
|
|
|
|
* @Return a detached Signature of the message
|
|
|
|
*/
|
|
|
|
const publicKey = await openpgp.readKey({ armoredKey: pubK });
|
|
|
|
let privateKey;
|
|
|
|
if (passphrase == "") {
|
|
|
|
privateKey = await openpgp.readPrivateKey({ armoredKey: privK });
|
|
|
|
} else {
|
|
|
|
privateKey = await openpgp.decryptKey({
|
|
|
|
privateKey: await openpgp.readPrivateKey({ armoredKey: privK }),
|
|
|
|
passphrase,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
console.log(message);
|
|
|
|
const msg = await openpgp.createMessage({ text: message });
|
|
|
|
console.log(msg);
|
|
|
|
const sig = await openpgp.sign({
|
|
|
|
message: msg,
|
|
|
|
signingKeys: privateKey,
|
|
|
|
detached: true,
|
|
|
|
});
|
|
|
|
return btoa(sig);
|
|
|
|
};
|
|
|
|
pagans.authenticatedetachedSignature = async (
|
|
|
|
alias,
|
|
|
|
pubK,
|
|
|
|
detachedSignature,
|
|
|
|
message
|
|
|
|
) => {
|
|
|
|
/**
|
|
|
|
* Check that alias (pubkey) signe a message
|
|
|
|
* @alias {string} alias link to the publicKey
|
|
|
|
* @pubK {string} publiKey text format
|
|
|
|
* @detachedSignature {string} a detachedsignatured get from apx.detachedSignature
|
|
|
|
* @message {string} the message signed
|
|
|
|
* @return {boolean} true the message was signed by alias
|
|
|
|
* false the message was not signed by alias
|
|
|
|
*/
|
|
|
|
const publicKey = await openpgp.readKey({ armoredKey: pubK });
|
|
|
|
const msg = await openpgp.createMessage({ text: message });
|
|
|
|
const signature = await openpgp.readSignature({
|
|
|
|
armoredSignature: atob(detachedSignature), // parse detached signature
|
|
|
|
});
|
|
|
|
const verificationResult = await openpgp.verify({
|
|
|
|
msg, // Message object
|
|
|
|
signature,
|
|
|
|
verificationKeys: publicKey,
|
|
|
|
});
|
|
|
|
const { verified, keyID } = verificationResult.signatures[0];
|
|
|
|
try {
|
|
|
|
await verified; // throws on invalid signature
|
|
|
|
console.log("Signed by key id " + keyID.toHex());
|
|
|
|
return KeyId.toHex().alias == alias;
|
|
|
|
} catch (e) {
|
|
|
|
console.log("Signature could not be verified: " + e.message);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
pagans.createIdentity = async (alias, passphrase = "") => {
|
|
|
|
console.log(Object.keys(apx.data.pagans["idxalias_all"]));
|
|
|
|
if (
|
|
|
|
alias.length < 3 ||
|
|
|
|
Object.keys(apx.data.pagans["idxalias_all"]).includes(alias)
|
|
|
|
) {
|
|
|
|
alert("Please chose another alias");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const keys = await pagans.generateKey(alias, passphrase);
|
|
|
|
for (let tag of ["inputalias", "inputpassphrase"]) {
|
|
|
|
document.getElementById(tag).classList.add("disabled");
|
|
|
|
}
|
|
|
|
console.log(keys);
|
|
|
|
document.getElementById("privatekey").setAttribute("key", keys.privateKey);
|
|
|
|
document.getElementById("publickey").setAttribute("key", keys.publicKey);
|
2023-05-16 08:31:27 +00:00
|
|
|
apx.data.tmp = keys; // to make it available for btn download
|
2023-05-12 05:59:32 +00:00
|
|
|
document.getElementById("generatekeys").classList.add("d-none");
|
|
|
|
document.getElementById("trustintribe").classList.remove("d-none");
|
|
|
|
document.getElementById("downloadkeys").classList.remove("d-none");
|
|
|
|
document.getElementById("createId").classList.remove("d-none");
|
|
|
|
};
|
|
|
|
|
|
|
|
pagans.registerIdentity = async () => {
|
|
|
|
const emailregex =
|
|
|
|
/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
|
|
|
const data = {};
|
|
|
|
data.alias = document.getElementById("inputalias").value;
|
|
|
|
data.publickey = document.getElementById("publickey").getAttribute("key");
|
|
|
|
|
|
|
|
if (document.getElementById("inputemailrecovery").value != "") {
|
|
|
|
data.email = document.getElementById("inputemailrecovery").value;
|
|
|
|
}
|
|
|
|
if (data.email && !emailregex.test(data.email)) {
|
|
|
|
alert("Check your email");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
var select = document.getElementById("trustedtribe");
|
|
|
|
if (document.getElementById("trustedcheck").checked) {
|
|
|
|
data.trustedtribe = select.options[select.selectedIndex].value;
|
|
|
|
data.privatekey = document.getElementById("privatekey").getAttribute("key");
|
|
|
|
data.passphrase = document.getElementById("inputpassphrase").value;
|
|
|
|
}
|
|
|
|
if (document.getElementById("trustedcheck").checked && !data.email) {
|
|
|
|
alert("Please provide a valid email");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
console.log(data);
|
|
|
|
//store and create authentification by signing 'alias_timestamp'
|
|
|
|
/* const passp = data.passphrase ? data.passphrase : "";
|
|
|
|
apx.data.auth = {
|
|
|
|
alias: data.alias,
|
|
|
|
publickey: data.publickey,
|
|
|
|
privatekey: document.getElementById("privatekey").getAttribute("key"),
|
|
|
|
passphrase: passp,
|
|
|
|
};
|
|
|
|
apx.data.headers.xalias = data.alias;
|
|
|
|
apx.data.headers.xdays = dayjs().valueOf();
|
|
|
|
apx.save();
|
|
|
|
const msg = `${data.alias}_${apx.data.headers.xdays}`;
|
|
|
|
apx.data.headers.xhash = await pagans.detachedSignature(
|
|
|
|
apx.data.auth.publickey,
|
|
|
|
apx.data.auth.privatekey,
|
|
|
|
passp,
|
|
|
|
msg
|
|
|
|
);
|
|
|
|
apx.save();*/
|
|
|
|
await pagans.authentifyme(
|
|
|
|
data.alias,
|
|
|
|
data.passphrase,
|
|
|
|
document.getElementById("privatekey").getAttribute("key"),
|
|
|
|
document.getElementById("publickey").getAttribute("key")
|
|
|
|
);
|
|
|
|
console.log("header", apx.data.headers);
|
|
|
|
axios
|
|
|
|
.post("api/pagans", data, { headers: apx.data.headers })
|
|
|
|
.then((reppagan) => {
|
|
|
|
console.log(reppagan);
|
|
|
|
})
|
|
|
|
.catch((err) => {
|
|
|
|
console.log("sorry", err);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
pagans.authentifyme = async (
|
|
|
|
alias,
|
|
|
|
passphrase,
|
|
|
|
privatekey,
|
|
|
|
publickeycreate
|
|
|
|
) => {
|
|
|
|
/**
|
|
|
|
* Set apx.data.auth with pub, priv, passphrase alias that allow authentification
|
|
|
|
* set headers with xdays (timestamp) and xhash of message: {alias}_{timestamp} generate with pub & priv key
|
|
|
|
*
|
|
|
|
* @Param {key} publickeycreate optional when alias does not exist
|
|
|
|
*/
|
|
|
|
console.log(alias, passphrase);
|
|
|
|
console.log(privatekey);
|
|
|
|
const passp = passphrase ? passphrase : "";
|
|
|
|
const publickey = publickeycreate
|
|
|
|
? publickeycreate
|
|
|
|
: apx.data.pagans.idxalias_all[alias].publicKey;
|
|
|
|
apx.data.auth = {
|
|
|
|
alias: alias,
|
|
|
|
publickey: publickey,
|
|
|
|
privatekey: privatekey,
|
|
|
|
passphrase: passp,
|
|
|
|
};
|
|
|
|
apx.data.headers.xalias = alias;
|
|
|
|
apx.data.headers.xdays = dayjs().valueOf();
|
|
|
|
apx.save();
|
|
|
|
const msg = `${alias}_${apx.data.headers.xdays}`;
|
|
|
|
|
|
|
|
apx.data.headers.xhash = await pagans.detachedSignature(
|
|
|
|
apx.data.auth.publickey,
|
|
|
|
apx.data.auth.privatekey,
|
|
|
|
passp,
|
|
|
|
msg
|
|
|
|
);
|
|
|
|
apx.save();
|
|
|
|
};
|
2023-06-02 08:21:01 +00:00
|
|
|
|
|
|
|
pagans.logout=()=>{
|
|
|
|
delete apx.data.auth;
|
|
|
|
delete apx.data.headers;
|
|
|
|
apx.data.headers = apxlocal.headers;
|
|
|
|
apx.save();
|
|
|
|
alert('delete apx.data.auth and reinit apx.data.header');
|
|
|
|
}
|