UNPKG

3.3 kBJavaScriptView Raw
1/**
2 * Private Key
3 * ===========
4 *
5 * A private key is used for signing transactions (or messages). The primary
6 * way to use this is new PrivKey().fromRandom(), or new PrivKey().fromBuffer(buf).
7 */
8'use strict'
9
10import { Bn } from './bn'
11import { Point } from './point'
12import { Constants } from './constants'
13import { Base58Check } from './base-58-check'
14import { Random } from './random'
15import { Struct } from './struct'
16
17class PrivKey extends Struct {
18 constructor (bn, compressed, constants = null) {
19 super({ bn, compressed })
20 constants = constants || Constants.Default.PrivKey
21 this.Constants = constants
22 }
23
24 fromJSON (json) {
25 this.fromHex(json)
26 return this
27 }
28
29 toJSON () {
30 return this.toHex()
31 }
32
33 fromRandom () {
34 let privBuf, bn, condition
35
36 do {
37 privBuf = Random.getRandomBuffer(32)
38 bn = new Bn().fromBuffer(privBuf)
39 condition = bn.lt(Point.getN())
40 } while (!condition)
41
42 this.fromObject({
43 bn: bn,
44 compressed: true
45 })
46 return this
47 }
48
49 static fromRandom () {
50 return new this().fromRandom()
51 }
52
53 toBuffer () {
54 let compressed = this.compressed
55
56 if (compressed === undefined) {
57 compressed = true
58 }
59
60 const privBuf = this.bn.toBuffer({ size: 32 })
61 let buf
62 if (compressed) {
63 buf = Buffer.concat([
64 Buffer.from([this.Constants.versionByteNum]),
65 privBuf,
66 Buffer.from([0x01])
67 ])
68 } else {
69 buf = Buffer.concat([Buffer.from([this.Constants.versionByteNum]), privBuf])
70 }
71
72 return buf
73 }
74
75 fromBuffer (buf) {
76 if (buf.length === 1 + 32 + 1 && buf[1 + 32 + 1 - 1] === 1) {
77 this.compressed = true
78 } else if (buf.length === 1 + 32) {
79 this.compressed = false
80 } else {
81 throw new Error(
82 'Length of privKey buffer must be 33 (uncompressed pubKey) or 34 (compressed pubKey)'
83 )
84 }
85
86 if (buf[0] !== this.Constants.versionByteNum) {
87 throw new Error('Invalid versionByteNum byte')
88 }
89
90 return this.fromBn(new Bn().fromBuffer(buf.slice(1, 1 + 32)))
91 }
92
93 toBn () {
94 return this.bn
95 }
96
97 fromBn (bn) {
98 this.bn = bn
99 return this
100 }
101
102 static fromBn (bn) {
103 return new this().fromBn(bn)
104 }
105
106 validate () {
107 if (!this.bn.lt(Point.getN())) {
108 throw new Error('Number must be less than N')
109 }
110 if (typeof this.compressed !== 'boolean') {
111 throw new Error(
112 'Must specify whether the corresponding public key is compressed or not (true or false)'
113 )
114 }
115 return this
116 }
117
118 /**
119 * Output the private key a Wallet Import Format (Wif) string.
120 */
121 toWif () {
122 return Base58Check.encode(this.toBuffer())
123 }
124
125 /**
126 * Input the private key from a Wallet Import Format (Wif) string.
127 */
128 fromWif (str) {
129 return this.fromBuffer(Base58Check.decode(str))
130 }
131
132 static fromWif (str) {
133 return new this().fromWif(str)
134 }
135
136 toString () {
137 return this.toWif()
138 }
139
140 fromString (str) {
141 return this.fromWif(str)
142 }
143}
144
145PrivKey.Mainnet = class extends PrivKey {
146 constructor (bn, compressed) {
147 super(bn, compressed, Constants.Mainnet.PrivKey)
148 }
149}
150
151PrivKey.Testnet = class extends PrivKey {
152 constructor (bn, compressed) {
153 super(bn, compressed, Constants.Testnet.PrivKey)
154 }
155}
156
157export { PrivKey }