on master help sign in
Merge pull request #295 from urbit/view-code

View +code inside bridge

commit7502d29484281818ba9accf405099342d005e378 authorFang <Fang-@users.noreply.github.com> dateThu 10 Oct 2019, 20:04 (7 years ago) parenta292a87ed20c3e
4 files changed+75−4
src/lib/keys.js+4−4 src/lib/networkCode.js+50 src/lib/useKeyfileGenerator.js+7 src/views/Point.js+14
src/lib/keys.js+4−4
@@ -59,6 +59,9 @@ const jam = seed => {
5959// simple alias to avoid importing kg into component scope
6060export const deriveNetworkKeys = seed => kg.deriveNetworkKeys(seed);
6161
62+export const createRing = pair =>
63+ pair.crypt.private + pair.auth.private + NETWORK_KEY_CURVE_PARAMETER;
64+
6265/**
6366 * @param {object} pair
6467 * @param {number} point
@@ -66,10 +69,7 @@ export const deriveNetworkKeys = seed => kg.deriveNetworkKeys(seed);
6669 * @return {string}
6770 */
6871export const compileNetworkingKey = (pair, point, revision) => {
69− const bnsec = new BN(
70− pair.crypt.private + pair.auth.private + NETWORK_KEY_CURVE_PARAMETER,
71− 'hex'
72− );
72+ const bnsec = new BN(createRing(pair), 'hex');
7373
7474 const sed = noun.dwim(
7575 noun.Atom.fromInt(point),
src/lib/networkCode.jsnew file+50
@@ -0,0 +1,50 @@
1+import { hex2patp } from 'urbit-ob';
2+import { createRing } from 'lib/keys';
3+
4+import jssha256 from 'js-sha256';
5+
6+function shax(buf) {
7+ const hashed = jssha256.sha256.array(buf);
8+ return Buffer.from(hashed);
9+}
10+
11+function hex2buf(hex) {
12+ return Buffer.from(hex, 'hex').reverse();
13+}
14+
15+function buf2hex(buf) {
16+ return Buffer.from(buf)
17+ .reverse()
18+ .toString('hex');
19+}
20+
21+function shas(buf, salt) {
22+ return shax(xor(salt, shax(buf)));
23+}
24+
25+function xor(a, b) {
26+ const length = Math.max(a.byteLength, b.byteLength);
27+ const result = new Uint8Array(length);
28+ for (let i = 0; i < length; i++) {
29+ result[i] = a[i] ^ b[i];
30+ }
31+ return result;
32+}
33+
34+function shaf(buf, salt) {
35+ const result = shas(buf, salt);
36+ const halfway = result.length / 2;
37+ const front = result.slice(0, halfway);
38+ const back = result.slice(halfway, result.length);
39+ return xor(front, back);
40+}
41+
42+export const generateCode = pair => {
43+ const ring = hex2buf(createRing(pair));
44+ const salt = hex2buf('73736170'); // salt is the noun %pass
45+ const hash = shax(ring);
46+ const result = shaf(hash, salt);
47+ const half = result.slice(0, result.length / 2);
48+
49+ return hex2patp(buf2hex(half));
50+};
src/lib/useKeyfileGenerator.js+7
@@ -8,6 +8,7 @@ import { useWallet } from 'store/wallet';
88import { usePointCursor } from 'store/pointCursor';
99
1010import * as need from 'lib/need';
11+import { generateCode } from 'lib/networkCode';
1112
1213import {
1314 attemptNetworkSeedDerivation,
@@ -28,6 +29,8 @@ export default function useKeyfileGenerator(manualNetworkSeed) {
2829 const [generating, setGenerating] = useState(true);
2930 const [keyfile, setKeyfile] = useState(false);
3031
32+ const [code, setCode] = useState(false);
33+
3134 const _point = need.point(pointCursor);
3235 const _details = need.details(getDetails(_point));
3336
@@ -71,6 +74,8 @@ export default function useKeyfileGenerator(manualNetworkSeed) {
7174
7275 const pair = deriveNetworkKeys(_networkSeed);
7376
77+ setCode(generateCode(pair));
78+
7479 if (!keysMatchChain(pair, _details)) {
7580 setGenerating(false);
7681 setNotice('Derived networking keys do not match on-chain details.');
@@ -88,6 +93,7 @@ export default function useKeyfileGenerator(manualNetworkSeed) {
8893 urbitWallet,
8994 wallet,
9095 authMnemonic,
96+ setCode,
9197 _details,
9298 _point,
9399 ]);
@@ -113,6 +119,7 @@ export default function useKeyfileGenerator(manualNetworkSeed) {
113119 downloaded,
114120 download,
115121 notice,
122+ code,
116123 };
117124
118125 return { ...values, bind: values };
src/views/Point.js+14
@@ -9,6 +9,7 @@ import View from 'components/View';
99import Greeting from 'components/Greeting';
1010import Passport from 'components/Passport';
1111import { ForwardButton, BootArvoButton } from 'components/Buttons';
12+import CopyButton from 'components/CopyButton';
1213import { matchBlinky } from 'components/Blinky';
1314import DownloadSigilButton from 'components/DownloadSigilButton';
1415
@@ -17,6 +18,7 @@ import useInvites from 'lib/useInvites';
1718import { useSyncOwnedPoints } from 'lib/useSyncPoints';
1819import useCurrentPermissions from 'lib/useCurrentPermissions';
1920import { useLocalRouter } from 'lib/LocalRouter';
21+import useKeyfileGenerator from 'lib/useKeyfileGenerator';
2022
2123export default function Point() {
2224 const { pop, push, names } = useLocalRouter();
@@ -24,6 +26,8 @@ export default function Point() {
2426
2527 const point = need.point(pointCursor);
2628
29+ const { code, notice } = useKeyfileGenerator();
30+
2731 const {
2832 isParent,
2933 isActiveOwner,
@@ -101,6 +105,16 @@ export default function Point() {
101105 Admin
102106 </Grid.Item>
103107 <Grid.Divider />
108+ <Grid.Item
109+ full
110+ as={ForwardButton}
111+ accessory={code && <CopyButton text={code} />}
112+ detail={code || notice}
113+ disabled={!code}
114+ detailClassName="mono">
115+ Login Code
116+ </Grid.Item>
117+ <Grid.Divider />
104118 {isParent && (
105119 <>
106120 <Grid.Item