digibyte-js
Version:
A pure and powerful JavaScript DigiByte library.
117 lines (97 loc) • 4.05 kB
JavaScript
const Hash = require("./crypto/hash");
const Mnemonic = require("./mnemonic");
const HDPrivateKey = require("./hdprivatekey");
const Message = require("./message");
const PrivateKey = require("./privatekey");
const Address = require("./address");
/**
* Instances a DigiID object.
* @param {*} uri - DigiID url
*/
function DigiID(uri) {
if (uri instanceof DigiID)
return uri;
if (typeof uri != 'string')
throw 'Invalid type';
if (uri.substr(0, 9) !== 'digiid://')
throw new Error("Not a DigiID uri");
let params = {};
uri.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (m, key, value) {
params[key] = value;
});
this.params = params;
let paramsStart = uri.indexOf("?");
if (this.params.x === undefined) {
var x = (new Date()).getTime().toString(16);
uri += (paramsStart === -1) ? '?x=' + x : '&x=' + x;
}
if (this.params.assetId !== undefined) {
this.asset = this.params["assetId"];
} else {
this.asset = false;
}
if (this.params.tos !== undefined) {
this.contract = Buffer.from(this.params.tos, 'base64');
} else {
this.contract = false;
}
this.unsafe = this.params.u !== undefined;
this.uri = uri;
this.callback = (this.unsafe ? 'http://' : 'https://') + uri.substr(9, (paramsStart === -1) ? undefined : paramsStart - 9);
this.domain = uri.match(/^digiid\:\/\/([^\/?#]+)(?:[\/?#]|$)/i)[1];
}
DigiID.prototype._path = function (index = 0) {
var indexBuffer = Buffer.alloc(4);
indexBuffer.writeUInt32LE(index, 0);
var toHash = Buffer.concat([indexBuffer, Buffer.from(this.callback)])
var hash = Hash.sha256(toHash);
var A = hash.slice(0, 4).readUInt32LE() % 0x80000000;
var B = hash.slice(4, 8).readUInt32LE() % 0x80000000;
var C = hash.slice(8, 12).readUInt32LE() % 0x80000000;
var D = hash.slice(12, 16).readUInt32LE() % 0x80000000;
return `m/13'/${A}'/${B}'/${C}'/${D}'`;
}
DigiID.prototype.sign = function (secret, index = 0, address, assetAddress, assetKey) {
if (typeof secret == 'string') {
if (Mnemonic.isValid(secret))
var hdPrivateKey = (new Mnemonic(secret)).toHDPrivateKey();
else if (secret.startsWith('xprv'))
var hdPrivateKey = HDPrivateKey.fromString(secret);
else if (PrivateKey.isValid(secret))
var privateKey = new PrivateKey(secret);
} else if (secret instanceof HDPrivateKey)
var hdPrivateKey = secret;
else if (secret instanceof PrivateKey)
var privateKey = secret;
if (!hdPrivateKey && !privateKey) throw 'Invalid secret';
if (hdPrivateKey) {
var path = this._path(index);
var privateKey = hdPrivateKey.deriveChild(path).privateKey;
}
if (!Address.isValid(address)) address = privateKey.toAddress().toString();
var signature = new Message(this.uri).sign(privateKey);
var result = { uri: this.uri, address, signature };
if (this.asset.dual) {
if (!Address.isValid(assetAddress)) throw "Invalid asset address";
if (!PrivateKey.isValid(assetKey)) throw "Invalid asset private key";
result.assetaddress = assetAddress;
result.assetsignature = new Message(this.uri).sign(new PrivateKey(assetKey));
}
return result;
}
DigiID.prototype.login = async function (secret, index = 0, address, assetAddress, assetKey) {
try {
var data = await fetch(this.callback, {
method: "POST",
body: JSON.stringify(this.sign(secret, index = 0, address, assetAddress, assetKey)),
headers: { "Content-type": "application/json; charset=UTF-8" }
});
return data.status === 200;
} catch {
return { error: 'Invalid response' };
}
}
DigiID.verify = function ({ uri, address, signature }) {
return new Message(uri).verify(address, signature);
}
module.exports = DigiID;