From 80ca63fdf888c40aaaf42797ef957cec5ca354e9 Mon Sep 17 00:00:00 2001 From: sairaj mote Date: Mon, 19 Sep 2022 14:13:54 +0530 Subject: [PATCH] Updating std ops --- scripts/components.js | 1 + scripts/floBlockchainAPI.js | 14 ++-- scripts/floCloudAPI.js | 5 +- scripts/floCrypto.js | 125 +++++++++++++++++------------------- scripts/floDapps.js | 34 ++++++++-- scripts/lib.js | 93 +++++++++++++++------------ 6 files changed, 152 insertions(+), 120 deletions(-) diff --git a/scripts/components.js b/scripts/components.js index dae48a7..bbdbca4 100644 --- a/scripts/components.js +++ b/scripts/components.js @@ -1016,6 +1016,7 @@ smNotifications.innerHTML = ` padding: 0.3rem; transition: background-color 0.3s, transform 0.3s; background-color: transparent; + flex-shrink: 0; } .close:active{ transform: scale(0.9); diff --git a/scripts/floBlockchainAPI.js b/scripts/floBlockchainAPI.js index 8cf3a79..d250f86 100644 --- a/scripts/floBlockchainAPI.js +++ b/scripts/floBlockchainAPI.js @@ -1,4 +1,4 @@ -(function(EXPORTS) { //floBlockchainAPI v2.3.3a +(function(EXPORTS) { //floBlockchainAPI v2.3.3b /* FLO Blockchain Operator to send/receive data from blockchain using API calls*/ 'use strict'; const floBlockchainAPI = EXPORTS; @@ -6,7 +6,7 @@ const DEFAULT = { blockchain: floGlobals.blockchain, apiURL: { - FLO: ['https://livenet.flocha.in/', 'https://flosight.duckdns.org/'], + FLO: ['https://flosight.duckdns.org/'], FLO_TEST: ['https://testnet-flosight.duckdns.org', 'https://testnet.flocha.in/'] }, sendAmt: 0.001, @@ -49,7 +49,7 @@ const allServerList = new Set(floGlobals.apiURL && floGlobals.apiURL[DEFAULT.blockchain] ? floGlobals.apiURL[DEFAULT.blockchain] : DEFAULT.apiURL[DEFAULT.blockchain]); var serverList = Array.from(allServerList); - var curPos = floCrypto.randInt(0, serverList - 1); + var curPos = floCrypto.randInt(0, serverList.length - 1); function fetch_retry(apicall, rm_flosight) { return new Promise((resolve, reject) => { @@ -371,18 +371,18 @@ }) //Calculate totalSentAmount and check if totalBalance is sufficient let totalSendAmt = totalFee; - for (floID in receivers) + for (let floID in receivers) totalSendAmt += receivers[floID]; if (totalBalance < totalSendAmt) return reject("Insufficient total Balance"); //Get the UTXOs of the senders let promises = []; - for (floID in senders) + for (let floID in senders) promises.push(promisedAPI(`api/addr/${floID}/utxo`)); Promise.all(promises).then(results => { let wifSeq = []; var trx = bitjs.transaction(); - for (floID in senders) { + for (let floID in senders) { let utxos = results.shift(); let sendAmt; if (preserveRatio) { @@ -406,7 +406,7 @@ if (change > 0) trx.addoutput(floID, change); } - for (floID in receivers) + for (let floID in receivers) trx.addoutput(floID, receivers[floID]); trx.addflodata(floData.replace(/\n/g, ' ')); for (let i = 0; i < wifSeq.length; i++) diff --git a/scripts/floCloudAPI.js b/scripts/floCloudAPI.js index 402c0c5..1fafb51 100644 --- a/scripts/floCloudAPI.js +++ b/scripts/floCloudAPI.js @@ -1,4 +1,4 @@ -(function(EXPORTS) { //floCloudAPI v2.4.2c +(function(EXPORTS) { //floCloudAPI v2.4.2d /* FLO Cloud operations to send/request application data*/ 'use strict'; const floCloudAPI = EXPORTS; @@ -317,6 +317,7 @@ data => { data = objectifier(data); let filtered = {}, + proxy = proxyID(request.receiverID), r = request; for (let v in data) { let d = data[v]; @@ -325,7 +326,7 @@ (r.atVectorClock || !r.upperVectorClock || r.upperVectorClock >= v) && (!r.afterTime || r.afterTime < d.log_time) && r.application == d.application && - r.receiverID == d.receiverID && + (proxy == d.receiverID || proxy == d.proxyID) && (!r.comment || r.comment == d.comment) && (!r.type || r.type == d.type) && (!r.senderID || r.senderID.includes(d.senderID))) diff --git a/scripts/floCrypto.js b/scripts/floCrypto.js index 01921d1..6671ffa 100644 --- a/scripts/floCrypto.js +++ b/scripts/floCrypto.js @@ -1,4 +1,4 @@ -(function(EXPORTS) { //floCrypto v2.3.3b +(function(EXPORTS) { //floCrypto v2.3.3d /* FLO Crypto Operators */ 'use strict'; const floCrypto = EXPORTS; @@ -81,7 +81,7 @@ floCrypto.randInt = function(min, max) { min = Math.ceil(min); max = Math.floor(max); - return Math.floor(Math.random() * (max - min + 1)) + min; + return Math.floor(securedMathRandom() * (max - min + 1)) + min; } //generate a random String within length (options : alphaNumeric chars only) @@ -90,7 +90,7 @@ var characters = alphaNumeric ? 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_+-./*?@#&$<>=[]{}():'; for (var i = 0; i < length; i++) - result += characters.charAt(Math.floor(Math.random() * characters.length)); + result += characters.charAt(Math.floor(securedMathRandom() * characters.length)); return result; } @@ -245,101 +245,96 @@ //Check if the given address (any blockchain) is valid or not floCrypto.validateAddr = function(address, std = true, bech = true) { - if (address.length == 33 || address.length == 34) { //legacy or segwit encoding - if (std === false) + let raw = decodeAddress(address); + if (!raw) + return false; + if (typeof raw.version !== 'undefined') { //legacy or segwit + if (std == false) return false; - let decode = bitjs.Base58.decode(address); - var raw = decode.slice(0, decode.length - 4), - checksum = decode.slice(decode.length - 4); - var hash = Crypto.SHA256(Crypto.SHA256(raw, { - asBytes: true - }), { - asBytes: true - }); - if (hash[0] != checksum[0] || hash[1] != checksum[1] || hash[2] != checksum[2] || hash[3] != checksum[3]) - return false; - else if (std === true || (!Array.isArray(std) && std === raw[0]) || (Array.isArray(std) && std.includes(raw[0]))) + else if (std === true || (!Array.isArray(std) && std === raw.version) || (Array.isArray(std) && std.includes(raw.version))) return true; else return false; - } else if (address.length == 42 || address.length == 62) { //bech encoding + } else if (typeof raw.bech_version !== 'undefined') { //bech32 if (bech === false) return false; - let decode = coinjs.bech32_decode(address); - if (!decode) - return false; - var raw = decode.data; - if (bech === true || (!Array.isArray(bech) && bech === raw[0]) || (Array.isArray(bech) && bech.includes(raw[0]))) + else if (bech === true || (!Array.isArray(bech) && bech === raw.bech_version) || (Array.isArray(bech) && bech.includes(raw.bech_version))) return true; else return false; - } else //unknown length + } else //unknown return false; } //Check the public-key for the address (any blockchain) floCrypto.verifyPubKey = function(pubKeyHex, address) { - let pub_hash = Crypto.util.bytesToHex(ripemd160(Crypto.SHA256(Crypto.util.hexToBytes(pubKeyHex), { - asBytes: true - }))); - if (address.length == 33 || address.length == 34) { //legacy encoding - let decode = bitjs.Base58.decode(address); - var raw = decode.slice(0, decode.length - 4), - checksum = decode.slice(decode.length - 4); - var hash = Crypto.SHA256(Crypto.SHA256(raw, { + let raw = decodeAddress(address), + pub_hash = Crypto.util.bytesToHex(ripemd160(Crypto.SHA256(Crypto.util.hexToBytes(pubKeyHex), { asBytes: true - }), { - asBytes: true - }); - if (hash[0] != checksum[0] || hash[1] != checksum[1] || hash[2] != checksum[2] || hash[3] != checksum[3]) - return false; - raw.shift(); - return pub_hash === Crypto.util.bytesToHex(raw); - } else if (address.length == 42 || address.length == 62) { //bech encoding - let decode = coinjs.bech32_decode(address); - if (!decode) - return false; - var raw = decode.data; - raw.shift(); - raw = coinjs.bech32_convert(raw, 5, 8, false); - return pub_hash === Crypto.util.bytesToHex(raw); - } else //unknown length - return false; + }))); + return raw ? pub_hash === raw.hex : false; } //Convert the given address (any blockchain) to equivalent floID floCrypto.toFloID = function(address) { if (!address) return; - var bytes; - if (address.length == 33 || address.length == 34) { //legacy encoding + let raw = decodeAddress(address); + if (!raw) + return; + raw.bytes.unshift(bitjs.pub); + let hash = Crypto.SHA256(Crypto.SHA256(raw.bytes, { + asBytes: true + }), { + asBytes: true + }); + return bitjs.Base58.encode(raw.bytes.concat(hash.slice(0, 4))); + } + + //Checks if the given addresses (any blockchain) are same (w.r.t keys) + floCrypto.isSameAddr = function(addr1, addr2) { + if (!addr1 || !addr2) + return; + let raw1 = decodeAddress(addr1), + raw2 = decodeAddress(addr2); + if (!raw1 || !raw2) + return false; + else + return raw1.hex === raw2.hex; + } + + const decodeAddress = floCrypto.decodeAddr = function(address) { + if (!address) + return; + else if (address.length == 33 || address.length == 34) { //legacy encoding let decode = bitjs.Base58.decode(address); - bytes = decode.slice(0, decode.length - 4); + let bytes = decode.slice(0, decode.length - 4); let checksum = decode.slice(decode.length - 4), hash = Crypto.SHA256(Crypto.SHA256(bytes, { asBytes: true }), { asBytes: true }); - hash[0] != checksum[0] || hash[1] != checksum[1] || hash[2] != checksum[2] || hash[3] != checksum[3] ? - bytes = undefined : bytes.shift(); + return (hash[0] != checksum[0] || hash[1] != checksum[1] || hash[2] != checksum[2] || hash[3] != checksum[3]) ? null : { + version: bytes.shift(), + hex: Crypto.util.bytesToHex(bytes), + bytes + } } else if (address.length == 42) { //bech encoding let decode = coinjs.bech32_decode(address); if (decode) { - bytes = decode.data; - bytes.shift(); + let bytes = decode.data; + let bech_version = bytes.shift(); bytes = coinjs.bech32_convert(bytes, 5, 8, false); - } + return { + bech_version, + hrp: decode.hrp, + hex: Crypto.util.bytesToHex(bytes), + bytes + } + } else + return null; } - if (!bytes) - return; - bytes.unshift(bitjs.pub); - let hash = Crypto.SHA256(Crypto.SHA256(bytes, { - asBytes: true - }), { - asBytes: true - }); - return bitjs.Base58.encode(bytes.concat(hash.slice(0, 4))); } //Split the str using shamir's Secret and Returns the shares diff --git a/scripts/floDapps.js b/scripts/floDapps.js index 1da58b8..38ee0b4 100644 --- a/scripts/floDapps.js +++ b/scripts/floDapps.js @@ -1,4 +1,4 @@ -(function(EXPORTS) { //floDapps v2.3.2c +(function(EXPORTS) { //floDapps v2.3.2d /* General functions for FLO Dapps*/ 'use strict'; const floDapps = EXPORTS; @@ -63,7 +63,7 @@ return Crypto.AES.decrypt(data, raw_user.private); }, get db_name() { - return "floDapps#" + user.id; + return "floDapps#" + floCrypto.toFloID(user.id); }, lock() { user_private = user_priv_wrap; @@ -72,6 +72,30 @@ if (await user.private === raw_user.private) user_private = user_priv_raw; }, + get_contact(id) { + if (!user.contacts) + throw "Contacts not available"; + else if (user.contacts[id]) + return user.contacts[id]; + else { + let id_raw = floCrypto.decodeAddr(id).hex; + for (let i in user.contacts) + if (floCrypto.decodeAddr(i).hex == id_raw) + return user.contacts[i]; + } + }, + get_pubKey(id) { + if (!user.pubKeys) + throw "Contacts not available"; + else if (user.pubKeys[id]) + return user.pubKeys[id]; + else { + let id_raw = floCrypto.decodeAddr(id).hex; + for (let i in user.pubKeys) + if (floCrypto.decodeAddr(i).hex == id_raw) + return user.pubKeys[i]; + } + }, clear() { user_id = user_public = user_private = undefined; user_priv_raw = aes_key = undefined; @@ -475,7 +499,7 @@ floDapps.storeContact = function(floID, name) { return new Promise((resolve, reject) => { - if (!floCrypto.validateFloID(floID)) + if (!floCrypto.validateAddr(floID)) return reject("Invalid floID!") compactIDB.writeData("contacts", name, floID, user.db_name).then(result => { user.contacts[floID] = name; @@ -488,9 +512,9 @@ return new Promise((resolve, reject) => { if (floID in user.pubKeys) return resolve("pubKey already stored") - if (!floCrypto.validateFloID(floID)) + if (!floCrypto.validateAddr(floID)) return reject("Invalid floID!") - if (floCrypto.getFloID(pubKey) != floID) + if (!floCrypto.verifyPubKey(pubKey, floID)) return reject("Incorrect pubKey") compactIDB.writeData("pubKeys", pubKey, floID, user.db_name).then(result => { user.pubKeys[floID] = pubKey; diff --git a/scripts/lib.js b/scripts/lib.js index 1ae4ca2..b435194 100644 --- a/scripts/lib.js +++ b/scripts/lib.js @@ -1,4 +1,4 @@ -(function(GLOBAL) { //lib v1.3.0c +(function(GLOBAL) { //lib v1.3.1 'use strict'; /* Utility Libraries required for Standard operations * All credits for these codes belong to their respective creators, moderators and owners. @@ -6,6 +6,37 @@ */ GLOBAL.cryptocoin = (typeof floGlobals === 'undefined' ? null : floGlobals.blockchain) || 'FLO'; + const getRandomBytes = (function() { + if (typeof require === 'function') { + const crypto = require('crypto'); + return function(buf) { + var bytes = crypto.randomBytes(buf.length); + buf.set(bytes); + return buf; + } + } else if (GLOBAL.crypto && GLOBAL.crypto.getRandomValues) { + return function(buf) { + return GLOBAL.crypto.getRandomValues(buf); + } + } else + throw Error('Unable to define getRandomBytes'); + })(); + + + GLOBAL.securedMathRandom = (function() { + if (typeof require === 'function') { + const crypto = require('crypto'); + return function() { + return crypto.randomBytes(4).readUInt32LE() / 0xffffffff; + } + } else if (GLOBAL.crypto && GLOBAL.crypto.getRandomValues) { + return function() { + return (GLOBAL.crypto.getRandomValues(new Uint32Array(1))[0] / 0xffffffff); + } + } else + throw Error('Unable to define securedMathRandom'); + })(); + //Crypto.js (function() { // Global Crypto object @@ -52,7 +83,7 @@ // Generate an array of any length of random bytes randomBytes: function(n) { for (var bytes = []; n > 0; n--) - bytes.push(Math.floor(Math.random() * 256)); + bytes.push(Math.floor(securedMathRandom() * 256)); return bytes; }, @@ -405,16 +436,6 @@ //SecureRandom.js (function() { - const getRandomValues = function(buf) { - if (typeof require === 'function') { - var bytes = require('crypto').randomBytes(buf.length); - buf.set(bytes) - return buf; - } else if (GLOBAL.crypto && GLOBAL.crypto.getRandomValues) - return GLOBAL.crypto.getRandomValues(buf); - else - return null; - } /*! * Random number generator with ArcFour PRNG @@ -446,10 +467,10 @@ // ba: byte array sr.prototype.nextBytes = function(ba) { var i; - if (getRandomValues && GLOBAL.Uint8Array) { + if (getRandomBytes && GLOBAL.Uint8Array) { try { var rvBytes = new Uint8Array(ba.length); - getRandomValues(rvBytes); + getRandomBytes(rvBytes); for (i = 0; i < ba.length; ++i) ba[i] = sr.getByte() ^ rvBytes[i]; return; @@ -549,23 +570,23 @@ sr.pool = new Array(); sr.pptr = 0; var t; - if (getRandomValues && GLOBAL.Uint8Array) { + if (getRandomBytes && GLOBAL.Uint8Array) { try { // Use webcrypto if available var ua = new Uint8Array(sr.poolSize); - getRandomValues(ua); + getRandomBytes(ua); for (t = 0; t < sr.poolSize; ++t) sr.pool[sr.pptr++] = ua[t]; } catch (e) { alert(e); } } - while (sr.pptr < sr.poolSize) { // extract some randomness from Math.random() - t = Math.floor(65536 * Math.random()); + while (sr.pptr < sr.poolSize) { // extract some randomness from securedMathRandom() + t = Math.floor(65536 * securedMathRandom()); sr.pool[sr.pptr++] = t >>> 8; sr.pool[sr.pptr++] = t & 255; } - sr.pptr = Math.floor(sr.poolSize * Math.random()); + sr.pptr = Math.floor(sr.poolSize * securedMathRandom()); sr.seedTime(); // entropy var entropyStr = ""; @@ -1654,7 +1675,7 @@ var a = nbi(); for (var i = 0; i < t; ++i) { //Pick bases at random, instead of starting at 2 - a.fromInt(lowprimes[Math.floor(Math.random() * lowprimes.length)]); + a.fromInt(lowprimes[Math.floor(securedMathRandom() * lowprimes.length)]); var y = a.modPow(r, this); if (y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) { var j = 1; @@ -2612,7 +2633,7 @@ pad: function(cipher, message) { var reqd = _requiredPadding(cipher, message); for (var i = 1; i < reqd; i++) { - message.push(Math.floor(Math.random() * 256)); + message.push(Math.floor(securedMathRandom() * 256)); } message.push(reqd); }, @@ -4782,8 +4803,8 @@ } else if (floDataCount < 253) { floDataCountString = floDataCount.toString(16); } else if (floDataCount <= 1040) { - floDataCountAdjusted = (floDataCount - 253) + parseInt("0xfd00fd"); - floDataCountStringAdjusted = floDataCountAdjusted.toString(16); + let floDataCountAdjusted = (floDataCount - 253) + parseInt("0xfd00fd"); + let floDataCountStringAdjusted = floDataCountAdjusted.toString(16); floDataCountString = floDataCountStringAdjusted.substr(0, 2) + floDataCountStringAdjusted.substr(4, 2) + floDataCountStringAdjusted.substr(2, 2); } else { floDataCountString = "Character Limit Exceeded"; @@ -6690,7 +6711,7 @@ /* retreive the balance from a given address */ coinjs.addressBalance = function(address, callback) { - coinjs.ajax(coinjs.host + '?uid=' + coinjs.uid + '&key=' + coinjs.key + '&setmodule=addresses&request=bal&address=' + address + '&r=' + Math.random(), callback, "GET"); + coinjs.ajax(coinjs.host + '?uid=' + coinjs.uid + '&key=' + coinjs.key + '&setmodule=addresses&request=bal&address=' + address + '&r=' + securedMathRandom(), callback, "GET"); } /* decompress an compressed public key */ @@ -7469,12 +7490,12 @@ /* list unspent transactions */ r.listUnspent = function(address, callback) { - coinjs.ajax(coinjs.host + '?uid=' + coinjs.uid + '&key=' + coinjs.key + '&setmodule=addresses&request=unspent&address=' + address + '&r=' + Math.random(), callback, "GET"); + coinjs.ajax(coinjs.host + '?uid=' + coinjs.uid + '&key=' + coinjs.key + '&setmodule=addresses&request=unspent&address=' + address + '&r=' + securedMathRandom(), callback, "GET"); } /* list transaction data */ r.getTransaction = function(txid, callback) { - coinjs.ajax(coinjs.host + '?uid=' + coinjs.uid + '&key=' + coinjs.key + '&setmodule=bitcoin&request=gettransaction&txid=' + txid + '&r=' + Math.random(), callback, "GET"); + coinjs.ajax(coinjs.host + '?uid=' + coinjs.uid + '&key=' + coinjs.key + '&setmodule=bitcoin&request=gettransaction&txid=' + txid + '&r=' + securedMathRandom(), callback, "GET"); } /* add unspent to transaction */ @@ -8566,7 +8587,7 @@ var l = length || 25; var chars = "!$%^&*()_+{}:@~?><|\./;'#][=-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; for (let x = 0; x < l; x++) { - r += chars.charAt(Math.floor(Math.random() * 62)); + r += chars.charAt(Math.floor(securedMathRandom() * 62)); } return r; } @@ -8595,7 +8616,7 @@ ], // warning for insecure PRNG - warning: 'WARNING:\nA secure random number generator was not found.\nUsing Math.random(), which is NOT cryptographically strong!' + warning: 'WARNING:\nA secure random number generator was not found.\nUsing securedMathRandom(), which is NOT cryptographically strong!' }; // Protected settings object @@ -8715,7 +8736,7 @@ str = null; while (str === null) { for (var i = 0; i < elems; i++) { - arr[i] = Math.floor(Math.random() * max + 1); + arr[i] = Math.floor(securedMathRandom() * max + 1); } str = construct(bits, arr, 10, bitsPerNum); } @@ -8724,7 +8745,7 @@ }; // Warn about using insecure rng. - // Called when Math.random() is being used. + // Called when securedMathRandom() is being used. function warn() { GLOBAL['console']['warn'](defaults.warning); if (typeof GLOBAL['alert'] === 'function' && config.alert) { @@ -9148,22 +9169,12 @@ //kbucket.js (function() { - const getRandomValues = function(buf) { - if (typeof require === 'function') { - var bytes = require('crypto').randomBytes(buf.length); - buf.set(bytes) - return buf; - } else if (GLOBAL.crypto && GLOBAL.crypto.getRandomValues) - return GLOBAL.crypto.getRandomValues(buf); - else - return null; - } // Kademlia DHT K-bucket implementation as a binary tree. // by 'Tristan Slominski' under 'MIT License' GLOBAL.BuildKBucket = function KBucket(options = {}) { if (!(this instanceof KBucket)) return new KBucket(options); - this.localNodeId = options.localNodeId || getRandomValues(new Uint8Array(20)) + this.localNodeId = options.localNodeId || getRandomBytes(new Uint8Array(20)) this.numberOfNodesPerKBucket = options.numberOfNodesPerKBucket || 20 this.numberOfNodesToPing = options.numberOfNodesToPing || 3 this.distance = options.distance || this.distance