/
sha256.test.js
138 lines (134 loc) · 5.44 KB
/
sha256.test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import * as t from '../testing.js'
import * as sha256 from './sha256.fallback.js'
import * as buffer from '../buffer.js'
import * as string from '../string.js'
import * as prng from '../prng.js'
import * as webcrypto from 'lib0/webcrypto'
import * as promise from '../promise.js'
import * as env from '../environment.js'
import * as array from '../array.js'
import * as f from '../function.js'
/**
* @param {t.TestCase} _tc
*/
export const testSha256Basics = async _tc => {
/**
* @param {string | Uint8Array} data input data (buffer or hex encoded)
* @param {string} result Expected result (hex encoded)
*/
const test = async (data, result) => {
data = typeof data === 'string' ? buffer.fromHexString(data) : data
const res = sha256.hash(data)
const resHex = buffer.toHexString(res)
t.assert(resHex === result)
const resWebcrypto = new Uint8Array(await webcrypto.subtle.digest('SHA-256', data))
const resWebcryptoHex = buffer.toHexString(resWebcrypto)
t.assert(resWebcryptoHex === result)
}
// const newInput = 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopno'
// const xx = new Uint8Array(await webcrypto.subtle.digest('SHA-256', string.encodeUtf8(newInput)))
// console.log(buffer.toHexString(xx), ' dtrndtndtn', newInput.length)
await test('', 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855')
await test(string.encodeUtf8('ab'), 'fb8e20fc2e4c3f248c60c39bd652f3c1347298bb977b8b4d5903b85055620603')
await test(string.encodeUtf8('abc'), 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad')
await test(string.encodeUtf8('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopno'), '71806f0af18dbbe905f8fcaa576b8e687859163cf68b38bc26f32e5120522cc1')
await test(string.encodeUtf8('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'), '248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1')
await test(string.encodeUtf8('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopqqqq0001'), 'e54ad86cad2d9d7c03506d6a67ed03fab5fbb8d34012143e9c0eb88ace56ca59')
await test(string.encodeUtf8('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopqqqq00012'), '7a1e062405a534817dcb89fa2416a69e4fbe75fabece33d528b82d1b71d3e418')
await test(string.encodeUtf8('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopqqqq000123'), '51691fe639226a9df2c0e4637918990291c73cdbb58665a7c729bb4e8d67784c')
}
/**
* Test if implementation is correct when length (in bits) exceeds uint32.
*
* @param {t.TestCase} _tc
*/
export const testLargeValue = async _tc => {
t.skip(!t.extensive)
const BS = 100 * 1000 * 1000
const data = prng.uint8Array(prng.create(42), BS)
let resNode = buffer.fromBase64('81m7UtkH2s9J3E33Bw5kRMuC5zvktgZ64SfzenbV5Lw=')
let resLib0
let resWebcrypto
if (env.isNode) {
const sha256Node = await import('./sha256.node.js')
t.measureTime(`[node] Hash message of size ${BS}`, () => {
const res = new Uint8Array(sha256Node.hash(data))
if (!f.equalityDeep(res, resNode)) {
console.warn(`Precomputed result should be the same! New result: ${buffer.toBase64(res)}`)
}
resNode = res
t.compare(res, resNode, 'Precomputed result should be the same')
})
}
t.measureTime(`[lib0] Hash message of size ${BS}`, () => {
resLib0 = sha256.hash(data)
})
await t.measureTimeAsync(`[webcrypto] Hash message of size ${BS}`, async () => {
resWebcrypto = new Uint8Array(await webcrypto.subtle.digest('SHA-256', data))
})
t.compare(resLib0, resNode)
t.compare(resLib0, resWebcrypto)
}
/**
* @param {t.TestCase} tc
*/
export const testRepeatSha256Hashing = async tc => {
const LEN = prng.bool(tc.prng) ? prng.uint32(tc.prng, 0, 512) : prng.uint32(tc.prng, 0, 3003030)
const data = prng.uint8Array(tc.prng, LEN)
const hashedCustom = sha256.hash(data)
const hashedWebcrypto = new Uint8Array(await webcrypto.subtle.digest('SHA-256', data))
t.compare(hashedCustom, hashedWebcrypto)
}
/**
* @param {t.TestCase} _tc
*/
export const testBenchmarkSha256 = async _tc => {
/**
* @param {number} N
* @param {number} BS
*/
const bench = (N, BS) => t.groupAsync(`Hash ${N} random values of size ${BS}`, async () => {
const gen = prng.create(42)
const datas = array.unfold(N, () => prng.uint8Array(gen, BS))
t.measureTime('lib0 (fallback))', () => {
for (let i = 0; i < N; i++) {
const x = sha256.hash(datas[i])
if (x === null) throw new Error()
}
})
if (env.isNode) {
const nodeSha = await import('./sha256.node.js')
t.measureTime('lib0 (node))', () => {
for (let i = 0; i < N; i++) {
const x = nodeSha.hash(datas[i])
if (x === null) throw new Error()
}
})
}
await t.measureTimeAsync('webcrypto sequentially', async () => {
for (let i = 0; i < N; i++) {
const x = await webcrypto.subtle.digest('SHA-256', datas[i])
if (x === null) throw new Error()
}
})
await t.measureTimeAsync('webcrypto concurrent', async () => {
/**
* @type {Array<Promise<any>>}
*/
const ps = []
for (let i = 0; i < N; i++) {
ps.push(webcrypto.subtle.digest('SHA-256', datas[i]))
}
const x = await promise.all(ps)
if (x === null) throw new Error()
})
})
await bench(10 * 1000, 10)
await bench(10 * 1000, 50)
t.skip(!t.extensive)
await bench(10 * 1000, 100)
await bench(10 * 1000, 500)
await bench(10 * 1000, 1000)
await bench(10 * 1000, 4098)
await bench(10, 5 * 1000 * 1000)
}