functionalscript 0.0.297 → 0.0.301
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/sha2/index.js +152 -0
- package/sha2/test.js +69 -0
- package/test.js +1 -0
package/package.json
CHANGED
package/sha2/index.js
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {{
|
|
3
|
+
* readonly f: (i: number) => number
|
|
4
|
+
* readonly length: number
|
|
5
|
+
* }} HashInput
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {Int32Array} Hash8
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** @type {(input: number) => (pos: number) => number} */
|
|
13
|
+
const appendOne = input => pos => input | (1 << 31 - pos)
|
|
14
|
+
|
|
15
|
+
/** @type {(input: number) => (pos: number) => number} */
|
|
16
|
+
const mod = a => b => (a % b + b) % b
|
|
17
|
+
|
|
18
|
+
/** @type {(input: readonly number[]) => (bits: number) => HashInput} */
|
|
19
|
+
const padding = input => bitsCount =>
|
|
20
|
+
{
|
|
21
|
+
const appendBlockIndex = (bitsCount / 32) | 0
|
|
22
|
+
const length = (bitsCount + mod(447 - bitsCount)(512) + 65) / 32
|
|
23
|
+
/** @type {(i: number) => number} */
|
|
24
|
+
const f = i =>
|
|
25
|
+
i < appendBlockIndex ?
|
|
26
|
+
input[i] :
|
|
27
|
+
i === appendBlockIndex ?
|
|
28
|
+
(appendBlockIndex >= input.length ? 0x8000_0000 : appendOne(input[appendBlockIndex])(bitsCount % 32)) :
|
|
29
|
+
i === length - 2 ? (bitsCount / 0x1_0000_0000) | 0 :
|
|
30
|
+
i === length - 1 ? bitsCount % 0x1_0000_0000 : 0
|
|
31
|
+
return ({f, length})
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** @type {(n: number) => (d: number) => number} */
|
|
35
|
+
const rotr = n => d => n >>> d | n << (32 - d)
|
|
36
|
+
|
|
37
|
+
/** @type {(x: number) => (y: number) => (z: number) => number} */
|
|
38
|
+
const ch = x => y => z => x & y ^ ~x & z
|
|
39
|
+
|
|
40
|
+
/** @type {(x: number) => (y: number) => (z: number) => number} */
|
|
41
|
+
const maj = x => y => z => x & y ^ x & z ^ y & z
|
|
42
|
+
|
|
43
|
+
/** @type {(n: number) => (d: number) => number} */
|
|
44
|
+
const shr = n => d => n >>> d
|
|
45
|
+
|
|
46
|
+
/** @type {(x: number) => number} */
|
|
47
|
+
const bsig0 = x => rotr(x)(2) ^ rotr(x)(13) ^ rotr(x)(22)
|
|
48
|
+
|
|
49
|
+
/** @type {(x: number) => number} */
|
|
50
|
+
const bsig1 = x => rotr(x)(6) ^ rotr(x)(11) ^ rotr(x)(25)
|
|
51
|
+
|
|
52
|
+
/** @type {(x: number) => number} */
|
|
53
|
+
const ssig0 = x => rotr(x)(7) ^ rotr(x)(18) ^ shr(x)(3)
|
|
54
|
+
|
|
55
|
+
/** @type {(x: number) => number} */
|
|
56
|
+
const ssig1 = x => rotr(x)(17) ^ rotr(x)(19) ^ shr(x)(10)
|
|
57
|
+
|
|
58
|
+
/** @type {Hash8} */
|
|
59
|
+
const init256 = new Int32Array([0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19])
|
|
60
|
+
|
|
61
|
+
/** @type {(input: readonly number[]) => (bitsCount: number) => Hash8} */
|
|
62
|
+
const computeSha256 = input => bitsCount => compute(input)(bitsCount)(init256)
|
|
63
|
+
|
|
64
|
+
/** @type {Hash8} */
|
|
65
|
+
const init224 = new Int32Array([0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4])
|
|
66
|
+
|
|
67
|
+
const k = new Int32Array([
|
|
68
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
69
|
+
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
70
|
+
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
71
|
+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
72
|
+
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
73
|
+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
74
|
+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
75
|
+
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
|
76
|
+
]);
|
|
77
|
+
|
|
78
|
+
/** @type {(input: readonly number[]) => (bitsCount: number) => Hash8} */
|
|
79
|
+
const computeSha224 = input => bitsCount => compute(input)(bitsCount)(init224)
|
|
80
|
+
|
|
81
|
+
/** @type {(input: readonly number[]) => (bitsCount: number) => (init: Hash8) => Hash8} */
|
|
82
|
+
const compute = input => bitsCount => init =>
|
|
83
|
+
{
|
|
84
|
+
const padded = padding(input)(bitsCount)
|
|
85
|
+
|
|
86
|
+
let h0 = init[0]
|
|
87
|
+
let h1 = init[1]
|
|
88
|
+
let h2 = init[2]
|
|
89
|
+
let h3 = init[3]
|
|
90
|
+
let h4 = init[4]
|
|
91
|
+
let h5 = init[5]
|
|
92
|
+
let h6 = init[6]
|
|
93
|
+
let h7 = init[7]
|
|
94
|
+
|
|
95
|
+
const chunkCount = padded.length / 16
|
|
96
|
+
for(let i = 0; i < chunkCount; i++)
|
|
97
|
+
{
|
|
98
|
+
const w = new Int32Array(64)
|
|
99
|
+
for(let t = 0; t < 16; t++)
|
|
100
|
+
{
|
|
101
|
+
w[t] = padded.f(t + i * 16)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
for(let t = 16; t < 64; t++)
|
|
105
|
+
{
|
|
106
|
+
w[t] = (ssig1(w[t - 2]) + w[t - 7] + ssig0(w[t-15]) + w[t - 16]) | 0
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
let a = h0
|
|
110
|
+
let b = h1
|
|
111
|
+
let c = h2
|
|
112
|
+
let d = h3
|
|
113
|
+
let e = h4
|
|
114
|
+
let f = h5
|
|
115
|
+
let g = h6
|
|
116
|
+
let h = h7
|
|
117
|
+
|
|
118
|
+
for(let t = 0; t < 64; t++)
|
|
119
|
+
{
|
|
120
|
+
let t1 = (h + bsig1(e) + ch(e)(f)(g) + k[t] + w[t]) | 0
|
|
121
|
+
let t2 = (bsig0(a) + maj(a)(b)(c)) | 0
|
|
122
|
+
h = g
|
|
123
|
+
g = f
|
|
124
|
+
f = e
|
|
125
|
+
e = (d + t1) | 0
|
|
126
|
+
d = c
|
|
127
|
+
c = b
|
|
128
|
+
b = a
|
|
129
|
+
a = (t1 + t2) | 0
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
h0 = (h0 + a) | 0
|
|
133
|
+
h1 = (h1 + b) | 0
|
|
134
|
+
h2 = (h2 + c) | 0
|
|
135
|
+
h3 = (h3 + d) | 0
|
|
136
|
+
h4 = (h4 + e) | 0
|
|
137
|
+
h5 = (h5 + f) | 0
|
|
138
|
+
h6 = (h6 + g) | 0
|
|
139
|
+
h7 = (h7 + h) | 0
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return new Int32Array([h0, h1, h2, h3, h4, h5, h6, h7])
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
module.exports = {
|
|
146
|
+
/** @readonly */
|
|
147
|
+
padding,
|
|
148
|
+
/** @readonly */
|
|
149
|
+
computeSha256,
|
|
150
|
+
/** @readonly */
|
|
151
|
+
computeSha224
|
|
152
|
+
}
|
package/sha2/test.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
const _ = require('.')
|
|
2
|
+
const json = require('../json')
|
|
3
|
+
const { sort } = require('../types/object')
|
|
4
|
+
const list = require('../types/list')
|
|
5
|
+
|
|
6
|
+
/** @type {(a: number) => number} */
|
|
7
|
+
const toU32 = x => (x + 0x1_0000_0000) % 0x1_0000_0000
|
|
8
|
+
|
|
9
|
+
/** @type {(a: number) => string} */
|
|
10
|
+
const toHexString = x => toU32(x).toString(16).padStart(8, '0')
|
|
11
|
+
|
|
12
|
+
/** @type {(a: readonly json.Unknown[]) => string} */
|
|
13
|
+
const stringify = a => json.stringify(sort)(a)
|
|
14
|
+
|
|
15
|
+
// {
|
|
16
|
+
// const result = _.padding([])(0)
|
|
17
|
+
// console.log(result.map(toHexString))
|
|
18
|
+
// }
|
|
19
|
+
|
|
20
|
+
// {
|
|
21
|
+
// const result = _.padding([0x61626364, 0x65000000])(40)
|
|
22
|
+
// console.log(result.map(toHexString))
|
|
23
|
+
// }
|
|
24
|
+
|
|
25
|
+
// {
|
|
26
|
+
// const result = _.padding([0x11111110])(31)
|
|
27
|
+
// console.log(result.map(toHexString))
|
|
28
|
+
// }
|
|
29
|
+
|
|
30
|
+
// {
|
|
31
|
+
// const result = _.padding([0x11111110])(32)
|
|
32
|
+
// console.log(result.map(toHexString))
|
|
33
|
+
// }
|
|
34
|
+
|
|
35
|
+
{
|
|
36
|
+
const hash = _.computeSha256([])(0)
|
|
37
|
+
const result = stringify(Array.from(hash).map(toHexString))
|
|
38
|
+
if (result !== '["e3b0c442","98fc1c14","9afbf4c8","996fb924","27ae41e4","649b934c","a495991b","7852b855"]') { throw result }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
{
|
|
42
|
+
const hash = _.computeSha224([])(0)
|
|
43
|
+
const result = stringify(Array.from(hash).map(toHexString))
|
|
44
|
+
if (result !== '["d14a028c","2a3a2bc9","476102bb","288234c4","15a2b01f","828ea62a","c5b3e42f","bdd387cb"]') { throw result }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
{
|
|
48
|
+
//[0x68656C6C, 0x6F20776F, 0x726C6400] represents phrase 'hello world'
|
|
49
|
+
const hash = _.computeSha256([0x68656C6C, 0x6F20776F, 0x726C6400])(88)
|
|
50
|
+
const result = stringify(Array.from(hash).map(toHexString))
|
|
51
|
+
if (result !== '["b94d27b9","934d3e08","a52e52d7","da7dabfa","c484efe3","7a5380ee","9088f7ac","e2efcde9"]') { throw result }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
{
|
|
55
|
+
const input = Array(8).fill(0x31313131)
|
|
56
|
+
const result = _.computeSha256(input)(256)
|
|
57
|
+
if (toU32(result[0]) !== 0x8a83665f) { throw result[0] }
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
{
|
|
61
|
+
const input = Array(16).fill(0x31313131)
|
|
62
|
+
const hash = _.computeSha256(input)(512)
|
|
63
|
+
const result = stringify(Array.from(hash).map(toHexString))
|
|
64
|
+
if (result !== '["3138bb9b","c78df27c","473ecfd1","410f7bd4","5ebac1f5","9cf3ff9c","fe4db77a","ab7aedd3"]') { throw result }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = {
|
|
68
|
+
|
|
69
|
+
}
|