2import { Just, Nothing } from 'folktale/maybe';
4import { noun, serial } from '@urbit/nockjs';
5import * as kg from 'urbit-key-generation';
7import { addHexPrefix, eqAddr } from './utils/address';
8import { shas } from './networkCode';
10// the curve param for the network keys
11export const NETWORK_KEY_CURVE_PARAMETER = '42';
12// the current crypto suite version
13export const CRYPTO_SUITE_VERSION = 1;
15export const CURVE_ZERO_ADDR =
16 '0x0000000000000000000000000000000000000000000000000000000000000000';
20 let hex = buf.reverse().toString('hex');
21 let n = new BN(hex, 'hex');
23 while (1 === n.cmpn(0)) {
24 c.push(n.andln(0x3f));
44 String.fromCharCode(trans(b)) + (i && 0 === i % 5 ? '.' : '') + a,
55 const pad = hex.length % 2 === 0 ? hex : '0' + hex;
56 return Buffer.from(pad, 'hex').reverse();
59// simple alias to avoid importing kg into component scope
60export const deriveNetworkKeys = seed => kg.deriveNetworkKeys(seed);
62export const createRing = pair =>
63 pair.crypt.private + pair.auth.private + NETWORK_KEY_CURVE_PARAMETER;
66 * @param {object} pair
67 * @param {number} point
68 * @param {number} revision
71export const compileNetworkKey = (pair, point, revision) => {
72 const bnsec = new BN(createRing(pair), 'hex');
74 const sed = noun.dwim(
75 noun.Atom.fromInt(point),
76 noun.Atom.fromInt(revision),
77 noun.Atom.fromString(bnsec.toString()),
85 * @param {number} point
86 * @param {array<{revision: number, pair: object}>} keys
89export const compileMultiKey = (point, keys) => {
90 const kyz = keys.map(k => {
91 const bnsec = new BN(createRing(k.pair), 'hex');
93 noun.Atom.fromInt(k.revision),
94 noun.Atom.fromString(bnsec.toString())
97 kyz.push(noun.Atom.fromInt(0));
99 const fed = noun.dwim(
100 noun.dwim(noun.Atom.fromInt(1), noun.Atom.fromInt(0)), // version
101 noun.Atom.fromInt(point), // ship
102 noun.dwim(kyz) // keys
105 return b64(jam(fed));
109 * @param {object} urbitWallet
110 * @param {number} revision
111 * @return {Promise<Maybe<string>>}
113export const deriveNetworkSeedFromUrbitWallet = async (
117 return await deriveNetworkSeedFromMnemonic(
118 urbitWallet.management.seed,
119 urbitWallet.meta.passphrase,
125 * @param {Maybe<any>} wallet
126 * @param {string} authMnemonic
127 * @param {object} details
128 * @param {number} revision
129 * @return {Promise<Maybe<string>>}
131export const deriveNetworkSeedFromManagementMnemonic = async (
137 const isManagementProxy = eqAddr(wallet.address, details.managementProxy);
139 // the network seed is derivable iff this mnemonic is the management proxy
140 if (isManagementProxy) {
141 return await deriveNetworkSeedFromMnemonic(
152 * @param {string} mnemonic
153 * @param {string} passphrase
154 * @param {number} revision
155 * @return {Promise<Maybe<string>>}
157const deriveNetworkSeedFromMnemonic = async (
162 //NOTE revision is the point's on-chain revision number. since common uhdw
163 // usage derives the first key at revision/index 0, we need to decrement
164 // the on-chain revision number by one to get the number to derive with.
165 return Just(await kg.deriveNetworkSeed(mnemonic, passphrase, revision - 1));
169 * @param {number} point
170 * @param {string} authToken
171 * @param {number} revision
172 * @return {Maybe<string>}
174export const deriveNetworkSeedFromAuthToken = (point, authToken, revision) => {
175 //NOTE revision is the point's on-chain revision number.
176 // since deriveNetworkSeedFromMnemonic does this too, we decrement the
177 // revision number by one before deriving from it.
178 const salt = Buffer.from(`revision-${point}-${revision - 1}`);
179 const networkSeed = shas(authToken, salt)
182 return Just(networkSeed);
186 * Derives from either a full Urbit Wallet, a current management mnemonic,
187 * or an auth token, in that order of preference.
188 * @return {Promise<Maybe<string>>}
190export const attemptNetworkSeedDerivation = async ({
199 if (Just.hasInstance(urbitWallet)) {
200 return await deriveNetworkSeedFromUrbitWallet(urbitWallet.value, revision);
203 if (Just.hasInstance(wallet) && Just.hasInstance(authMnemonic)) {
204 const managementSeed = await deriveNetworkSeedFromManagementMnemonic(
210 if (Just.hasInstance(managementSeed)) {
211 return managementSeed;
215 if (Just.hasInstance(authToken)) {
216 return deriveNetworkSeedFromAuthToken(point, authToken.value, revision);
224 * @param {object} pair - type NetworkKeys
225 * @param {object} details - type L1Point
228export const keysMatchChain = (pair, details) => {
229 const { crypt, auth } = pair;
230 const { encryptionKey, authenticationKey } = details;
233 encryptionKey === addHexPrefix(crypt.public) &&
234 authenticationKey === addHexPrefix(auth.public)
238export const segmentNetworkKey = hex => {
239 if (hex === CURVE_ZERO_ADDR) {
243 const sl = i => hex.slice(i, i + 4);
244 const rowFrom = i => `${sl(i)}.${sl(i + 4)}.${sl(i + 8)}.${sl(i + 12)}`;
246 return [rowFrom(2), rowFrom(18), rowFrom(34), rowFrom(50)];
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list