Initial commit

This commit is contained in:
sairajzero 2021-08-03 15:44:30 +05:30
commit 0bcc3a0d81
8 changed files with 6967 additions and 0 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 sairajzero
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# FLO-signValidator
server to verify signature from floID

44
src/Server.js Normal file
View File

@ -0,0 +1,44 @@
const http = require('http');
const floCrypto = require('./floCrypto');
module.exports = function startServer(port){
const httpServer = http.createServer((req, res) => {
res.setHeader("Access-Control-Allow-Origin", "*");
if(req.method === "GET")
res.end("");
else if (req.method === "POST") {
//POST: All data processing (required JSON input)
let data = '';
req.on('data', chunk => data += chunk);
req.on('end', () => {
//process verification
let result = {};
try {
var d = JSON.parse(data);
if(!floCrypto.validateAddr(d.floID))
result.failed = "Invalid floID";
else if(floCrypto.getFloID(d.pubKey) !== d.floID)
result.failed = "Public key mismatched";
else if (!floCrypto.verifySign(d.message, d.sign, d.pubKey))
result.failed = "Signature not verified";
else
result.success = true;
} catch (error) {
result.Error = "Invalid request";
}finally{
res.end(JSON.stringify(result));
};
});
};
});
httpServer.listen(port, (err) => {
if (!err)
console.log(`Server running at port ${port}`);
});
Object.defineProperty(this, "port", {
get: () => port
});
Object.defineProperty(this, "http", {
get: () => httpServer
});
};

279
src/floCrypto.js Normal file
View File

@ -0,0 +1,279 @@
'use strict';
global.cryptocoin = "FLO";
const param = require('./param.json');
for (let p in param)
global[p] = param[p];
require('./lib');
(function(floCrypto) {
//var floCrypto = GLOBAL.floCrypto = {};
const p = BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16);
const ecparams = EllipticCurve.getSECCurveByName("secp256k1");
function exponent1() {
return p.add(BigInteger.ONE).divide(BigInteger("4"));
};
function calculateY(x) {
let exp = exponent1();
// x is x value of public key in BigInteger format without 02 or 03 or 04 prefix
return x.modPow(BigInteger("3"), p).add(BigInteger("7")).mod(p).modPow(exp, p);
};
function getUncompressedPublicKey(compressedPublicKey) {
// Fetch x from compressedPublicKey
let pubKeyBytes = Crypto.util.hexToBytes(compressedPublicKey);
const prefix = pubKeyBytes.shift(); // remove prefix
let prefix_modulus = prefix % 2;
pubKeyBytes.unshift(0); // add prefix 0
let x = new BigInteger(pubKeyBytes);
let xDecimalValue = x.toString();
// Fetch y
let y = calculateY(x);
let yDecimalValue = y.toString();
// verify y value
let resultBigInt = y.mod(BigInteger("2"));
let check = resultBigInt.toString() % 2;
if (prefix_modulus !== check)
yDecimalValue = y.negate().mod(p).toString();
return {
x: xDecimalValue,
y: yDecimalValue
};
};
function getSenderPublicKeyString() {
privateKey = ellipticCurveEncryption.senderRandom();
senderPublicKeyString = ellipticCurveEncryption.senderPublicString(privateKey);
return {
privateKey: privateKey,
senderPublicKeyString: senderPublicKeyString
};
};
function deriveSharedKeySender(receiverCompressedPublicKey, senderPrivateKey) {
try {
let receiverPublicKeyString = getUncompressedPublicKey(receiverCompressedPublicKey);
var senderDerivedKey = ellipticCurveEncryption.senderSharedKeyDerivation(
receiverPublicKeyString.x, receiverPublicKeyString.y, senderPrivateKey);
return senderDerivedKey;
} catch (error) {
return new Error(error);
};
};
function deriveReceiverSharedKey(senderPublicKeyString, receiverPrivateKey) {
return ellipticCurveEncryption.receiverSharedKeyDerivation(
senderPublicKeyString.XValuePublicString,
senderPublicKeyString.YValuePublicString, receiverPrivateKey);
};
function getReceiverPublicKeyString(privateKey) {
return ellipticCurveEncryption.receiverPublicString(privateKey);
};
function wifToDecimal(pk_wif, isPubKeyCompressed = false) {
let pk = Bitcoin.Base58.decode(pk_wif);
pk.shift();
pk.splice(-4, 4);
//If the private key corresponded to a compressed public key, also drop the last byte (it should be 0x01).
if (isPubKeyCompressed == true) pk.pop();
pk.unshift(0);
privateKeyDecimal = BigInteger(pk).toString();
privateKeyHex = Crypto.util.bytesToHex(pk);
return {
privateKeyDecimal: privateKeyDecimal,
privateKeyHex: privateKeyHex
};
};
//generate a random Interger within range
floCrypto.randInt = function(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
};
//generate a random String within length (options : alphaNumeric chars only)
floCrypto.randString = function(length, alphaNumeric = true) {
var result = '';
if (alphaNumeric)
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
else
var characters =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_+-./*?@#&$<>=[]{}():';
for (var i = 0; i < length; i++)
result += characters.charAt(Math.floor(Math.random() * characters.length));
return result;
};
//Encrypt Data using public-key
floCrypto.encryptData = function(data, publicKeyHex) {
var senderECKeyData = getSenderPublicKeyString();
var senderDerivedKey = deriveSharedKeySender(
publicKeyHex, senderECKeyData.privateKey);
let senderKey = senderDerivedKey.XValue + senderDerivedKey.YValue;
let secret = Crypto.AES.encrypt(data, senderKey);
return {
secret: secret,
senderPublicKeyString: senderECKeyData.senderPublicKeyString
};
};
//Decrypt Data using private-key
floCrypto.decryptData = function(data, privateKeyHex) {
var receiverECKeyData = {};
if (typeof privateKeyHex !== "string") throw new Error("No private key found.");
let privateKey = wifToDecimal(privateKeyHex, true);
if (typeof privateKey.privateKeyDecimal !== "string") throw new Error(
"Failed to detremine your private key.");
receiverECKeyData.privateKey = privateKey.privateKeyDecimal;
var receiverDerivedKey = deriveReceiverSharedKey(
data.senderPublicKeyString, receiverECKeyData.privateKey);
let receiverKey = receiverDerivedKey.XValue + receiverDerivedKey.YValue;
let decryptMsg = Crypto.AES.decrypt(data.secret, receiverKey);
return decryptMsg;
};
//Sign data using private-key
floCrypto.signData = function(data, privateKeyHex) {
var key = new Bitcoin.ECKey(privateKeyHex);
if(key.priv === null)
return false;
key.setCompressed(true);
//var privateKeyArr = key.getBitcoinPrivateKeyByteArray();
//var privateKey = BigInteger.fromByteArrayUnsigned(privateKeyArr);
var messageHash = Crypto.SHA256(data);
var messageHashBigInteger = new BigInteger(messageHash);
var messageSign = Bitcoin.ECDSA.sign(messageHashBigInteger, key.priv);
var sighex = Crypto.util.bytesToHex(messageSign);
return sighex;
};
//Verify signatue of the data using public-key
floCrypto.verifySign = function(data, signatureHex, publicKeyHex) {
var msgHash = Crypto.SHA256(data);
var messageHashBigInteger = new BigInteger(msgHash);
var sigBytes = Crypto.util.hexToBytes(signatureHex);
var signature = Bitcoin.ECDSA.parseSig(sigBytes);
var publicKeyPoint = ecparams.getCurve().decodePointHex(publicKeyHex);
var verify = Bitcoin.ECDSA.verifyRaw(messageHashBigInteger,
signature.r, signature.s, publicKeyPoint);
return verify;
};
//Generates a new flo ID and returns private-key, public-key and floID
floCrypto.generateNewID = function() {
try {
var key = new Bitcoin.ECKey(false);
key.setCompressed(true);
return {
floID: key.getBitcoinAddress(),
pubKey: key.getPubKeyHex(),
privKey: key.getBitcoinWalletImportFormat()
};
} catch (e) {
console.error(e);
};
};
//Returns public-key from private-key
floCrypto.getPubKeyHex = function(privateKeyHex) {
if (!privateKeyHex)
return null;
var key = new Bitcoin.ECKey(privateKeyHex);
if (key.priv == null)
return null;
key.setCompressed(true);
return key.getPubKeyHex();
};
//Returns flo-ID from public-key or private-key
floCrypto.getFloID = function(keyHex) {
if (!keyHex)
return null;
try {
var key = new Bitcoin.ECKey(keyHex);
if (key.priv == null)
key.setPub(keyHex);
return key.getBitcoinAddress();
} catch (e) {
return null;
};
};
//Verify the private-key for the given public-key or flo-ID
floCrypto.verifyPrivKey = function(privateKeyHex, publicHex_ID) {
if (!privateKeyHex || !publicHex_ID)
return false;
try {
var key = new Bitcoin.ECKey(privateKeyHex);
if (key.priv == null)
return false;
key.setCompressed(true);
if (publicHex_ID === key.getBitcoinAddress())
return true;
else if (publicHex_ID === key.getPubKeyHex())
return true;
else
return false;
} catch (e) {
console.error(e);
};
};
//Check if the given Address is valid or not
floCrypto.validateAddr = function(inpAddr) {
if (!inpAddr)
return false;
try {
var addr = new Bitcoin.Address(inpAddr);
return true;
} catch {
return false;
};
};
//Split the str using shamir's Secret and Returns the shares
floCrypto.createShamirsSecretShares = function(str, total_shares, threshold_limit) {
try {
if (str.length > 0) {
var strHex = shamirSecretShare.str2hex(str);
return shamirSecretShare.share(strHex, total_shares, threshold_limit);
};
return false;
} catch {
return false;
};
};
//Verifies the shares and str
floCrypto.verifyShamirsSecret = function(sharesArray, str) {
if(str == false)
return false;
try {
if (sharesArray.length > 0) {
var comb = shamirSecretShare.combine(sharesArray.slice(0, sharesArray.length));
return (shamirSecretShare.hex2str(comb) === str ? true : false);
};
return false;
} catch {
return false;
};
};
//Returns the retrived secret by combining the shamirs shares
floCrypto.retrieveShamirSecret = function(sharesArray) {
try {
if (sharesArray.length > 0) {
var comb = shamirSecretShare.combine(sharesArray.slice(0, sharesArray.length));
return shamirSecretShare.hex2str(comb);
};
return false;
} catch {
return false;
};
};
})(module.exports = {});

6578
src/lib.js Normal file

File diff suppressed because it is too large Load Diff

37
src/param.json Normal file
View File

@ -0,0 +1,37 @@
{
"screen": {
"height": 1160,
"width": 2000,
"colorDepth": 24,
"availHeight": 1080,
"availWidth": 1920,
"pixelDepth": 24
},
"navigator": {
"userAgent": "Node/14.17.3 (Linux; aarch64; arm)",
"plugins": [{
"name": "MySQL",
"filename": "mysql",
"description": "A node.js driver for mysql. It is written in JavaScript, does not require compiling, and is 100% MIT licensed."
}, {
"name": "WebSocket",
"filename": "ws",
"description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js"
}, {
"name": "Node fetch",
"filename": "node-fetch",
"description": "A light-weight module that brings window.fetch to node.js"
}],
"mimeTypes": [{
"description": "",
"type": "application/pdf",
"suffixes": "pdf"
}],
"cookieEnabled": true,
"language": "en-US"
},
"history": {
"length": 512
},
"location": "protocol://subdomain.example.domain/path"
}

4
start.js Normal file
View File

@ -0,0 +1,4 @@
const Server = require('./src/Server');
const port = process.argv[2] || 8080;
const serve = new Server(port);