on 4efb153 help sign in
bridge/src/views/GenKeyfile.js
150 lines 3.8 kB history raw
1import React from 'react'
2import Maybe from 'folktale/maybe'
4import { Button } from '../components/Base'
5import { RequiredInput, InnerLabel } from '../components/Base'
6import { Row, Col, H1, P } from '../components/Base'
7import { Code } from '../components/Base'
9import * as ob from 'urbit-ob'
10import * as kg from '../../node_modules/urbit-key-generation/dist/index'
11import saveAs from 'file-saver'
13import { attemptSeedDerivation, genKey } from '../lib/keys'
14import { BRIDGE_ERROR } from '../lib/error'
15import {
16 addHexPrefix
17 } from '../lib/wallet'
19class GenKeyfile extends React.Component {
20 constructor(props) {
21 super(props)
23 this.state = {
24 keyfile: '',
25 loaded: false
26 }
27 }
29 getPointDetails() {
30 const { pointCache } = this.props
31 const { pointCursor } = this.props
33 const point = pointCursor.matchWith({
34 Just: (pt) => pt.value,
35 Nothing: () => {
36 throw BRIDGE_ERROR.MISSING_POINT
37 }
38 })
40 const pointDetails =
41 point in pointCache
42 ? pointCache[point]
43 : (() => { throw BRIDGE_ERROR.MISSING_POINT })()
45 const revision = parseInt(pointDetails.keyRevisionNumber)
47 return {
48 point,
49 pointDetails,
50 revision
51 }
52 }
54 async componentDidMount() {
55 const { point, pointDetails, revision } = this.getPointDetails();
56 let keyfile = ''
58 const hexRegExp = /[0-9A-Fa-f]{64}/g
59 const networkSeed = await this.deriveSeed()
61 const keysmatch = this.checkKeysMatch(networkSeed, pointDetails)
62 const seedValid = hexRegExp.test(networkSeed)
64 if (keysmatch && seedValid) {
65 keyfile = genKey(networkSeed, point, revision)
66 }
68 this.setState({
69 keyfile: keyfile,
70 loaded: true
71 });
72 }
74 checkKeysMatch(networkSeed, pointDetails) {
75 const crypub = pointDetails.encryptionKey
76 const sgnpub = pointDetails.authenticationKey
78 const { crypt, auth } = kg.deriveNetworkKeys(networkSeed)
80 const keysmatch =
81 crypub === addHexPrefix(crypt.public)
82 && sgnpub === addHexPrefix(auth.public)
84 return keysmatch;
85 }
87 async deriveSeed() {
88 const next = false
89 let seed = await attemptSeedDerivation(next, this.props)
91 if (seed.getOrElse('') === '' && this.props.networkSeedCache) {
92 seed = Maybe.Just(this.props.networkSeedCache)
93 }
95 return seed.getOrElse('')
96 }
98 render() {
99 const { point, pointDetails, revision } = this.getPointDetails();
100 const { keyfile, loaded } = this.state
102 return (
103 <Row>
104 <Col className={'col-md-8'}>
105 <H1>{ 'Generate keyfile' }</H1>
107 <P>
108 { "Download a private key file for booting this point in Arvo." }
109 </P>
111 { keyfile === '' && !loaded &&
112 <P>
113 { "Generating keyfile..." }
114 </P>
115 }
117 { keyfile === '' && loaded &&
118 <P>
119 <b>Warning: </b>
120 { `No valid network seed detected. To generate a keyfile, you
121 must reset your networking keys, or try logging in with your
122 master ticket or management mnemonic` }
123 </P>
124 }
126 { keyfile !== '' &&
127 <React.Fragment>
128 <div className="pb-5 text-code keyfile">
129 { keyfile }
130 </div>
131 <Button
132 onClick={
133 () => {
134 let blob = new Blob([keyfile], {type:"text/plain;charset=utf-8"});
135 saveAs(blob, `${ob.patp(point).slice(1)}-${revision}.key`)
136 }
137 }>
138 Download →
139 </Button>
140 </React.Fragment>
141 }
143 </Col>
144 </Row>
145 )
146 }
150export default GenKeyfile