on abbbcbc help sign in
bridge/src/lib/keys.js
174 lines 4.0 kB history raw
1import BN from 'bn.js';
2import { Just, Nothing } from 'folktale/maybe';
4import * as noun from '../nockjs/noun';
5import * as serial from '../nockjs/serial';
6import * as kg from 'urbit-key-generation/dist';
8import { eqAddr, addHexPrefix, CURVE_ZERO_ADDR } from './wallet';
9import { NETWORK_KEY_CURVE_PARAMETER } from './constants';
11// ctsy joemfb
12const b64 = buf => {
13 let hex = buf.reverse().toString('hex');
14 let n = new BN(hex, 'hex');
15 let c = [];
16 while (1 === n.cmpn(0)) {
17 c.push(n.andln(0x3f));
18 n = n.shrn(6);
19 }
21 // prettier-ignore
22 const trans = j =>
23 10 > j
24 ? j + 48
25 : 36 > j
26 ? j + 87
27 : 62 > j
28 ? j + 29
29 : 62 === j
30 ? 45
31 : 126;
33 return (
34 '0w' +
35 c.reduce(
36 (a, b, i) =>
37 String.fromCharCode(trans(b)) + (i && 0 === i % 5 ? '.' : '') + a,
38 ''
39 )
40 );
41};
43const jam = seed => {
44 const hex = serial
45 .jam(seed)
46 .toString()
47 .slice(2);
48 const pad = hex.length % 2 === 0 ? hex : '0' + hex;
49 return Buffer.from(pad, 'hex').reverse();
50};
52// simple alias to avoid importing kg into component scope
53export const deriveNetworkKeys = seed => kg.deriveNetworkKeys(seed);
55/**
56 * @param {object} pair
57 * @param {number} point
58 * @param {number} revision
59 * @return {string}
60 */
61export const compileNetworkingKey = (pair, point, revision) => {
62 const bnsec = new BN(
63 pair.crypt.private + pair.auth.private + NETWORK_KEY_CURVE_PARAMETER,
64 'hex'
65 );
67 const sed = noun.dwim(
68 noun.Atom.fromInt(point),
69 noun.Atom.fromInt(revision),
70 noun.Atom.fromString(bnsec.toString()),
71 noun.Atom.yes
72 );
74 return b64(jam(sed));
75};
77/**
78 * @param {object} urbitWallet
79 * @param {number} revision
80 * @return {Promise<Maybe<string>>}
81 */
82export const deriveNetworkSeedFromUrbitWallet = async (
83 urbitWallet,
84 revision = 1
85) => {
86 return await deriveNetworkSeedFromSeed(urbitWallet.management.seed, revision);
87};
89/**
90 * @param {Maybe<any>} wallet
91 * @param {string} authMnemonic
92 * @param {object} details
93 * @param {number} revision
94 * @return {Promise<Maybe<string>>}
95 */
96export const deriveNetworkSeedFromMnemonic = async (
97 wallet,
98 authMnemonic,
99 details,
100 revision = 1
101) => {
102 const isOwner = eqAddr(wallet.address, details.owner);
103 const isManagementProxy = eqAddr(wallet.address, details.managementProxy);
105 // the network seed is only derivable from mnemonic if the derived
106 // management seed or owner equals the record we have on chain
107 if (isOwner || isManagementProxy) {
108 return await deriveNetworkSeedFromSeed(authMnemonic, revision);
109 }
111 return Nothing();
112};
114/**
115 * @param {string} seed
116 * @param {number} revision
117 * @return {Promise<Maybe<string>>}
118 */
119const deriveNetworkSeedFromSeed = async (seed, revision) => {
120 return Just(await kg.deriveNetworkSeed(seed, '', revision));
121};
123/**
124 * @return {Promise<Maybe<string>>}
125 */
126export const attemptNetworkSeedDerivation = async ({
127 urbitWallet,
128 wallet,
129 authMnemonic,
130 details,
131 revision,
132}) => {
133 if (Just.hasInstance(urbitWallet)) {
134 return await deriveNetworkSeedFromUrbitWallet(urbitWallet.value, revision);
135 }
137 if (Just.hasInstance(wallet) && Just.hasInstance(authMnemonic)) {
138 return await deriveNetworkSeedFromMnemonic(
139 wallet.value,
140 authMnemonic.value,
141 details,
142 revision
143 );
144 }
146 return Nothing();
147};
149/**
150 *
151 * @param {object} pair
152 * @param {object} details
153 * @return {boolean}
154 */
155export const keysMatchChain = (pair, details) => {
156 const { crypt, auth } = pair;
157 const { encryptionKey, authenticationKey } = details;
159 return (
160 encryptionKey === addHexPrefix(crypt.public) &&
161 authenticationKey === addHexPrefix(auth.public)
162 );
163};
165export const segmentNetworkKey = hex => {
166 if (hex === CURVE_ZERO_ADDR) {
167 return null;
168 }
170 const sl = i => hex.slice(i, i + 4);
171 const rowFrom = i => `${sl(i)}.${sl(i + 4)}.${sl(i + 8)}.${sl(i + 12)}`;
173 return [rowFrom(2), rowFrom(18), rowFrom(34), rowFrom(50)];
174};