lib0 0.2.77 → 0.2.79
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/README.md +1 -1
- package/array.d.ts +1 -0
- package/array.d.ts.map +1 -1
- package/array.js +18 -0
- package/binary.test.d.ts.map +1 -1
- package/buffer.d.ts +3 -0
- package/buffer.d.ts.map +1 -1
- package/buffer.js +40 -0
- package/buffer.test.d.ts +2 -1
- package/buffer.test.d.ts.map +1 -1
- package/cache.d.ts.map +1 -1
- package/cache.js +0 -1
- package/cache.test.d.ts.map +1 -1
- package/component.d.ts +5 -5
- package/component.d.ts.map +1 -1
- package/component.js +14 -11
- package/coverage/tmp/coverage-10499-1691528887100-0.json +1 -0
- package/decoding.d.ts +2 -0
- package/decoding.d.ts.map +1 -1
- package/decoding.js +26 -0
- package/dist/aes-gcm.cjs +161 -0
- package/dist/aes-gcm.cjs.map +1 -0
- package/dist/{array-fd99bc23.cjs → array-704ca50e.cjs} +22 -2
- package/dist/array-704ca50e.cjs.map +1 -0
- package/dist/array.cjs +2 -1
- package/dist/array.cjs.map +1 -1
- package/dist/array.d.ts +1 -0
- package/dist/array.d.ts.map +1 -1
- package/dist/binary.test.d.ts.map +1 -1
- package/dist/{broadcastchannel-fff713ef.cjs → broadcastchannel-7801969a.cjs} +2 -2
- package/dist/{broadcastchannel-fff713ef.cjs.map → broadcastchannel-7801969a.cjs.map} +1 -1
- package/dist/broadcastchannel.cjs +9 -9
- package/dist/{buffer-621617f6.cjs → buffer-c5d69c70.cjs} +126 -7
- package/dist/buffer-c5d69c70.cjs.map +1 -0
- package/dist/buffer.cjs +12 -9
- package/dist/buffer.cjs.map +1 -1
- package/dist/buffer.d.ts +3 -0
- package/dist/buffer.d.ts.map +1 -1
- package/dist/buffer.test.d.ts +2 -1
- package/dist/buffer.test.d.ts.map +1 -1
- package/dist/cache.cjs +5 -3
- package/dist/cache.cjs.map +1 -1
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.test.d.ts.map +1 -1
- package/dist/common.cjs +37 -0
- package/dist/common.cjs.map +1 -0
- package/dist/component.cjs +20 -17
- package/dist/component.cjs.map +1 -1
- package/dist/component.d.ts +5 -5
- package/dist/component.d.ts.map +1 -1
- package/dist/decoding.cjs +9 -7
- package/dist/decoding.cjs.map +1 -1
- package/dist/decoding.d.ts +2 -0
- package/dist/decoding.d.ts.map +1 -1
- package/dist/{diff-18852f48.cjs → diff-fbaa426b.cjs} +2 -2
- package/dist/{diff-18852f48.cjs.map → diff-fbaa426b.cjs.map} +1 -1
- package/dist/diff.cjs +4 -4
- package/dist/ecdsa.cjs +118 -0
- package/dist/ecdsa.cjs.map +1 -0
- package/dist/encoding.cjs +9 -7
- package/dist/encoding.cjs.map +1 -1
- package/dist/encoding.d.ts +2 -0
- package/dist/encoding.d.ts.map +1 -1
- package/dist/encoding.test.d.ts +1 -0
- package/dist/encoding.test.d.ts.map +1 -1
- package/dist/{environment-0c5ff22b.cjs → environment-ad129e4d.cjs} +3 -3
- package/dist/{environment-0c5ff22b.cjs.map → environment-ad129e4d.cjs.map} +1 -1
- package/dist/environment.cjs +5 -5
- package/dist/{function-831844d3.cjs → function-314fdc56.cjs} +3 -3
- package/dist/{function-831844d3.cjs.map → function-314fdc56.cjs.map} +1 -1
- package/dist/function.cjs +3 -3
- package/dist/hash/rabin-gf2-polynomial.d.ts +45 -0
- package/dist/hash/rabin-gf2-polynomial.d.ts.map +1 -0
- package/dist/hash/rabin-uncached.d.ts +29 -0
- package/dist/hash/rabin-uncached.d.ts.map +1 -0
- package/dist/hash/rabin.d.ts +27 -0
- package/dist/hash/rabin.d.ts.map +1 -0
- package/dist/hash/rabin.test.d.ts +8 -0
- package/dist/hash/rabin.test.d.ts.map +1 -0
- package/dist/hash/sha256.fallback.d.ts +2 -0
- package/dist/hash/sha256.fallback.d.ts.map +1 -0
- package/dist/hash/sha256.node.d.ts +2 -0
- package/dist/hash/sha256.node.d.ts.map +1 -0
- package/dist/hash/sha256.test.d.ts +6 -0
- package/dist/hash/sha256.test.d.ts.map +1 -0
- package/dist/index.cjs +11 -11
- package/dist/list.cjs +3 -3
- package/dist/logging.cjs +5 -5
- package/dist/logging.common.cjs +21 -21
- package/dist/logging.common.cjs.map +1 -1
- package/dist/logging.node.cjs +5 -5
- package/dist/logging.test.d.ts.map +1 -1
- package/dist/{number-dc113762.cjs → number-466d8922.cjs} +29 -10
- package/dist/number-466d8922.cjs.map +1 -0
- package/dist/number.cjs +2 -1
- package/dist/number.cjs.map +1 -1
- package/dist/number.d.ts +1 -0
- package/dist/number.d.ts.map +1 -1
- package/dist/number.test.d.ts +1 -1
- package/dist/number.test.d.ts.map +1 -1
- package/dist/{object-aad630ed.cjs → object-fecf6a7b.cjs} +2 -1
- package/dist/object-fecf6a7b.cjs.map +1 -0
- package/dist/object.cjs +1 -1
- package/dist/object.d.ts.map +1 -1
- package/dist/observable.cjs +1 -1
- package/dist/performance.node.cjs +3 -3
- package/dist/{prng-9ccc85f7.cjs → prng-1149c8c4.cjs} +3 -3
- package/dist/{prng-9ccc85f7.cjs.map → prng-1149c8c4.cjs.map} +1 -1
- package/dist/prng.cjs +8 -8
- package/dist/prng.test.d.ts.map +1 -1
- package/dist/queue.cjs.map +1 -1
- package/dist/queue.d.ts.map +1 -1
- package/dist/rabin-gf2-polynomial.cjs +437 -0
- package/dist/rabin-gf2-polynomial.cjs.map +1 -0
- package/dist/rabin-uncached.cjs +87 -0
- package/dist/rabin-uncached.cjs.map +1 -0
- package/dist/rabin.cjs +125 -0
- package/dist/rabin.cjs.map +1 -0
- package/dist/random.cjs +12 -0
- package/dist/random.cjs.map +1 -1
- package/dist/random.d.ts +1 -1
- package/dist/random.d.ts.map +1 -1
- package/dist/rsa-oaep.cjs +112 -0
- package/dist/rsa-oaep.cjs.map +1 -0
- package/dist/set.test.d.ts.map +1 -1
- package/dist/sha256.fallback.cjs +179 -0
- package/dist/sha256.fallback.cjs.map +1 -0
- package/dist/sha256.node.cjs +17 -0
- package/dist/sha256.node.cjs.map +1 -0
- package/dist/{string-e7eb0c1d.cjs → string-6d104757.cjs} +10 -2
- package/dist/string-6d104757.cjs.map +1 -0
- package/dist/string.cjs +3 -2
- package/dist/string.cjs.map +1 -1
- package/dist/string.d.ts +5 -0
- package/dist/string.d.ts.map +1 -1
- package/dist/testing.cjs +23 -17
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.ts +13 -7
- package/dist/testing.d.ts.map +1 -1
- package/dist/url.cjs +1 -1
- package/dist/webcrypto.node.cjs.map +1 -1
- package/dist/webcrypto.node.d.ts.map +1 -1
- package/dist/{websocket-0632cb8c.cjs → websocket-44e4ead5.cjs} +1 -1
- package/dist/{websocket-0632cb8c.cjs.map → websocket-44e4ead5.cjs.map} +1 -1
- package/dist/websocket.cjs +2 -2
- package/encoding.d.ts +2 -0
- package/encoding.d.ts.map +1 -1
- package/encoding.js +42 -0
- package/encoding.test.d.ts +1 -0
- package/encoding.test.d.ts.map +1 -1
- package/hash/rabin-gf2-polynomial.d.ts +45 -0
- package/hash/rabin-gf2-polynomial.d.ts.map +1 -0
- package/hash/rabin-gf2-polynomial.js +379 -0
- package/hash/rabin-uncached.d.ts +29 -0
- package/hash/rabin-uncached.d.ts.map +1 -0
- package/hash/rabin-uncached.js +68 -0
- package/hash/rabin.d.ts +27 -0
- package/hash/rabin.d.ts.map +1 -0
- package/hash/rabin.js +100 -0
- package/hash/rabin.test.d.ts +8 -0
- package/hash/rabin.test.d.ts.map +1 -0
- package/hash/sha256.fallback.d.ts +2 -0
- package/hash/sha256.fallback.d.ts.map +1 -0
- package/hash/sha256.fallback.js +172 -0
- package/hash/sha256.node.d.ts +2 -0
- package/hash/sha256.node.d.ts.map +1 -0
- package/hash/sha256.node.js +10 -0
- package/hash/sha256.test.d.ts +6 -0
- package/hash/sha256.test.d.ts.map +1 -0
- package/logging.common.js +16 -16
- package/logging.test.d.ts.map +1 -1
- package/number.d.ts +1 -0
- package/number.d.ts.map +1 -1
- package/number.js +17 -0
- package/number.test.d.ts +1 -1
- package/number.test.d.ts.map +1 -1
- package/object.d.ts.map +1 -1
- package/object.js +1 -0
- package/package.json +24 -6
- package/prng.test.d.ts.map +1 -1
- package/queue.d.ts.map +1 -1
- package/queue.js +0 -1
- package/random.d.ts +1 -1
- package/random.d.ts.map +1 -1
- package/random.js +4 -1
- package/set.test.d.ts.map +1 -1
- package/string.d.ts +5 -0
- package/string.d.ts.map +1 -1
- package/string.js +6 -0
- package/test.html +2 -0
- package/test.js +4 -0
- package/testing.d.ts +13 -7
- package/testing.d.ts.map +1 -1
- package/testing.js +14 -8
- package/webcrypto.node.d.ts.map +1 -1
- package/webcrypto.node.js +0 -1
- package/coverage/tmp/coverage-36234-1685177795346-0.json +0 -1
- package/dist/array-fd99bc23.cjs.map +0 -1
- package/dist/buffer-621617f6.cjs.map +0 -1
- package/dist/number-dc113762.cjs.map +0 -1
- package/dist/object-aad630ed.cjs.map +0 -1
- package/dist/string-e7eb0c1d.cjs.map +0 -1
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The idea of the Rabin fingerprint algorithm is to represent the binary as a polynomial in a
|
|
3
|
+
* finite field (Galois Field G(2)). The polynomial will then be taken "modulo" by an irreducible
|
|
4
|
+
* polynomial of the desired size.
|
|
5
|
+
*
|
|
6
|
+
* This implementation is inefficient and is solely used to verify the actually performant
|
|
7
|
+
* implementation in `./rabin.js`.
|
|
8
|
+
*
|
|
9
|
+
* @module rabin-gf2-polynomial
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import * as math from '../math.js'
|
|
13
|
+
import * as webcrypto from 'lib0/webcrypto'
|
|
14
|
+
import * as array from '../array.js'
|
|
15
|
+
import * as buffer from '../buffer.js'
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {number} degree
|
|
19
|
+
*/
|
|
20
|
+
const _degreeToMinByteLength = degree => math.floor(degree / 8) + 1
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* This is a GF2 Polynomial abstraction that is not meant for production!
|
|
24
|
+
*
|
|
25
|
+
* It is easy to understand and it's correctness is as obvious as possible. It can be used to verify
|
|
26
|
+
* efficient implementations of algorithms on GF2.
|
|
27
|
+
*/
|
|
28
|
+
export class GF2Polynomial {
|
|
29
|
+
constructor () {
|
|
30
|
+
/**
|
|
31
|
+
* @type {Set<number>}
|
|
32
|
+
*/
|
|
33
|
+
this.degrees = new Set()
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* From Uint8Array (MSB).
|
|
39
|
+
*
|
|
40
|
+
* @param {Uint8Array} bytes
|
|
41
|
+
*/
|
|
42
|
+
export const createFromBytes = bytes => {
|
|
43
|
+
const p = new GF2Polynomial()
|
|
44
|
+
for (let bsi = bytes.length - 1, currDegree = 0; bsi >= 0; bsi--) {
|
|
45
|
+
const currByte = bytes[bsi]
|
|
46
|
+
for (let i = 0; i < 8; i++) {
|
|
47
|
+
if (((currByte >>> i) & 1) === 1) {
|
|
48
|
+
p.degrees.add(currDegree)
|
|
49
|
+
}
|
|
50
|
+
currDegree++
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return p
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Transform to Uint8Array (MSB).
|
|
58
|
+
*
|
|
59
|
+
* @param {GF2Polynomial} p
|
|
60
|
+
* @param {number} byteLength
|
|
61
|
+
*/
|
|
62
|
+
export const toUint8Array = (p, byteLength = _degreeToMinByteLength(getHighestDegree(p))) => {
|
|
63
|
+
const buf = buffer.createUint8ArrayFromLen(byteLength)
|
|
64
|
+
/**
|
|
65
|
+
* @param {number} i
|
|
66
|
+
*/
|
|
67
|
+
const setBit = i => {
|
|
68
|
+
const bi = math.floor(i / 8)
|
|
69
|
+
buf[buf.length - 1 - bi] |= (1 << (i % 8))
|
|
70
|
+
}
|
|
71
|
+
p.degrees.forEach(setBit)
|
|
72
|
+
return buf
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Create from unsigned integer (max 32bit uint) - read most-significant-byte first.
|
|
77
|
+
*
|
|
78
|
+
* @param {number} uint
|
|
79
|
+
*/
|
|
80
|
+
export const createFromUint = uint => {
|
|
81
|
+
const buf = new Uint8Array(4)
|
|
82
|
+
for (let i = 0; i < 4; i++) {
|
|
83
|
+
buf[i] = uint >>> 8 * (3 - i)
|
|
84
|
+
}
|
|
85
|
+
return createFromBytes(buf)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Create a random polynomial of a specified degree.
|
|
90
|
+
*
|
|
91
|
+
* @param {number} degree
|
|
92
|
+
*/
|
|
93
|
+
export const createRandom = degree => {
|
|
94
|
+
const bs = new Uint8Array(_degreeToMinByteLength(degree))
|
|
95
|
+
webcrypto.getRandomValues(bs)
|
|
96
|
+
// Get first byte and explicitly set the bit of "degree" to 1 (the result must have the specified
|
|
97
|
+
// degree).
|
|
98
|
+
const firstByte = bs[0] | 1 << (degree % 8)
|
|
99
|
+
// Find out how many bits of the first byte need to be filled with zeros because they are >degree.
|
|
100
|
+
const zeros = 7 - (degree % 8)
|
|
101
|
+
bs[0] = ((firstByte << zeros) & 0xff) >>> zeros
|
|
102
|
+
return createFromBytes(bs)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* @param {GF2Polynomial} p
|
|
107
|
+
* @return number
|
|
108
|
+
*/
|
|
109
|
+
export const getHighestDegree = p => array.fold(array.from(p.degrees), 0, math.max)
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Add (+) p2 int the p1 polynomial.
|
|
113
|
+
*
|
|
114
|
+
* Addition is defined as xor in F2. Substraction is equivalent to addition in F2.
|
|
115
|
+
*
|
|
116
|
+
* @param {GF2Polynomial} p1
|
|
117
|
+
* @param {GF2Polynomial} p2
|
|
118
|
+
*/
|
|
119
|
+
export const addInto = (p1, p2) => {
|
|
120
|
+
p2.degrees.forEach(degree => {
|
|
121
|
+
if (p1.degrees.has(degree)) {
|
|
122
|
+
p1.degrees.delete(degree)
|
|
123
|
+
} else {
|
|
124
|
+
p1.degrees.add(degree)
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Or (|) p2 into the p1 polynomial.
|
|
131
|
+
*
|
|
132
|
+
* Addition is defined as xor in F2. Substraction is equivalent to addition in F2.
|
|
133
|
+
*
|
|
134
|
+
* @param {GF2Polynomial} p1
|
|
135
|
+
* @param {GF2Polynomial} p2
|
|
136
|
+
*/
|
|
137
|
+
export const orInto = (p1, p2) => {
|
|
138
|
+
p2.degrees.forEach(degree => {
|
|
139
|
+
p1.degrees.add(degree)
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Add (+) p2 to the p1 polynomial.
|
|
145
|
+
*
|
|
146
|
+
* Addition is defined as xor in F2. Substraction is equivalent to addition in F2.
|
|
147
|
+
*
|
|
148
|
+
* @param {GF2Polynomial} p1
|
|
149
|
+
* @param {GF2Polynomial} p2
|
|
150
|
+
*/
|
|
151
|
+
export const add = (p1, p2) => {
|
|
152
|
+
const result = new GF2Polynomial()
|
|
153
|
+
p2.degrees.forEach(degree => {
|
|
154
|
+
if (!p1.degrees.has(degree)) {
|
|
155
|
+
result.degrees.add(degree)
|
|
156
|
+
}
|
|
157
|
+
})
|
|
158
|
+
p1.degrees.forEach(degree => {
|
|
159
|
+
if (!p2.degrees.has(degree)) {
|
|
160
|
+
result.degrees.add(degree)
|
|
161
|
+
}
|
|
162
|
+
})
|
|
163
|
+
return result
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Add (+) p2 to the p1 polynomial.
|
|
168
|
+
*
|
|
169
|
+
* Addition is defined as xor in F2. Substraction is equivalent to addition in F2.
|
|
170
|
+
*
|
|
171
|
+
* @param {GF2Polynomial} p
|
|
172
|
+
*/
|
|
173
|
+
export const clone = (p) => {
|
|
174
|
+
const result = new GF2Polynomial()
|
|
175
|
+
p.degrees.forEach(d => result.degrees.add(d))
|
|
176
|
+
return result
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Add (+) p2 to the p1 polynomial.
|
|
181
|
+
*
|
|
182
|
+
* Addition is defined as xor in F2. Substraction is equivalent to addition in F2.
|
|
183
|
+
*
|
|
184
|
+
* @param {GF2Polynomial} p
|
|
185
|
+
* @param {number} degree
|
|
186
|
+
*/
|
|
187
|
+
export const addDegreeInto = (p, degree) => {
|
|
188
|
+
if (p.degrees.has(degree)) {
|
|
189
|
+
p.degrees.delete(degree)
|
|
190
|
+
} else {
|
|
191
|
+
p.degrees.add(degree)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Multiply (•) p1 with p2 and store the result in p1.
|
|
197
|
+
*
|
|
198
|
+
* @param {GF2Polynomial} p1
|
|
199
|
+
* @param {GF2Polynomial} p2
|
|
200
|
+
*/
|
|
201
|
+
export const multiply = (p1, p2) => {
|
|
202
|
+
const result = new GF2Polynomial()
|
|
203
|
+
p1.degrees.forEach(degree1 => {
|
|
204
|
+
p2.degrees.forEach(degree2 => {
|
|
205
|
+
addDegreeInto(result, degree1 + degree2)
|
|
206
|
+
})
|
|
207
|
+
})
|
|
208
|
+
return result
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Multiply (•) p1 with p2 and store the result in p1.
|
|
213
|
+
*
|
|
214
|
+
* @param {GF2Polynomial} p
|
|
215
|
+
* @param {number} shift
|
|
216
|
+
*/
|
|
217
|
+
export const shiftLeft = (p, shift) => {
|
|
218
|
+
const result = new GF2Polynomial()
|
|
219
|
+
p.degrees.forEach(degree => {
|
|
220
|
+
const r = degree + shift
|
|
221
|
+
r >= 0 && result.degrees.add(r)
|
|
222
|
+
})
|
|
223
|
+
return result
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Computes p1 % p2. I.e. the remainder of p1/p2.
|
|
228
|
+
*
|
|
229
|
+
* @param {GF2Polynomial} p1
|
|
230
|
+
* @param {GF2Polynomial} p2
|
|
231
|
+
*/
|
|
232
|
+
export const mod = (p1, p2) => {
|
|
233
|
+
const maxDeg1 = getHighestDegree(p1)
|
|
234
|
+
const maxDeg2 = getHighestDegree(p2)
|
|
235
|
+
const result = clone(p1)
|
|
236
|
+
for (let i = maxDeg1 - maxDeg2; i >= 0; i--) {
|
|
237
|
+
if (result.degrees.has(maxDeg2 + i)) {
|
|
238
|
+
const shifted = shiftLeft(p2, i)
|
|
239
|
+
addInto(result, shifted)
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return result
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Computes (p^e mod m).
|
|
247
|
+
*
|
|
248
|
+
* http://en.wikipedia.org/wiki/Modular_exponentiation
|
|
249
|
+
*
|
|
250
|
+
* @param {GF2Polynomial} p
|
|
251
|
+
* @param {number} e
|
|
252
|
+
* @param {GF2Polynomial} m
|
|
253
|
+
*/
|
|
254
|
+
export const modPow = (p, e, m) => {
|
|
255
|
+
let result = ONE
|
|
256
|
+
while (true) {
|
|
257
|
+
if ((e & 1) === 1) {
|
|
258
|
+
result = mod(multiply(result, p), m)
|
|
259
|
+
}
|
|
260
|
+
e >>>= 1
|
|
261
|
+
if (e === 0) {
|
|
262
|
+
return result
|
|
263
|
+
}
|
|
264
|
+
p = mod(multiply(p, p), m)
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Find the greatest common divisor using Euclid's Algorithm.
|
|
270
|
+
*
|
|
271
|
+
* @param {GF2Polynomial} p1
|
|
272
|
+
* @param {GF2Polynomial} p2
|
|
273
|
+
*/
|
|
274
|
+
export const gcd = (p1, p2) => {
|
|
275
|
+
while (p2.degrees.size > 0) {
|
|
276
|
+
const modded = mod(p1, p2)
|
|
277
|
+
p1 = p2
|
|
278
|
+
p2 = modded
|
|
279
|
+
}
|
|
280
|
+
return p1
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* true iff p1 equals p2
|
|
285
|
+
*
|
|
286
|
+
* @param {GF2Polynomial} p1
|
|
287
|
+
* @param {GF2Polynomial} p2
|
|
288
|
+
*/
|
|
289
|
+
export const equals = (p1, p2) => {
|
|
290
|
+
if (p1.degrees.size !== p2.degrees.size) return false
|
|
291
|
+
for (const d of p1.degrees) {
|
|
292
|
+
if (!p2.degrees.has(d)) return false
|
|
293
|
+
}
|
|
294
|
+
return true
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const X = createFromBytes(new Uint8Array([2]))
|
|
298
|
+
const ONE = createFromBytes(new Uint8Array([1]))
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Computes ( x^(2^p) - x ) mod f
|
|
302
|
+
*
|
|
303
|
+
* (shamelessly copied from
|
|
304
|
+
* https://github.com/opendedup/rabinfingerprint/blob/master/src/org/rabinfingerprint/polynomial/Polynomial.java)
|
|
305
|
+
*
|
|
306
|
+
* @param {GF2Polynomial} f
|
|
307
|
+
* @param {number} p
|
|
308
|
+
*/
|
|
309
|
+
const reduceExponent = (f, p) => {
|
|
310
|
+
// compute (x^q^p mod f)
|
|
311
|
+
const q2p = math.pow(2, p)
|
|
312
|
+
const x2q2p = modPow(X, q2p, f)
|
|
313
|
+
// subtract (x mod f)
|
|
314
|
+
return mod(add(x2q2p, X), f)
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* BenOr Reducibility Test
|
|
319
|
+
*
|
|
320
|
+
* Tests and Constructions of Irreducible Polynomials over Finite Fields
|
|
321
|
+
* (1997) Shuhong Gao, Daniel Panario
|
|
322
|
+
*
|
|
323
|
+
* http://citeseer.ist.psu.edu/cache/papers/cs/27167/http:zSzzSzwww.math.clemson.eduzSzfacultyzSzGaozSzpaperszSzGP97a.pdf/gao97tests.pdf
|
|
324
|
+
*
|
|
325
|
+
* @param {GF2Polynomial} p
|
|
326
|
+
*/
|
|
327
|
+
export const isIrreducibleBenOr = p => {
|
|
328
|
+
const degree = getHighestDegree(p)
|
|
329
|
+
for (let i = 1; i < degree / 2; i++) {
|
|
330
|
+
const b = reduceExponent(p, i)
|
|
331
|
+
const g = gcd(p, b)
|
|
332
|
+
if (!equals(g, ONE)) {
|
|
333
|
+
return false
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return true
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* @param {number} degree
|
|
341
|
+
*/
|
|
342
|
+
export const createIrreducible = degree => {
|
|
343
|
+
while (true) {
|
|
344
|
+
const p = createRandom(degree)
|
|
345
|
+
if (isIrreducibleBenOr(p)) return p
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Create a fingerprint of buf using the irreducible polynomial m.
|
|
351
|
+
*
|
|
352
|
+
* @param {Uint8Array} buf
|
|
353
|
+
* @param {GF2Polynomial} m
|
|
354
|
+
*/
|
|
355
|
+
export const fingerprint = (buf, m) => toUint8Array(mod(createFromBytes(buf), m), _degreeToMinByteLength(getHighestDegree(m) - 1))
|
|
356
|
+
|
|
357
|
+
export class RabinPolynomialEncoder {
|
|
358
|
+
/**
|
|
359
|
+
* @param {GF2Polynomial} m The irreducible polynomial
|
|
360
|
+
*/
|
|
361
|
+
constructor (m) {
|
|
362
|
+
this.fingerprint = new GF2Polynomial()
|
|
363
|
+
this.m = m
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* @param {number} b
|
|
368
|
+
*/
|
|
369
|
+
write (b) {
|
|
370
|
+
const bp = createFromBytes(new Uint8Array([b]))
|
|
371
|
+
const fingerprint = shiftLeft(this.fingerprint, 8)
|
|
372
|
+
orInto(fingerprint, bp)
|
|
373
|
+
this.fingerprint = mod(fingerprint, this.m)
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
getFingerprint () {
|
|
377
|
+
return toUint8Array(this.fingerprint, _degreeToMinByteLength(getHighestDegree(this.m) - 1))
|
|
378
|
+
}
|
|
379
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export class RabinUncachedEncoder {
|
|
2
|
+
/**
|
|
3
|
+
* @param {Uint8Array} m assert(m[0] === 1)
|
|
4
|
+
*/
|
|
5
|
+
constructor(m: Uint8Array);
|
|
6
|
+
m: Uint8Array;
|
|
7
|
+
blen: number;
|
|
8
|
+
bs: Uint8Array;
|
|
9
|
+
/**
|
|
10
|
+
* This describes the position of the most significant byte (starts with 0 and increases with
|
|
11
|
+
* shift)
|
|
12
|
+
*/
|
|
13
|
+
bpos: number;
|
|
14
|
+
/**
|
|
15
|
+
* Add/Xor/Substract bytes.
|
|
16
|
+
*
|
|
17
|
+
* Discards bytes that are out of range.
|
|
18
|
+
* @todo put this in function or inline
|
|
19
|
+
*
|
|
20
|
+
* @param {Uint8Array} cs
|
|
21
|
+
*/
|
|
22
|
+
add(cs: Uint8Array): void;
|
|
23
|
+
/**
|
|
24
|
+
* @param {number} byte
|
|
25
|
+
*/
|
|
26
|
+
write(byte: number): void;
|
|
27
|
+
getFingerprint(): Uint8Array;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=rabin-uncached.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rabin-uncached.d.ts","sourceRoot":"","sources":["rabin-uncached.js"],"names":[],"mappings":"AAUA;IACE;;OAEG;IACH,eAFW,UAAU,EAWpB;IARC,cAAU;IACV,aAAwB;IACxB,eAAmC;IACnC;;;OAGG;IACH,aAAa;IAGf;;;;;;;OAOG;IACH,QAFW,UAAU,QAQpB;IAED;;OAEG;IACH,YAFW,MAAM,QAgBhB;IAED,6BAMC;CACF"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* It is not recommended to use this package. This is the uncached implementation of the rabin
|
|
3
|
+
* fingerprint algorithm. However, it can be used to verify the `rabin.js` implementation.
|
|
4
|
+
*
|
|
5
|
+
* @module rabin-uncached
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as math from '../math.js'
|
|
9
|
+
import * as buffer from '../buffer.js'
|
|
10
|
+
|
|
11
|
+
export class RabinUncachedEncoder {
|
|
12
|
+
/**
|
|
13
|
+
* @param {Uint8Array} m assert(m[0] === 1)
|
|
14
|
+
*/
|
|
15
|
+
constructor (m) {
|
|
16
|
+
this.m = m
|
|
17
|
+
this.blen = m.byteLength
|
|
18
|
+
this.bs = new Uint8Array(this.blen)
|
|
19
|
+
/**
|
|
20
|
+
* This describes the position of the most significant byte (starts with 0 and increases with
|
|
21
|
+
* shift)
|
|
22
|
+
*/
|
|
23
|
+
this.bpos = 0
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Add/Xor/Substract bytes.
|
|
28
|
+
*
|
|
29
|
+
* Discards bytes that are out of range.
|
|
30
|
+
* @todo put this in function or inline
|
|
31
|
+
*
|
|
32
|
+
* @param {Uint8Array} cs
|
|
33
|
+
*/
|
|
34
|
+
add (cs) {
|
|
35
|
+
const copyLen = math.min(this.blen, cs.byteLength)
|
|
36
|
+
// copy from right to left until max is reached
|
|
37
|
+
for (let i = 0; i < copyLen; i++) {
|
|
38
|
+
this.bs[(this.bpos + this.blen - i - 1) % this.blen] ^= cs[cs.byteLength - i - 1]
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param {number} byte
|
|
44
|
+
*/
|
|
45
|
+
write (byte) {
|
|
46
|
+
// [0,m1,m2,b]
|
|
47
|
+
// x <- bpos
|
|
48
|
+
// Shift one byte to the left, add b
|
|
49
|
+
this.bs[this.bpos] = byte
|
|
50
|
+
this.bpos = (this.bpos + 1) % this.blen
|
|
51
|
+
// mod
|
|
52
|
+
for (let i = 7; i >= 0; i--) {
|
|
53
|
+
if (((this.bs[this.bpos] >>> i) & 1) === 1) {
|
|
54
|
+
this.add(buffer.shiftNBitsLeft(this.m, i))
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// if (this.bs[this.bpos] !== 0) { error.unexpectedCase() }
|
|
58
|
+
// assert(this.bs[this.bpos] === 0)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
getFingerprint () {
|
|
62
|
+
const result = new Uint8Array(this.blen - 1)
|
|
63
|
+
for (let i = 0; i < result.byteLength; i++) {
|
|
64
|
+
result[i] = this.bs[(this.bpos + i + 1) % this.blen]
|
|
65
|
+
}
|
|
66
|
+
return result
|
|
67
|
+
}
|
|
68
|
+
}
|
package/hash/rabin.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export const StandardIrreducible8: Uint8Array;
|
|
2
|
+
export const StandardIrreducible16: Uint8Array;
|
|
3
|
+
export const StandardIrreducible32: Uint8Array;
|
|
4
|
+
export const StandardIrreducible64: Uint8Array;
|
|
5
|
+
export const StandardIrreducible128: Uint8Array;
|
|
6
|
+
export class RabinEncoder {
|
|
7
|
+
/**
|
|
8
|
+
* @param {Uint8Array} m assert(m[0] === 1)
|
|
9
|
+
*/
|
|
10
|
+
constructor(m: Uint8Array);
|
|
11
|
+
m: Uint8Array;
|
|
12
|
+
blen: number;
|
|
13
|
+
bs: Uint8Array;
|
|
14
|
+
cache: Uint8Array;
|
|
15
|
+
/**
|
|
16
|
+
* This describes the position of the most significant byte (starts with 0 and increases with
|
|
17
|
+
* shift)
|
|
18
|
+
*/
|
|
19
|
+
bpos: number;
|
|
20
|
+
/**
|
|
21
|
+
* @param {number} byte
|
|
22
|
+
*/
|
|
23
|
+
write(byte: number): void;
|
|
24
|
+
getFingerprint(): Uint8Array;
|
|
25
|
+
}
|
|
26
|
+
export function fingerprint(irreducible: Uint8Array, data: Uint8Array): Uint8Array;
|
|
27
|
+
//# sourceMappingURL=rabin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rabin.d.ts","sourceRoot":"","sources":["rabin.js"],"names":[],"mappings":"AAUA,8CAA4D;AAC5D,+CAAkE;AAClE,+CAA4E;AAC5E,+CAA+F;AAC/F,gDAAmI;AAmCnI;IACE;;OAEG;IACH,eAFW,UAAU,EAYpB;IATC,cAAU;IACV,aAAwB;IACxB,eAAmC;IACnC,kBAA2B;IAC3B;;;OAGG;IACH,aAAa;IAGf;;OAEG;IACH,YAFW,MAAM,QAYhB;IAED,6BAMC;CACF;AAMM,yCAHI,UAAU,QACV,UAAU,cAQpB"}
|
package/hash/rabin.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module rabin
|
|
3
|
+
*
|
|
4
|
+
* Very efficient & versatile fingerprint/hashing algorithm. However, it is not cryptographically
|
|
5
|
+
* secure. Well suited for fingerprinting.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as buffer from '../buffer.js'
|
|
9
|
+
import * as map from '../map.js'
|
|
10
|
+
|
|
11
|
+
export const StandardIrreducible8 = new Uint8Array([1, 221])
|
|
12
|
+
export const StandardIrreducible16 = new Uint8Array([1, 244, 157])
|
|
13
|
+
export const StandardIrreducible32 = new Uint8Array([1, 149, 183, 205, 191])
|
|
14
|
+
export const StandardIrreducible64 = new Uint8Array([1, 133, 250, 114, 193, 250, 28, 193, 231])
|
|
15
|
+
export const StandardIrreducible128 = new Uint8Array([1, 94, 109, 166, 228, 6, 222, 102, 239, 27, 128, 184, 13, 50, 112, 169, 199])
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Maps from a modulo to the precomputed values.
|
|
19
|
+
*
|
|
20
|
+
* @type {Map<string,Uint8Array>}
|
|
21
|
+
*/
|
|
22
|
+
const _precomputedFingerprintCache = new Map()
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @param {Uint8Array} m
|
|
26
|
+
*/
|
|
27
|
+
const ensureCache = m => map.setIfUndefined(_precomputedFingerprintCache, buffer.toBase64(m), () => {
|
|
28
|
+
const byteLen = m.byteLength
|
|
29
|
+
const cache = new Uint8Array(256 * byteLen)
|
|
30
|
+
// Use dynamic computing to compute the cached results.
|
|
31
|
+
// Starting values: cache(0) = 0; cache(1) = m
|
|
32
|
+
cache.set(m, byteLen)
|
|
33
|
+
for (let bit = 1; bit < 8; bit++) {
|
|
34
|
+
const mBitShifted = buffer.shiftNBitsLeft(m, bit)
|
|
35
|
+
const bitShifted = 1 << bit
|
|
36
|
+
for (let j = 0; j < bitShifted; j++) {
|
|
37
|
+
// apply the shifted result (reducing the degree of the polynomial)
|
|
38
|
+
const msb = bitShifted | j
|
|
39
|
+
const rest = msb ^ mBitShifted[0]
|
|
40
|
+
for (let i = 0; i < byteLen; i++) {
|
|
41
|
+
// rest is already precomputed in the cache
|
|
42
|
+
cache[msb * byteLen + i] = cache[rest * byteLen + i] ^ mBitShifted[i]
|
|
43
|
+
}
|
|
44
|
+
// if (cache[(bitShifted | j) * byteLen] !== (bitShifted | j)) { error.unexpectedCase() }
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return cache
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
export class RabinEncoder {
|
|
51
|
+
/**
|
|
52
|
+
* @param {Uint8Array} m assert(m[0] === 1)
|
|
53
|
+
*/
|
|
54
|
+
constructor (m) {
|
|
55
|
+
this.m = m
|
|
56
|
+
this.blen = m.byteLength
|
|
57
|
+
this.bs = new Uint8Array(this.blen)
|
|
58
|
+
this.cache = ensureCache(m)
|
|
59
|
+
/**
|
|
60
|
+
* This describes the position of the most significant byte (starts with 0 and increases with
|
|
61
|
+
* shift)
|
|
62
|
+
*/
|
|
63
|
+
this.bpos = 0
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @param {number} byte
|
|
68
|
+
*/
|
|
69
|
+
write (byte) {
|
|
70
|
+
// assert(this.bs[0] === 0)
|
|
71
|
+
// Shift one byte to the left, add b
|
|
72
|
+
this.bs[this.bpos] = byte
|
|
73
|
+
this.bpos = (this.bpos + 1) % this.blen
|
|
74
|
+
const msb = this.bs[this.bpos]
|
|
75
|
+
for (let i = 0; i < this.blen; i++) {
|
|
76
|
+
this.bs[(this.bpos + i) % this.blen] ^= this.cache[msb * this.blen + i]
|
|
77
|
+
}
|
|
78
|
+
// assert(this.bs[this.bpos] === 0)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
getFingerprint () {
|
|
82
|
+
const result = new Uint8Array(this.blen - 1)
|
|
83
|
+
for (let i = 0; i < result.byteLength; i++) {
|
|
84
|
+
result[i] = this.bs[(this.bpos + i + 1) % this.blen]
|
|
85
|
+
}
|
|
86
|
+
return result
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @param {Uint8Array} irreducible
|
|
92
|
+
* @param {Uint8Array} data
|
|
93
|
+
*/
|
|
94
|
+
export const fingerprint = (irreducible, data) => {
|
|
95
|
+
const encoder = new RabinEncoder(irreducible)
|
|
96
|
+
for (let i = 0; i < data.length; i++) {
|
|
97
|
+
encoder.write(data[i])
|
|
98
|
+
}
|
|
99
|
+
return encoder.getFingerprint()
|
|
100
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export function testPolynomialBasics(_tc: t.TestCase): void;
|
|
2
|
+
export function testIrreducibleInput(_tc: t.TestCase): void;
|
|
3
|
+
export function testIrreducibleSpread(_tc: t.TestCase): void;
|
|
4
|
+
export function testGenerateIrreducibles(_tc: t.TestCase): void;
|
|
5
|
+
export function testFingerprintCompatiblity(tc: t.TestCase): void;
|
|
6
|
+
export function testConflicts(tc: t.TestCase): void;
|
|
7
|
+
import * as t from '../testing.js';
|
|
8
|
+
//# sourceMappingURL=rabin.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rabin.test.d.ts","sourceRoot":"","sources":["rabin.test.js"],"names":[],"mappings":"AAaO,0CAFI,EAAE,QAAQ,QASpB;AAKM,0CAFI,EAAE,QAAQ,QAapB;AAKM,2CAFI,EAAE,QAAQ,QASpB;AAwBM,8CAFI,EAAE,QAAQ,QAyBpB;AAmGM,gDAFI,EAAE,QAAQ,QAQpB;AAKM,kCAFI,EAAE,QAAQ,QA4BpB;mBAvOkB,eAAe"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sha256.fallback.d.ts","sourceRoot":"","sources":["sha256.fallback.js"],"names":[],"mappings":"AA2KO,6BAFI,UAAU,cAEkC"}
|