UNPKG

4.6 kBJavaScriptView Raw
1/**
2 * Hash
3 * ====
4 *
5 * Some hash functions are used through out bitcoin. We expose them here as a
6 * convenience.
7 */
8'use strict'
9
10import { Workers } from './workers'
11import hashjs from 'hash.js'
12
13class Hash {}
14
15Hash.sha1 = function (buf) {
16 if (!Buffer.isBuffer(buf)) {
17 throw new Error('sha1 hash must be of a buffer')
18 }
19 const Sha1 = hashjs.sha1
20 const hash = new Sha1().update(buf).digest()
21 return Buffer.from(hash)
22}
23
24Hash.sha1.blockSize = 512
25
26Hash.asyncSha1 = async function (buf) {
27 const args = [buf]
28 const workersResult = await Workers.asyncClassMethod(Hash, 'sha1', args)
29 return workersResult.resbuf
30}
31
32Hash.sha256 = function (buf) {
33 if (!Buffer.isBuffer(buf)) {
34 throw new Error('sha256 hash must be of a buffer')
35 }
36 const Sha256 = hashjs.sha256
37 const hash = new Sha256().update(buf).digest()
38 return Buffer.from(hash)
39}
40
41Hash.sha256.blockSize = 512
42
43Hash.asyncSha256 = async function (buf) {
44 const args = [buf]
45 const workersResult = await Workers.asyncClassMethod(Hash, 'sha256', args)
46 return workersResult.resbuf
47}
48
49Hash.sha256Sha256 = function (buf) {
50 try {
51 return Hash.sha256(Hash.sha256(buf))
52 } catch (e) {
53 throw new Error('sha256Sha256 hash must be of a buffer: ' + e)
54 }
55}
56
57Hash.asyncSha256Sha256 = async function (buf) {
58 const args = [buf]
59 const workersResult = await Workers.asyncClassMethod(
60 Hash,
61 'sha256Sha256',
62 args
63 )
64 return workersResult.resbuf
65}
66
67Hash.ripemd160 = function (buf) {
68 if (!Buffer.isBuffer(buf)) {
69 throw new Error('ripemd160 hash must be of a buffer')
70 }
71 const Ripemd160 = hashjs.ripemd160
72 const hash = new Ripemd160().update(buf).digest()
73 return Buffer.from(hash)
74}
75
76Hash.asyncRipemd160 = async function (buf) {
77 const args = [buf]
78 const workersResult = await Workers.asyncClassMethod(Hash, 'ripemd160', args)
79 return workersResult.resbuf
80}
81
82Hash.sha256Ripemd160 = function (buf) {
83 try {
84 return Hash.ripemd160(Hash.sha256(buf))
85 } catch (e) {
86 throw new Error('sha256Ripemd160 hash must be of a buffer: ' + e)
87 }
88}
89
90Hash.asyncSha256Ripemd160 = async function (buf) {
91 const args = [buf]
92 const workersResult = await Workers.asyncClassMethod(
93 Hash,
94 'sha256Ripemd160',
95 args
96 )
97 return workersResult.resbuf
98}
99
100Hash.sha512 = function (buf) {
101 if (!Buffer.isBuffer(buf)) {
102 throw new Error('sha512 hash must be of a buffer')
103 }
104 const Sha512 = hashjs.sha512
105 const hash = new Sha512().update(buf).digest()
106 return Buffer.from(hash)
107}
108
109Hash.asyncSha512 = async function (buf) {
110 const args = [buf]
111 const workersResult = await Workers.asyncClassMethod(Hash, 'sha512', args)
112 return workersResult.resbuf
113}
114
115Hash.sha512.blockSize = 1024
116
117Hash.hmac = function (hashFStr, data, key) {
118 if (hashFStr !== 'sha1' && hashFStr !== 'sha256' && hashFStr !== 'sha512') {
119 throw new Error('invalid choice of hash function')
120 }
121
122 const hashf = Hash[hashFStr]
123
124 if (!Buffer.isBuffer(data) || !Buffer.isBuffer(key)) {
125 throw new Error('data and key must be buffers')
126 }
127
128 // http://en.wikipedia.org/wiki/Hash-based_message_authentication_code
129 // http://tools.ietf.org/html/rfc4868#section-2
130 const blockSize = hashf.blockSize / 8
131
132 if (key.length > blockSize) {
133 key = hashf(key)
134 }
135
136 if (key.length < blockSize) {
137 const fill = Buffer.alloc(blockSize)
138 fill.fill(0, key.length)
139 key.copy(fill)
140 key = fill
141 }
142
143 const oKeyPad = Buffer.alloc(blockSize)
144 const iKeyPad = Buffer.alloc(blockSize)
145 for (let i = 0; i < blockSize; i++) {
146 oKeyPad[i] = 0x5c ^ key[i]
147 iKeyPad[i] = 0x36 ^ key[i]
148 }
149
150 return hashf(
151 Buffer.concat([oKeyPad, hashf(Buffer.concat([iKeyPad, data]))])
152 )
153}
154
155Hash.sha1Hmac = function (data, key) {
156 return Hash.hmac('sha1', data, key)
157}
158
159Hash.asyncSha1Hmac = async function (data, key) {
160 const args = [data, key]
161 const workersResult = await Workers.asyncClassMethod(Hash, 'sha1Hmac', args)
162 return workersResult.resbuf
163}
164
165Hash.sha1Hmac.bitsize = 160
166
167Hash.sha256Hmac = function (data, key) {
168 return Hash.hmac('sha256', data, key)
169}
170
171Hash.asyncSha256Hmac = async function (data, key) {
172 const args = [data, key]
173 const workersResult = await Workers.asyncClassMethod(Hash, 'sha256Hmac', args)
174 return workersResult.resbuf
175}
176
177Hash.sha256Hmac.bitsize = 256
178
179Hash.sha512Hmac = function (data, key) {
180 return Hash.hmac('sha512', data, key)
181}
182
183Hash.asyncSha512Hmac = async function (data, key) {
184 const args = [data, key]
185 const workersResult = await Workers.asyncClassMethod(Hash, 'sha512Hmac', args)
186 return workersResult.resbuf
187}
188
189Hash.sha512Hmac.bitsize = 512
190
191export { Hash }