on a64a26c help sign in
bridge/src/views/GenKeyfile.js
169 lines 4.2 kB history raw
1import React from 'react'
3import { Button } from '../components/Base'
4import { RequiredInput, InnerLabel } from '../components/Base'
5import { Row, Col, H1, P } from '../components/Base'
6import { Form, Code } from '../components/Base'
8import * as ob from 'urbit-ob'
9import * as kg from '../../node_modules/urbit-key-generation/dist/index'
10import saveAs from 'file-saver'
12import { attemptSeedDerivation, genKey } from '../lib/keys'
13import { BRIDGE_ERROR } from '../lib/error'
14import {
15 addHexPrefix
16 } from '../lib/wallet'
18class GenKeyfile extends React.Component {
19 constructor(props) {
20 super(props)
22 this.state = {
23 keyfile: '',
24 networkSeed: ''
25 }
27 this.handleNetworkSeedInput = this.handleNetworkSeedInput.bind(this)
28 this.handleKeyfileChange = this.handleKeyfileChange.bind(this)
29 }
31 componentDidMount() {
32 this.deriveSeed()
33 }
35 async deriveSeed() {
36 const next = false
37 const seed = await attemptSeedDerivation(next, this.props)
38 this.setState({
39 networkSeed: seed.getOrElse('')
40 })
41 }
43 handleNetworkSeedInput = (networkSeed) => {
44 this.setState({ networkSeed })
45 }
47 handleKeyfileChange = (keyfile) => {
48 this.setState({ keyfile })
49 }
51 render() {
52 const { pointCache } = this.props
53 const { pointCursor } = this.props
55 const { keyfile, networkSeed } = this.state
57 const point = pointCursor.matchWith({
58 Just: (pt) => pt.value,
59 Nothing: () => {
60 throw BRIDGE_ERROR.MISSING_POINT
61 }
62 })
64 const pointDetails =
65 point in pointCache
66 ? pointCache[point]
67 : (() => { throw BRIDGE_ERROR.MISSING_POINT })()
69 const revision = parseInt(pointDetails.keyRevisionNumber)
71 const crypub = pointDetails.encryptionKey
72 const sgnpub = pointDetails.authenticationKey
74 const { crypt, auth } = kg.deriveNetworkKeys(networkSeed)
76 const keysmatch =
77 crypub === addHexPrefix(crypt.public)
78 && sgnpub === addHexPrefix(auth.public)
80 const warning =
81 keyfile !== '' && keysmatch === false
82 ? <Row>
83 <Col>
84 <b>{ 'WARNING' }</b>{ ": derived key doesn't match Azimuth keys!" }
85 </Col>
86 </Row>
87 : <div />
89 const hexRegExp = /[0-9A-Fa-f]{64}/g
91 const download =
92 keyfile !== ''
93 ? <Button
94 onClick={
95 () => {
96 let blob = new Blob([keyfile], {type:"text/plain;charset=utf-8"});
97 saveAs(blob, `${ob.patp(point).slice(1)}-${revision}.key`)
98 }
99 }>
100 Download →
101 </Button>
102 : ''
104 return (
105 <Row>
106 <Col className={'col-md-8'}>
107 <H1>{ 'Generate keyfile' }</H1>
109 <P>
110 { "Generate a private key file for booting this point in Arvo." }
111 </P>
113 <P>
114 {
115 `Enter a network seed below for generating your key file. Your
116 network seed must be a 32-byte-long hexadecimal string.`
117 }
118 </P>
119 <P>
120 {
121 `If you've authenticated with either a master ticket or a
122 management proxy mnemonic, a seed will be generated for you
123 automatically.`
124 }
125 </P>
127 <Form>
128 <RequiredInput
129 className='mono'
130 prop-size='lg'
131 prop-format='innerLabel'
132 autoFocus
133 value={ networkSeed }
134 onChange={ this.handleNetworkSeedInput }>
135 <InnerLabel>{ 'Network seed' }</InnerLabel>
136 </RequiredInput>
138 <Button
139 className={'mt-8'}
140 color={'blue'}
141 onClick={
142 () => {
143 if (hexRegExp.test(networkSeed)) {
144 const keyfile = genKey(networkSeed, point, revision)
145 this.setState({ keyfile })
146 }
147 }
148 }
149 >
150 { 'Generate →' }
151 </Button>
152 </Form>
154 <Code>
155 { keyfile }
156 </Code>
158 { warning }
160 { download }
162 </Col>
163 </Row>
164 )
165 }
169export default GenKeyfile