add Diffie-Hellman
This commit is contained in:
parent
926af80518
commit
291c8ac874
|
@ -157,6 +157,7 @@ function WalletSuggestionDialog({ open, onClose, onIgnore }) {
|
|||
>
|
||||
<div>
|
||||
<img
|
||||
alt=""
|
||||
style={{ height: '39px' }}
|
||||
src="https://raw.githubusercontent.com/solana-labs/wallet-adapter/master/packages/wallets/icons/phantom.svg"
|
||||
/>
|
||||
|
@ -187,6 +188,7 @@ function WalletSuggestionDialog({ open, onClose, onIgnore }) {
|
|||
>
|
||||
<div>
|
||||
<img
|
||||
alt=""
|
||||
style={{ height: '39px' }}
|
||||
src="https://raw.githubusercontent.com/solana-labs/wallet-adapter/master/packages/wallets/icons/solflare.svg"
|
||||
/>
|
||||
|
|
|
@ -4,7 +4,12 @@ import AppBar from '@material-ui/core/AppBar';
|
|||
import Typography from '@material-ui/core/Typography';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import { useConnectionConfig } from '../utils/connection';
|
||||
import {CLUSTERS, clusterForEndpoint, getClusters, addCustomCluster, customClusterExists} from '../utils/clusters';
|
||||
import {
|
||||
clusterForEndpoint,
|
||||
getClusters,
|
||||
addCustomCluster,
|
||||
customClusterExists,
|
||||
} from '../utils/clusters';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Menu from '@material-ui/core/Menu';
|
||||
import MenuItem from '@material-ui/core/MenuItem';
|
||||
|
@ -36,7 +41,7 @@ import { Badge } from '@material-ui/core';
|
|||
import { useConnectedWallets } from '../utils/connected-wallets';
|
||||
import { usePage } from '../utils/page';
|
||||
import { MonetizationOn, OpenInNew } from '@material-ui/icons';
|
||||
import AddCustomClusterDialog from "./AddCustomClusterDialog";
|
||||
import AddCustomClusterDialog from './AddCustomClusterDialog';
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
content: {
|
||||
|
@ -267,9 +272,10 @@ function NetworkSelector() {
|
|||
setCustomNetworkOpen(true);
|
||||
}}
|
||||
>
|
||||
<ListItemIcon className={classes.menuItemIcon}>
|
||||
</ListItemIcon>
|
||||
{customClusterExists() ? 'Edit Custom Endpoint' : 'Add Custom Endpoint'}
|
||||
<ListItemIcon className={classes.menuItemIcon}></ListItemIcon>
|
||||
{customClusterExists()
|
||||
? 'Edit Custom Endpoint'
|
||||
: 'Add Custom Endpoint'}
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</>
|
||||
|
|
|
@ -44,6 +44,9 @@ export default function SignFormContent({
|
|||
case 'hex':
|
||||
messageTxt = '0x' + toHex(message);
|
||||
break;
|
||||
case 'diffieHellman':
|
||||
messageTxt = 'Create Diffie-Hellman keys';
|
||||
break;
|
||||
default:
|
||||
throw new Error('Unexpected message type: ' + messageDisplay);
|
||||
}
|
||||
|
@ -64,6 +67,8 @@ export default function SignFormContent({
|
|||
{`Sign data with account ${wallet.publicKey}`}
|
||||
</>
|
||||
);
|
||||
case 'diffieHellman':
|
||||
return `Create Diffie-Hellman keys`;
|
||||
default:
|
||||
throw new Error('Unexpected message display type: ' + messageDisplay);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,14 @@ import WarningIcon from '@material-ui/icons/Warning';
|
|||
import { useLocalStorageState, isExtension } from '../utils/utils';
|
||||
import SignTransactionFormContent from '../components/SignTransactionFormContent';
|
||||
import SignFormContent from '../components/SignFormContent';
|
||||
import { generateDiffieHelllman } from '../utils/diffie-hellman';
|
||||
|
||||
const AUTHORIZED_METHODS = [
|
||||
'signTransaction',
|
||||
'signAllTransactions',
|
||||
'sign',
|
||||
'diffieHellman',
|
||||
];
|
||||
|
||||
function getInitialRequests() {
|
||||
if (!isExtension) {
|
||||
|
@ -36,7 +44,7 @@ function getInitialRequests() {
|
|||
|
||||
const urlParams = new URLSearchParams(window.location.hash.slice(1));
|
||||
const request = JSON.parse(urlParams.get('request'));
|
||||
|
||||
|
||||
if (request.method === 'sign') {
|
||||
const dataObj = request.params.data;
|
||||
// Deserialize `data` into a Uint8Array
|
||||
|
@ -60,7 +68,8 @@ export default function PopupPage({ opener }) {
|
|||
return params.get('origin');
|
||||
}, []);
|
||||
const selectedWallet = useWallet();
|
||||
const selectedWalletAddress = selectedWallet && selectedWallet.publicKey.toBase58();
|
||||
const selectedWalletAddress =
|
||||
selectedWallet && selectedWallet.publicKey.toBase58();
|
||||
const { accounts, setWalletSelector } = useWalletSelector();
|
||||
const [wallet, setWallet] = useState(isExtension ? null : selectedWallet);
|
||||
|
||||
|
@ -87,11 +96,10 @@ export default function PopupPage({ opener }) {
|
|||
if (!isExtension) {
|
||||
setWallet(selectedWallet);
|
||||
}
|
||||
// using stronger condition here
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
// using stronger condition here
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [selectedWalletAddress]);
|
||||
|
||||
|
||||
// (Extension only) Fetch connected wallet for site from local storage.
|
||||
useEffect(() => {
|
||||
if (isExtension) {
|
||||
|
@ -106,7 +114,7 @@ export default function PopupPage({ opener }) {
|
|||
}
|
||||
});
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [origin]);
|
||||
|
||||
// (Extension only) Set wallet once connectedWallet is retrieved.
|
||||
|
@ -114,8 +122,8 @@ export default function PopupPage({ opener }) {
|
|||
if (isExtension && connectedAccount) {
|
||||
setWallet(selectedWallet);
|
||||
}
|
||||
// using stronger condition here
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
// using stronger condition here
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [connectedAccount, selectedWalletAddress]);
|
||||
|
||||
// Send a disconnect event if this window is closed, this component is
|
||||
|
@ -149,11 +157,7 @@ export default function PopupPage({ opener }) {
|
|||
useEffect(() => {
|
||||
function messageHandler(e) {
|
||||
if (e.origin === origin && e.source === window.opener) {
|
||||
if (
|
||||
e.data.method !== 'signTransaction' &&
|
||||
e.data.method !== 'signAllTransactions' &&
|
||||
e.data.method !== 'sign'
|
||||
) {
|
||||
if (!AUTHORIZED_METHODS.includes(e.data.method)) {
|
||||
postMessage({ error: 'Unsupported method', id: e.data.id });
|
||||
}
|
||||
|
||||
|
@ -169,9 +173,14 @@ export default function PopupPage({ opener }) {
|
|||
|
||||
const { messages, messageDisplay } = useMemo(() => {
|
||||
if (!request || request.method === 'connect') {
|
||||
return { messages: [], messageDisplay: 'tx' }
|
||||
return { messages: [], messageDisplay: 'tx' };
|
||||
}
|
||||
switch (request.method) {
|
||||
case 'diffieHellman':
|
||||
return {
|
||||
messages: [request.params.publicKey],
|
||||
messageDisplay: 'diffieHellman',
|
||||
};
|
||||
case 'signTransaction':
|
||||
return {
|
||||
messages: [bs58.decode(request.params.message)],
|
||||
|
@ -189,7 +198,7 @@ export default function PopupPage({ opener }) {
|
|||
return {
|
||||
messages: [request.params.data],
|
||||
messageDisplay: request.params.display === 'utf8' ? 'utf8' : 'hex',
|
||||
}
|
||||
};
|
||||
default:
|
||||
throw new Error('Unexpected method: ' + request.method);
|
||||
}
|
||||
|
@ -258,16 +267,13 @@ export default function PopupPage({ opener }) {
|
|||
return <ApproveConnectionForm origin={origin} onApprove={connect} />;
|
||||
}
|
||||
|
||||
assert(
|
||||
(request.method === 'signTransaction' ||
|
||||
request.method === 'signAllTransactions' ||
|
||||
request.method === 'sign') &&
|
||||
wallet,
|
||||
);
|
||||
assert(AUTHORIZED_METHODS.includes(request.method) && wallet);
|
||||
|
||||
async function onApprove() {
|
||||
popRequest();
|
||||
switch (request.method) {
|
||||
case 'diffieHellman':
|
||||
return diffieHellman(messages[0]);
|
||||
case 'signTransaction':
|
||||
case 'sign':
|
||||
sendSignature(messages[0]);
|
||||
|
@ -312,6 +318,17 @@ export default function PopupPage({ opener }) {
|
|||
});
|
||||
}
|
||||
|
||||
function diffieHellman(publicKey) {
|
||||
const keys = generateDiffieHelllman(
|
||||
publicKey,
|
||||
wallet.provider.account.secretKey,
|
||||
);
|
||||
postMessage({
|
||||
result: keys,
|
||||
id: request.id,
|
||||
});
|
||||
}
|
||||
|
||||
function sendReject() {
|
||||
popRequest();
|
||||
postMessage({
|
||||
|
|
|
@ -0,0 +1,299 @@
|
|||
/*
|
||||
* 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 */
|
||||
;(function (root, f) {
|
||||
'use strict'
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
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,
|
||||
}
|
||||
})
|
|
@ -0,0 +1,14 @@
|
|||
import ed2curve from './ed2curve';
|
||||
|
||||
/**
|
||||
* Generate Diffie-Hellman keys
|
||||
* publicKey is a Uint8Array
|
||||
* secretKey is a Uint8Array
|
||||
* Returns { publicKey: Uint8Array, secretKey: Uint8Array }
|
||||
*/
|
||||
export const generateDiffieHelllman = (publicKey, secretKey) => {
|
||||
return ed2curve.convertKeyPair({
|
||||
publicKey: publicKey,
|
||||
secretKey: new Uint8Array(secretKey),
|
||||
});
|
||||
};
|
Loading…
Reference in New Issue