mirror of
https://github.com/Qortal/chrome-extension.git
synced 2025-02-14 11:15:49 +00:00
started oauth
This commit is contained in:
parent
0e2816f57e
commit
30c6a8b024
@ -62,6 +62,35 @@ document.addEventListener('qortalExtensionRequests', async (event) => {
|
||||
}));
|
||||
}
|
||||
});
|
||||
} else if (type === 'REQUEST_OAUTH') {
|
||||
const hostname = window.location.hostname
|
||||
const res = await connection(hostname)
|
||||
if(!res){
|
||||
document.dispatchEvent(new CustomEvent('qortalExtensionResponses', {
|
||||
detail: { type: "OAUTH", data: {
|
||||
error: "Not authorized"
|
||||
}, requestId }
|
||||
}));
|
||||
return
|
||||
}
|
||||
chrome.runtime.sendMessage({ action: "oauth", payload: {
|
||||
nodeBaseUrl,
|
||||
senderAddress,
|
||||
senderPublicKey, timestamp
|
||||
}}, (response) => {
|
||||
if (response.error) {
|
||||
document.dispatchEvent(new CustomEvent('qortalExtensionResponses', {
|
||||
detail: { type: "OAUTH", data: {
|
||||
error: response.error
|
||||
}, requestId }
|
||||
}));
|
||||
} else {
|
||||
// Include the requestId in the detail when dispatching the response
|
||||
document.dispatchEvent(new CustomEvent('qortalExtensionResponses', {
|
||||
detail: { type: "OAUTH", data: response, requestId }
|
||||
}));
|
||||
}
|
||||
});
|
||||
} else if (type === 'REQUEST_AUTHENTICATION') {
|
||||
const hostname = window.location.hostname
|
||||
const res = await connection(hostname)
|
||||
|
@ -1,6 +1,7 @@
|
||||
// @ts-nocheck
|
||||
import Base58 from "./deps/Base58";
|
||||
import { createTransaction } from "./transactions/transactions";
|
||||
import { decryptChatMessage } from "./utils/decryptChatMessage";
|
||||
import { decryptStoredWallet } from "./utils/decryptWallet";
|
||||
import PhraseWallet from "./utils/generateWallet/phrase-wallet";
|
||||
import { validateAddress } from "./utils/validateAddress";
|
||||
@ -132,8 +133,10 @@ const processTransactionVersion2 = async (body: any, validApi: string) => {
|
||||
});
|
||||
};
|
||||
|
||||
const transaction = async ({ type, params, apiVersion, keyPair }: any, validApi) => {
|
||||
|
||||
const transaction = async (
|
||||
{ type, params, apiVersion, keyPair }: any,
|
||||
validApi
|
||||
) => {
|
||||
const tx = createTransaction(type, keyPair, params);
|
||||
let res;
|
||||
|
||||
@ -155,20 +158,22 @@ const makeTransactionRequest = async (
|
||||
keyPair,
|
||||
validApi
|
||||
) => {
|
||||
|
||||
const myTxnrequest = await transaction({
|
||||
nonce: 0,
|
||||
type: 2,
|
||||
params: {
|
||||
recipient: receiver,
|
||||
// recipientName: recipientName,
|
||||
amount: amount,
|
||||
lastReference: lastRef,
|
||||
fee: fee,
|
||||
const myTxnrequest = await transaction(
|
||||
{
|
||||
nonce: 0,
|
||||
type: 2,
|
||||
params: {
|
||||
recipient: receiver,
|
||||
// recipientName: recipientName,
|
||||
amount: amount,
|
||||
lastReference: lastRef,
|
||||
fee: fee,
|
||||
},
|
||||
apiVersion: 2,
|
||||
keyPair,
|
||||
},
|
||||
apiVersion: 2,
|
||||
keyPair,
|
||||
}, validApi);
|
||||
validApi
|
||||
);
|
||||
return myTxnrequest;
|
||||
};
|
||||
|
||||
@ -214,7 +219,7 @@ async function getNameOrAddress(receiver) {
|
||||
if (!response?.ok) throw new Error("Cannot fetch name");
|
||||
return { error: "cannot validate address or name" };
|
||||
} catch (error) {
|
||||
throw new Error(error?.message || "cannot validate address or name")
|
||||
throw new Error(error?.message || "cannot validate address or name");
|
||||
}
|
||||
}
|
||||
async function sendCoin({ password, amount, receiver }) {
|
||||
@ -238,7 +243,67 @@ async function sendCoin({ password, amount, receiver }) {
|
||||
wallet2._addresses[0].keyPair,
|
||||
validApi
|
||||
);
|
||||
return {res, validApi};
|
||||
return { res, validApi };
|
||||
} catch (error) {
|
||||
throw new Error(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
function fetchMessages(apiCall) {
|
||||
let retryDelay = 2000; // Start with a 2-second delay
|
||||
const maxDuration = 360000; // Maximum duration set to 6 minutes
|
||||
const startTime = Date.now(); // Record the start time
|
||||
|
||||
// Promise to handle polling logic
|
||||
return new Promise((resolve, reject) => {
|
||||
const attemptFetch = async () => {
|
||||
if (Date.now() - startTime > maxDuration) {
|
||||
return reject(new Error("Maximum polling time exceeded"));
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(apiCall);
|
||||
const data = await response.json();
|
||||
|
||||
if (data && data.length > 0) {
|
||||
resolve(data); // Resolve the promise when data is found
|
||||
} else {
|
||||
console.log("No items found, retrying in", retryDelay / 1000, "seconds...");
|
||||
setTimeout(attemptFetch, retryDelay);
|
||||
retryDelay = Math.min(retryDelay * 2, 360000); // Ensure delay does not exceed 6 minutes
|
||||
}
|
||||
} catch (error) {
|
||||
reject(error); // Reject the promise on error
|
||||
}
|
||||
};
|
||||
|
||||
attemptFetch(); // Initial call to start the polling
|
||||
});
|
||||
}
|
||||
|
||||
async function listenForChatMessage({ nodeBaseUrl, senderAddress, senderPublicKey, timestamp }) {
|
||||
try {
|
||||
let validApi = "";
|
||||
const checkIfNodeBaseUrlIsAcceptable = apiEndpoints.find(
|
||||
(item) => item === nodeBaseUrl
|
||||
);
|
||||
if (checkIfNodeBaseUrlIsAcceptable) {
|
||||
validApi = checkIfNodeBaseUrlIsAcceptable;
|
||||
} else {
|
||||
validApi = await findUsableApi();
|
||||
}
|
||||
const wallet = await getSaveWallet();
|
||||
const address = wallet.address0;
|
||||
const before = timestamp + 5000
|
||||
const after = timestamp - 5000
|
||||
const apiCall = `${validApi}/chat/messages?involving=${senderAddress}&involving=${address}&reverse=true&limit=1&before=${before}&after=${after}}`;
|
||||
const encodedMessageObj = await fetchMessages(apiCall)
|
||||
console.log({encodedMessageObj})
|
||||
const response = await decryptStoredWallet(password, wallet);
|
||||
const wallet2 = new PhraseWallet(response, walletVersion);
|
||||
const decodedMessage = decryptChatMessage(encodedMessageObj.data, wallet2._addresses[0].keyPair.privateKey, senderPublicKey, encodedMessageObj.reference)
|
||||
console.log({decodedMessage})
|
||||
return { secretCode: decodedMessage };
|
||||
} catch (error) {
|
||||
throw new Error(error.message);
|
||||
}
|
||||
@ -321,6 +386,21 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "oauth": {
|
||||
const { nodeBaseUrl, senderAddress, senderPublicKey, timestamp } = request.payload;
|
||||
|
||||
listenForChatMessage({ nodeBaseUrl, senderAddress, senderPublicKey, timestamp })
|
||||
.then(({ secretCode }) => {
|
||||
sendResponse(secretCode);
|
||||
})
|
||||
.catch((error) => {
|
||||
sendResponse({ error: error.message });
|
||||
console.error(error.message);
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
case "authentication":
|
||||
{
|
||||
getSaveWallet()
|
||||
@ -333,7 +413,6 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
chrome.windows.getAll(
|
||||
{ populate: true, windowTypes: ["popup"] },
|
||||
(windows) => {
|
||||
|
||||
// Attempt to find an existing popup window that has a tab with the correct URL
|
||||
const existingPopup = windows.find(
|
||||
(w) =>
|
||||
@ -396,7 +475,9 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
let intervalId = null;
|
||||
const startTime = Date.now();
|
||||
const checkInterval = 3000; // Check every 3 seconds
|
||||
const timeout = request.timeout ? 0.75 * (request.timeout * 1000) : 60000; // Stop after 15 seconds
|
||||
const timeout = request.timeout
|
||||
? 0.75 * (request.timeout * 1000)
|
||||
: 60000; // Stop after 15 seconds
|
||||
|
||||
const checkFunction = () => {
|
||||
getSaveWallet()
|
||||
@ -439,7 +520,6 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
chrome.windows.getAll(
|
||||
{ populate: true, windowTypes: ["popup"] },
|
||||
(windows) => {
|
||||
|
||||
// Attempt to find an existing popup window that has a tab with the correct URL
|
||||
const existingPopup = windows.find(
|
||||
(w) =>
|
||||
@ -515,7 +595,6 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
chrome.windows.getAll(
|
||||
{ populate: true, windowTypes: ["popup"] },
|
||||
(windows) => {
|
||||
|
||||
// Attempt to find an existing popup window that has a tab with the correct URL
|
||||
const existingPopup = windows.find(
|
||||
(w) =>
|
||||
@ -557,7 +636,6 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
|
||||
const interactionId = Date.now().toString(); // Simple example; consider a better unique ID
|
||||
|
||||
|
||||
setTimeout(() => {
|
||||
chrome.runtime.sendMessage({
|
||||
action: "SET_COUNTDOWN",
|
||||
@ -638,33 +716,30 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
}
|
||||
|
||||
break;
|
||||
case "logout" : {
|
||||
chrome.storage.local.remove('walletInfo', () => {
|
||||
if (chrome.runtime.lastError) {
|
||||
// Handle error
|
||||
console.error(chrome.runtime.lastError.message);
|
||||
} else {
|
||||
// Data removed successfully
|
||||
sendResponse(true)
|
||||
}
|
||||
});
|
||||
|
||||
case "logout":
|
||||
{
|
||||
chrome.storage.local.remove("walletInfo", () => {
|
||||
if (chrome.runtime.lastError) {
|
||||
// Handle error
|
||||
console.error(chrome.runtime.lastError.message);
|
||||
} else {
|
||||
// Data removed successfully
|
||||
sendResponse(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
|
||||
chrome.action.onClicked.addListener((tab) => {
|
||||
const popupUrl = chrome.runtime.getURL("index.html");
|
||||
chrome.windows.getAll(
|
||||
{ populate: true, windowTypes: ["popup"] },
|
||||
(windows) => {
|
||||
|
||||
// Attempt to find an existing popup window that has a tab with the correct URL
|
||||
const existingPopup = windows.find(
|
||||
(w) =>
|
||||
|
266
src/deps/ed2curve.ts
Normal file
266
src/deps/ed2curve.ts
Normal file
@ -0,0 +1,266 @@
|
||||
// @ts-nocheck
|
||||
|
||||
/*
|
||||
* ed2curve: convert Ed25519 signing key pair into Curve25519
|
||||
* key pair suitable for Diffie-Hellman key exchange.
|
||||
*
|
||||
* Written by Dmitry Chestnykh in 2014. Public domain.
|
||||
*/
|
||||
/* jshint newcap: false */
|
||||
|
||||
/*
|
||||
Change to es6 import/export
|
||||
*/
|
||||
|
||||
import nacl from './nacl-fast'
|
||||
|
||||
// (function(root, f) {
|
||||
// 'use strict';
|
||||
// if (typeof module !== 'undefined' && module.exports) module.exports = f(require('tweetnacl'));
|
||||
// else root.ed2curve = f(root.nacl);
|
||||
// }(this, function(nacl) {
|
||||
// 'use strict';
|
||||
// if (!nacl) throw new Error('tweetnacl not loaded');
|
||||
|
||||
// -- Operations copied from TweetNaCl.js. --
|
||||
|
||||
var gf = function(init) {
|
||||
var i, r = new Float64Array(16);
|
||||
if (init) for (i = 0; i < init.length; i++) r[i] = init[i];
|
||||
return r;
|
||||
};
|
||||
|
||||
var gf0 = gf(),
|
||||
gf1 = gf([1]),
|
||||
D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]),
|
||||
I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]);
|
||||
|
||||
function car25519(o) {
|
||||
var c;
|
||||
var i;
|
||||
for (i = 0; i < 16; i++) {
|
||||
o[i] += 65536;
|
||||
c = Math.floor(o[i] / 65536);
|
||||
o[(i+1)*(i<15?1:0)] += c - 1 + 37 * (c-1) * (i===15?1:0);
|
||||
o[i] -= (c * 65536);
|
||||
}
|
||||
}
|
||||
|
||||
function sel25519(p, q, b) {
|
||||
var t, c = ~(b-1);
|
||||
for (var i = 0; i < 16; i++) {
|
||||
t = c & (p[i] ^ q[i]);
|
||||
p[i] ^= t;
|
||||
q[i] ^= t;
|
||||
}
|
||||
}
|
||||
|
||||
function unpack25519(o, n) {
|
||||
var i;
|
||||
for (i = 0; i < 16; i++) o[i] = n[2*i] + (n[2*i+1] << 8);
|
||||
o[15] &= 0x7fff;
|
||||
}
|
||||
|
||||
// addition
|
||||
function A(o, a, b) {
|
||||
var i;
|
||||
for (i = 0; i < 16; i++) o[i] = (a[i] + b[i])|0;
|
||||
}
|
||||
|
||||
// subtraction
|
||||
function Z(o, a, b) {
|
||||
var i;
|
||||
for (i = 0; i < 16; i++) o[i] = (a[i] - b[i])|0;
|
||||
}
|
||||
|
||||
// multiplication
|
||||
function M(o, a, b) {
|
||||
var i, j, t = new Float64Array(31);
|
||||
for (i = 0; i < 31; i++) t[i] = 0;
|
||||
for (i = 0; i < 16; i++) {
|
||||
for (j = 0; j < 16; j++) {
|
||||
t[i+j] += a[i] * b[j];
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 15; i++) {
|
||||
t[i] += 38 * t[i+16];
|
||||
}
|
||||
for (i = 0; i < 16; i++) o[i] = t[i];
|
||||
car25519(o);
|
||||
car25519(o);
|
||||
}
|
||||
|
||||
// squaring
|
||||
function S(o, a) {
|
||||
M(o, a, a);
|
||||
}
|
||||
|
||||
// inversion
|
||||
function inv25519(o, i) {
|
||||
var c = gf();
|
||||
var a;
|
||||
for (a = 0; a < 16; a++) c[a] = i[a];
|
||||
for (a = 253; a >= 0; a--) {
|
||||
S(c, c);
|
||||
if(a !== 2 && a !== 4) M(c, c, i);
|
||||
}
|
||||
for (a = 0; a < 16; a++) o[a] = c[a];
|
||||
}
|
||||
|
||||
function pack25519(o, n) {
|
||||
var i, j, b;
|
||||
var m = gf(), t = gf();
|
||||
for (i = 0; i < 16; i++) t[i] = n[i];
|
||||
car25519(t);
|
||||
car25519(t);
|
||||
car25519(t);
|
||||
for (j = 0; j < 2; j++) {
|
||||
m[0] = t[0] - 0xffed;
|
||||
for (i = 1; i < 15; i++) {
|
||||
m[i] = t[i] - 0xffff - ((m[i-1]>>16) & 1);
|
||||
m[i-1] &= 0xffff;
|
||||
}
|
||||
m[15] = t[15] - 0x7fff - ((m[14]>>16) & 1);
|
||||
b = (m[15]>>16) & 1;
|
||||
m[14] &= 0xffff;
|
||||
sel25519(t, m, 1-b);
|
||||
}
|
||||
for (i = 0; i < 16; i++) {
|
||||
o[2*i] = t[i] & 0xff;
|
||||
o[2*i+1] = t[i] >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
function par25519(a) {
|
||||
var d = new Uint8Array(32);
|
||||
pack25519(d, a);
|
||||
return d[0] & 1;
|
||||
}
|
||||
|
||||
function vn(x, xi, y, yi, n) {
|
||||
var i, d = 0;
|
||||
for (i = 0; i < n; i++) d |= x[xi + i] ^ y[yi + i];
|
||||
return (1 & ((d - 1) >>> 8)) - 1;
|
||||
}
|
||||
|
||||
function crypto_verify_32(x, xi, y, yi) {
|
||||
return vn(x, xi, y, yi, 32);
|
||||
}
|
||||
|
||||
function neq25519(a, b) {
|
||||
var c = new Uint8Array(32), d = new Uint8Array(32);
|
||||
pack25519(c, a);
|
||||
pack25519(d, b);
|
||||
return crypto_verify_32(c, 0, d, 0);
|
||||
}
|
||||
|
||||
function pow2523(o, i) {
|
||||
var c = gf();
|
||||
var a;
|
||||
for (a = 0; a < 16; a++) c[a] = i[a];
|
||||
for (a = 250; a >= 0; a--) {
|
||||
S(c, c);
|
||||
if (a !== 1) M(c, c, i);
|
||||
}
|
||||
for (a = 0; a < 16; a++) o[a] = c[a];
|
||||
}
|
||||
|
||||
function set25519(r, a) {
|
||||
var i;
|
||||
for (i = 0; i < 16; i++) r[i] = a[i] | 0;
|
||||
}
|
||||
|
||||
function unpackneg(r, p) {
|
||||
var t = gf(), chk = gf(), num = gf(),
|
||||
den = gf(), den2 = gf(), den4 = gf(),
|
||||
den6 = gf();
|
||||
|
||||
set25519(r[2], gf1);
|
||||
unpack25519(r[1], p);
|
||||
S(num, r[1]);
|
||||
M(den, num, D);
|
||||
Z(num, num, r[2]);
|
||||
A(den, r[2], den);
|
||||
|
||||
S(den2, den);
|
||||
S(den4, den2);
|
||||
M(den6, den4, den2);
|
||||
M(t, den6, num);
|
||||
M(t, t, den);
|
||||
|
||||
pow2523(t, t);
|
||||
M(t, t, num);
|
||||
M(t, t, den);
|
||||
M(t, t, den);
|
||||
M(r[0], t, den);
|
||||
|
||||
S(chk, r[0]);
|
||||
M(chk, chk, den);
|
||||
if (neq25519(chk, num)) M(r[0], r[0], I);
|
||||
|
||||
S(chk, r[0]);
|
||||
M(chk, chk, den);
|
||||
if (neq25519(chk, num)) return -1;
|
||||
|
||||
if (par25519(r[0]) === (p[31] >> 7)) Z(r[0], gf0, r[0]);
|
||||
|
||||
M(r[3], r[0], r[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
// Converts Ed25519 public key to Curve25519 public key.
|
||||
// montgomeryX = (edwardsY + 1)*inverse(1 - edwardsY) mod p
|
||||
function convertPublicKey(pk) {
|
||||
var z = new Uint8Array(32),
|
||||
q = [gf(), gf(), gf(), gf()],
|
||||
a = gf(), b = gf();
|
||||
|
||||
if (unpackneg(q, pk)) return null; // reject invalid key
|
||||
|
||||
var y = q[1];
|
||||
|
||||
A(a, gf1, y);
|
||||
Z(b, gf1, y);
|
||||
inv25519(b, b);
|
||||
M(a, a, b);
|
||||
|
||||
pack25519(z, a);
|
||||
return z;
|
||||
}
|
||||
|
||||
// Converts Ed25519 secret key to Curve25519 secret key.
|
||||
function convertSecretKey(sk) {
|
||||
var d = new Uint8Array(64), o = new Uint8Array(32), i;
|
||||
nacl.lowlevel.crypto_hash(d, sk, 32);
|
||||
d[0] &= 248;
|
||||
d[31] &= 127;
|
||||
d[31] |= 64;
|
||||
for (i = 0; i < 32; i++) o[i] = d[i];
|
||||
for (i = 0; i < 64; i++) d[i] = 0;
|
||||
return o;
|
||||
}
|
||||
|
||||
function convertKeyPair(edKeyPair) {
|
||||
var publicKey = convertPublicKey(edKeyPair.publicKey);
|
||||
if (!publicKey) return null;
|
||||
return {
|
||||
publicKey: publicKey,
|
||||
secretKey: convertSecretKey(edKeyPair.secretKey)
|
||||
};
|
||||
}
|
||||
|
||||
// return {
|
||||
// convertPublicKey: convertPublicKey,
|
||||
// convertSecretKey: convertSecretKey,
|
||||
// convertKeyPair: convertKeyPair,
|
||||
// };
|
||||
|
||||
export default {
|
||||
convertPublicKey: convertPublicKey,
|
||||
convertSecretKey: convertSecretKey,
|
||||
convertKeyPair: convertKeyPair,
|
||||
}
|
||||
|
||||
// }));
|
29
src/utils/decryptChatMessage.ts
Normal file
29
src/utils/decryptChatMessage.ts
Normal file
@ -0,0 +1,29 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import Base58 from '../deps/Base58'
|
||||
import ed2curve from '../deps/ed2curve'
|
||||
import nacl from '../deps/nacl-fast'
|
||||
import {Sha256} from 'asmcrypto.js'
|
||||
|
||||
|
||||
export const decryptChatMessage = (encryptedMessage, privateKey, recipientPublicKey, lastReference) => {
|
||||
let _encryptedMessage = Base58.decode(encryptedMessage)
|
||||
|
||||
const _base58RecipientPublicKey = recipientPublicKey instanceof Uint8Array ? Base58.encode(recipientPublicKey) : recipientPublicKey
|
||||
const _recipientPublicKey = Base58.decode(_base58RecipientPublicKey)
|
||||
|
||||
const _lastReference = lastReference instanceof Uint8Array ? lastReference : Base58.decode(lastReference)
|
||||
|
||||
const convertedPrivateKey = ed2curve.convertSecretKey(privateKey)
|
||||
const convertedPublicKey = ed2curve.convertPublicKey(_recipientPublicKey)
|
||||
const sharedSecret = new Uint8Array(32);
|
||||
nacl.lowlevel.crypto_scalarmult(sharedSecret, convertedPrivateKey, convertedPublicKey)
|
||||
|
||||
const _chatEncryptionSeed = new Sha256().process(sharedSecret).finish().result
|
||||
const _decryptedMessage = nacl.secretbox.open(_encryptedMessage, _lastReference.slice(0, 24), _chatEncryptionSeed)
|
||||
|
||||
let decryptedMessage = ''
|
||||
|
||||
_decryptedMessage === false ? decryptedMessage : decryptedMessage = new TextDecoder('utf-8').decode(_decryptedMessage)
|
||||
return decryptedMessage
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user