Update floCrypto.js

This commit is contained in:
sairajzero 2021-09-24 03:31:03 +05:30
parent 5164d51146
commit 60f1a2742d

View File

@ -1,30 +1,36 @@
'use strict'; 'use strict';
(function(GLOBAL) { (function(GLOBAL) {
var floCrypto = GLOBAL.floCrypto = {}; const floCrypto = GLOBAL.floCrypto = {
const p = BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16);
const ecparams = EllipticCurve.getSECCurveByName("secp256k1");
function exponent1() { util: {
return p.add(BigInteger.ONE).divide(BigInteger("4")); p: BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16),
};
function calculateY(x) { ecparams: EllipticCurve.getSECCurveByName("secp256k1"),
let exp = exponent1();
asciiAlternatives: ` '\n '\n“ "\n” "\n --\n— ---\n≥ >=\n≤ <=\n≠ !=\n× *\n÷ /\n← <-\n→ ->\n↔ <->\n⇒ =>\n⇐ <=\n⇔ <=>`,
exponent1: function() {
return this.p.add(BigInteger.ONE).divide(BigInteger("4"))
},
calculateY: function(x) {
let p = this.p;
let exp = this.exponent1();
// x is x value of public key in BigInteger format without 02 or 03 or 04 prefix // 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); return x.modPow(BigInteger("3"), p).add(BigInteger("7")).mod(p).modPow(exp, p)
}; },
getUncompressedPublicKey: function(compressedPublicKey) {
function getUncompressedPublicKey(compressedPublicKey) { const p = this.p;
// Fetch x from compressedPublicKey // Fetch x from compressedPublicKey
let pubKeyBytes = Crypto.util.hexToBytes(compressedPublicKey); let pubKeyBytes = Crypto.util.hexToBytes(compressedPublicKey);
const prefix = pubKeyBytes.shift(); // remove prefix const prefix = pubKeyBytes.shift() // remove prefix
let prefix_modulus = prefix % 2; let prefix_modulus = prefix % 2;
pubKeyBytes.unshift(0); // add prefix 0 pubKeyBytes.unshift(0) // add prefix 0
let x = new BigInteger(pubKeyBytes); let x = new BigInteger(pubKeyBytes)
let xDecimalValue = x.toString(); let xDecimalValue = x.toString()
// Fetch y // Fetch y
let y = calculateY(x); let y = this.calculateY(x);
let yDecimalValue = y.toString(); let yDecimalValue = y.toString();
// verify y value // verify y value
let resultBigInt = y.mod(BigInteger("2")); let resultBigInt = y.mod(BigInteger("2"));
@ -35,63 +41,63 @@
x: xDecimalValue, x: xDecimalValue,
y: yDecimalValue y: yDecimalValue
}; };
}; },
function getSenderPublicKeyString() { getSenderPublicKeyString: function() {
privateKey = ellipticCurveEncryption.senderRandom(); privateKey = ellipticCurveEncryption.senderRandom();
senderPublicKeyString = ellipticCurveEncryption.senderPublicString(privateKey); senderPublicKeyString = ellipticCurveEncryption.senderPublicString(privateKey);
return { return {
privateKey: privateKey, privateKey: privateKey,
senderPublicKeyString: senderPublicKeyString senderPublicKeyString: senderPublicKeyString
}; }
}; },
function deriveSharedKeySender(receiverCompressedPublicKey, senderPrivateKey) { deriveSharedKeySender: function(receiverCompressedPublicKey, senderPrivateKey) {
try { let receiverPublicKeyString = this.getUncompressedPublicKey(receiverCompressedPublicKey);
let receiverPublicKeyString = getUncompressedPublicKey(receiverCompressedPublicKey);
var senderDerivedKey = ellipticCurveEncryption.senderSharedKeyDerivation( var senderDerivedKey = ellipticCurveEncryption.senderSharedKeyDerivation(
receiverPublicKeyString.x, receiverPublicKeyString.y, senderPrivateKey); receiverPublicKeyString.x, receiverPublicKeyString.y, senderPrivateKey);
return senderDerivedKey; return senderDerivedKey;
} catch (error) { },
return new Error(error);
};
};
function deriveReceiverSharedKey(senderPublicKeyString, receiverPrivateKey) { deriveReceiverSharedKey: function(senderPublicKeyString, receiverPrivateKey) {
return ellipticCurveEncryption.receiverSharedKeyDerivation( return ellipticCurveEncryption.receiverSharedKeyDerivation(
senderPublicKeyString.XValuePublicString, senderPublicKeyString.XValuePublicString, senderPublicKeyString.YValuePublicString, receiverPrivateKey);
senderPublicKeyString.YValuePublicString, receiverPrivateKey); },
};
function getReceiverPublicKeyString(privateKey) { getReceiverPublicKeyString: function(privateKey) {
return ellipticCurveEncryption.receiverPublicString(privateKey); return ellipticCurveEncryption.receiverPublicString(privateKey);
}; },
function wifToDecimal(pk_wif, isPubKeyCompressed = false) { deriveSharedKeyReceiver: function(senderPublicKeyString, receiverPrivateKey) {
let pk = Bitcoin.Base58.decode(pk_wif); return ellipticCurveEncryption.receiverSharedKeyDerivation(
pk.shift(); senderPublicKeyString.XValuePublicString, senderPublicKeyString.YValuePublicString, receiverPrivateKey);
pk.splice(-4, 4); },
wifToDecimal: function(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 the private key corresponded to a compressed public key, also drop the last byte (it should be 0x01).
if (isPubKeyCompressed == true) pk.pop(); if (isPubKeyCompressed == true) pk.pop()
pk.unshift(0); pk.unshift(0)
privateKeyDecimal = BigInteger(pk).toString(); privateKeyDecimal = BigInteger(pk).toString()
privateKeyHex = Crypto.util.bytesToHex(pk); privateKeyHex = Crypto.util.bytesToHex(pk)
return { return {
privateKeyDecimal: privateKeyDecimal, privateKeyDecimal: privateKeyDecimal,
privateKeyHex: privateKeyHex privateKeyHex: privateKeyHex
}; }
}; }
},
//generate a random Interger within range //generate a random Interger within range
floCrypto.randInt = function(min, max) { randInt: function(min, max) {
min = Math.ceil(min); min = Math.ceil(min);
max = Math.floor(max); max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min; return Math.floor(Math.random() * (max - min + 1)) + min;
}; },
//generate a random String within length (options : alphaNumeric chars only) //generate a random String within length (options : alphaNumeric chars only)
floCrypto.randString = function(length, alphaNumeric = true) { randString: function(length, alphaNumeric = true) {
var result = ''; var result = '';
if (alphaNumeric) if (alphaNumeric)
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
@ -101,65 +107,73 @@
for (var i = 0; i < length; i++) for (var i = 0; i < length; i++)
result += characters.charAt(Math.floor(Math.random() * characters.length)); result += characters.charAt(Math.floor(Math.random() * characters.length));
return result; return result;
}; },
//Encrypt Data using public-key //Encrypt Data using public-key
floCrypto.encryptData = function(data, publicKeyHex) { encryptData: function(data, receiverCompressedPublicKey) {
var senderECKeyData = getSenderPublicKeyString(); var senderECKeyData = this.util.getSenderPublicKeyString();
var senderDerivedKey = deriveSharedKeySender( var senderDerivedKey = this.util.deriveSharedKeySender(receiverCompressedPublicKey, senderECKeyData
publicKeyHex, senderECKeyData.privateKey); .privateKey);
let senderKey = senderDerivedKey.XValue + senderDerivedKey.YValue; let senderKey = senderDerivedKey.XValue + senderDerivedKey.YValue;
let secret = Crypto.AES.encrypt(data, senderKey); let secret = Crypto.AES.encrypt(data, senderKey);
return { return {
secret: secret, secret: secret,
senderPublicKeyString: senderECKeyData.senderPublicKeyString senderPublicKeyString: senderECKeyData.senderPublicKeyString
}; };
}; },
//Decrypt Data using private-key //Decrypt Data using private-key
floCrypto.decryptData = function(data, privateKeyHex) { decryptData: function(data, myPrivateKey) {
var receiverECKeyData = {}; var receiverECKeyData = {};
if (typeof privateKeyHex !== "string") throw new Error("No private key found."); if (typeof myPrivateKey !== "string") throw new Error("No private key found.");
let privateKey = wifToDecimal(privateKeyHex, true);
let privateKey = this.util.wifToDecimal(myPrivateKey, true);
if (typeof privateKey.privateKeyDecimal !== "string") throw new Error( if (typeof privateKey.privateKeyDecimal !== "string") throw new Error(
"Failed to detremine your private key."); "Failed to detremine your private key.");
receiverECKeyData.privateKey = privateKey.privateKeyDecimal; receiverECKeyData.privateKey = privateKey.privateKeyDecimal;
var receiverDerivedKey = deriveReceiverSharedKey(
data.senderPublicKeyString, receiverECKeyData.privateKey); var receiverDerivedKey = this.util.deriveReceiverSharedKey(data.senderPublicKeyString,
receiverECKeyData
.privateKey);
let receiverKey = receiverDerivedKey.XValue + receiverDerivedKey.YValue; let receiverKey = receiverDerivedKey.XValue + receiverDerivedKey.YValue;
let decryptMsg = Crypto.AES.decrypt(data.secret, receiverKey); let decryptMsg = Crypto.AES.decrypt(data.secret, receiverKey);
return decryptMsg; return decryptMsg;
}; },
//Sign data using private-key //Sign data using private-key
floCrypto.signData = function(data, privateKeyHex) { signData: function(data, privateKeyHex) {
var key = new Bitcoin.ECKey(privateKeyHex); var key = new Bitcoin.ECKey(privateKeyHex);
if(key.priv === null)
return false;
key.setCompressed(true); key.setCompressed(true);
//var privateKeyArr = key.getBitcoinPrivateKeyByteArray();
//var privateKey = BigInteger.fromByteArrayUnsigned(privateKeyArr); var privateKeyArr = key.getBitcoinPrivateKeyByteArray();
privateKey = BigInteger.fromByteArrayUnsigned(privateKeyArr);
var messageHash = Crypto.SHA256(data); var messageHash = Crypto.SHA256(data);
var messageHashBigInteger = new BigInteger(messageHash); var messageHashBigInteger = new BigInteger(messageHash);
var messageSign = Bitcoin.ECDSA.sign(messageHashBigInteger, key.priv); var messageSign = Bitcoin.ECDSA.sign(messageHashBigInteger, key.priv);
var sighex = Crypto.util.bytesToHex(messageSign); var sighex = Crypto.util.bytesToHex(messageSign);
return sighex; return sighex;
}; },
//Verify signatue of the data using public-key //Verify signatue of the data using public-key
floCrypto.verifySign = function(data, signatureHex, publicKeyHex) { verifySign: function(data, signatureHex, publicKeyHex) {
var msgHash = Crypto.SHA256(data); var msgHash = Crypto.SHA256(data);
var messageHashBigInteger = new BigInteger(msgHash); var messageHashBigInteger = new BigInteger(msgHash);
var sigBytes = Crypto.util.hexToBytes(signatureHex); var sigBytes = Crypto.util.hexToBytes(signatureHex);
var signature = Bitcoin.ECDSA.parseSig(sigBytes); var signature = Bitcoin.ECDSA.parseSig(sigBytes);
var publicKeyPoint = ecparams.getCurve().decodePointHex(publicKeyHex);
var verify = Bitcoin.ECDSA.verifyRaw(messageHashBigInteger, var publicKeyPoint = this.util.ecparams.getCurve().decodePointHex(publicKeyHex);
signature.r, signature.s, publicKeyPoint);
var verify = Bitcoin.ECDSA.verifyRaw(messageHashBigInteger, signature.r, signature.s,
publicKeyPoint);
return verify; return verify;
}; },
//Generates a new flo ID and returns private-key, public-key and floID //Generates a new flo ID and returns private-key, public-key and floID
floCrypto.generateNewID = function() { generateNewID: function() {
try { try {
var key = new Bitcoin.ECKey(false); var key = new Bitcoin.ECKey(false);
key.setCompressed(true); key.setCompressed(true);
@ -167,14 +181,14 @@
floID: key.getBitcoinAddress(), floID: key.getBitcoinAddress(),
pubKey: key.getPubKeyHex(), pubKey: key.getPubKeyHex(),
privKey: key.getBitcoinWalletImportFormat() privKey: key.getBitcoinWalletImportFormat()
}; }
} catch (e) { } catch (e) {
console.error(e); console.error(e);
}; }
}; },
//Returns public-key from private-key //Returns public-key from private-key
floCrypto.getPubKeyHex = function(privateKeyHex) { getPubKeyHex: function(privateKeyHex) {
if (!privateKeyHex) if (!privateKeyHex)
return null; return null;
var key = new Bitcoin.ECKey(privateKeyHex); var key = new Bitcoin.ECKey(privateKeyHex);
@ -182,10 +196,10 @@
return null; return null;
key.setCompressed(true); key.setCompressed(true);
return key.getPubKeyHex(); return key.getPubKeyHex();
}; },
//Returns flo-ID from public-key or private-key //Returns flo-ID from public-key or private-key
floCrypto.getFloID = function(keyHex) { getFloID: function(keyHex) {
if (!keyHex) if (!keyHex)
return null; return null;
try { try {
@ -195,31 +209,31 @@
return key.getBitcoinAddress(); return key.getBitcoinAddress();
} catch (e) { } catch (e) {
return null; return null;
}; }
}; },
//Verify the private-key for the given public-key or flo-ID //Verify the private-key for the given public-key or flo-ID
floCrypto.verifyPrivKey = function(privateKeyHex, publicHex_ID) { verifyPrivKey: function(privateKeyHex, pubKey_floID, isfloID = true) {
if (!privateKeyHex || !publicHex_ID) if (!privateKeyHex || !pubKey_floID)
return false; return false;
try { try {
var key = new Bitcoin.ECKey(privateKeyHex); var key = new Bitcoin.ECKey(privateKeyHex);
if (key.priv == null) if (key.priv == null)
return false; return false;
key.setCompressed(true); key.setCompressed(true);
if (publicHex_ID === key.getBitcoinAddress()) if (isfloID && pubKey_floID == key.getBitcoinAddress())
return true; return true;
else if (publicHex_ID === key.getPubKeyHex()) else if (!isfloID && pubKey_floID == key.getPubKeyHex())
return true; return true;
else else
return false; return false;
} catch (e) { } catch (e) {
console.error(e); console.error(e);
}; }
}; },
//Check if the given Address is valid or not //Check if the given Address is valid or not
floCrypto.validateAddr = function(inpAddr) { validateAddr: function(inpAddr) {
if (!inpAddr) if (!inpAddr)
return false; return false;
try { try {
@ -227,48 +241,99 @@
return true; return true;
} catch { } catch {
return false; return false;
}; }
}; },
//Split the str using shamir's Secret and Returns the shares //Split the str using shamir's Secret and Returns the shares
floCrypto.createShamirsSecretShares = function(str, total_shares, threshold_limit) { createShamirsSecretShares: function(str, total_shares, threshold_limit) {
try { try {
if (str.length > 0) { if (str.length > 0) {
var strHex = shamirSecretShare.str2hex(str); var strHex = shamirSecretShare.str2hex(str);
return shamirSecretShare.share(strHex, total_shares, threshold_limit); var shares = shamirSecretShare.share(strHex, total_shares, threshold_limit);
}; return shares;
}
return false; return false;
} catch { } catch {
return false; return false
}; }
}; },
//Verifies the shares and str //Verifies the shares and str
floCrypto.verifyShamirsSecret = function(sharesArray, str) { verifyShamirsSecret: function(sharesArray, str) {
if(str == false) return (str && this.retrieveShamirSecret(sharesArray) === str)
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 //Returns the retrived secret by combining the shamirs shares
floCrypto.retrieveShamirSecret = function(sharesArray) { retrieveShamirSecret: function(sharesArray) {
try { try {
if (sharesArray.length > 0) { if (sharesArray.length > 0) {
var comb = shamirSecretShare.combine(sharesArray.slice(0, sharesArray.length)); var comb = shamirSecretShare.combine(sharesArray.slice(0, sharesArray.length));
return shamirSecretShare.hex2str(comb); comb = shamirSecretShare.hex2str(comb);
}; return comb;
}
return false; return false;
} catch { } catch {
return false; return false;
}; }
}; },
validateASCII: function(string, bool = true) {
if (typeof string !== "string")
return null;
if (bool) {
let x;
for (let i = 0; i < string.length; i++) {
x = string.charCodeAt(i);
if (x < 32 || x > 127)
return false;
}
return true;
} else {
let x, invalids = {};
for (let i = 0; i < string.length; i++) {
x = string.charCodeAt(i);
if (x < 32 || x > 127)
if (x in invalids)
invalids[string[i]].push(i)
else
invalids[string[i]] = [i];
}
if (Object.keys(invalids).length)
return invalids;
else
return true;
}
},
convertToASCII: function(string, mode = 'soft-remove') {
let chars = this.validateASCII(string, false);
if (chars === true)
return string;
else if (chars === null)
return null;
let convertor, result = string,
refAlt = {};
this.util.asciiAlternatives.split('\n').forEach(a => refAlt[a[0]] = a.slice(2));
mode = mode.toLowerCase();
if (mode === "hard-unicode")
convertor = (c) => `\\u${('000'+c.charCodeAt().toString(16)).slice(-4)}`;
else if (mode === "soft-unicode")
convertor = (c) => refAlt[c] || `\\u${('000'+c.charCodeAt().toString(16)).slice(-4)}`;
else if (mode === "hard-remove")
convertor = c => "";
else if (mode === "soft-remove")
convertor = c => refAlt[c] || "";
else
return null;
for (let c in chars)
result = result.replaceAll(c, convertor(c));
return result;
},
revertUnicode: function(string) {
return string.replace(/\\u[\dA-F]{4}/gi,
m => String.fromCharCode(parseInt(m.replace(/\\u/g, ''), 16)));
}
}
})(typeof global !== "undefined" ? global : window); })(typeof global !== "undefined" ? global : window);