@quenty/ellipticcurvecryptography 1.11.0 → 1.13.0

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.
@@ -1,4 +1,4 @@
1
- --!nonstrict
1
+ --!strict
2
2
  --!native
3
3
 
4
4
  --[=[
@@ -39,6 +39,9 @@ local modq = require(script.modq)
39
39
  local random = require(script.random)
40
40
  local sha256 = require(script.sha256)
41
41
  local util = require(script.util)
42
+
43
+ type ByteTable = typeof(setmetatable({} :: { number }, {} :: typeof(util.byteTableMT)))
44
+
42
45
  local EllipticCurveCryptography = {}
43
46
 
44
47
  EllipticCurveCryptography.chacha20 = chacha20
@@ -52,7 +55,7 @@ EllipticCurveCryptography._byteMetatable = assert(util.byteTableMT, "No byteTabl
52
55
  @param key any
53
56
  @return boolean
54
57
  ]=]
55
- function EllipticCurveCryptography.isByteTable(key)
58
+ function EllipticCurveCryptography.isByteTable(key: any): boolean
56
59
  return type(key) == "table" and getmetatable(key) == EllipticCurveCryptography._byteMetatable
57
60
  end
58
61
 
@@ -61,14 +64,14 @@ end
61
64
 
62
65
  @param value any
63
66
  ]=]
64
- function EllipticCurveCryptography.createByteTable(value)
67
+ function EllipticCurveCryptography.createByteTable(value: { number }): ByteTable
65
68
  assert(type(value) == "table", "Bad value")
66
69
 
67
70
  return setmetatable(table.clone(value), EllipticCurveCryptography._byteMetatable)
68
71
  end
69
72
 
70
- function EllipticCurveCryptography._getNonceFromEpoch()
71
- local nonce = table.create(12)
73
+ function EllipticCurveCryptography._getNonceFromEpoch(): { number }
74
+ local nonce: { number } = table.create(12)
72
75
  local epoch = DateTime.now().UnixTimestampMillis
73
76
  for i = 1, 12 do
74
77
  nonce[i] = epoch % 256
@@ -98,23 +101,23 @@ end
98
101
  @param key ByteTable
99
102
  @return ByteTable
100
103
  ]=]
101
- function EllipticCurveCryptography.encrypt(data, key)
104
+ function EllipticCurveCryptography.encrypt(data: string | ByteTable, key: ByteTable): ByteTable
102
105
  assert(type(data) == "string" or EllipticCurveCryptography.isByteTable(data), "Bad data")
103
106
  assert(EllipticCurveCryptography.isByteTable(key), "Bad key")
104
107
 
105
- local encKey = sha256.hmac("encKey", key)
106
- local macKey = sha256.hmac("macKey", key)
108
+ local encKey = sha256.hmac("encKey", (key :: any) :: { number })
109
+ local macKey = sha256.hmac("macKey", (key :: any) :: { number })
107
110
  local nonce = EllipticCurveCryptography._getNonceFromEpoch()
108
111
 
109
- local ciphertext = chacha20.crypt(data, encKey, nonce)
112
+ local ciphertext = chacha20.crypt(data :: any, (encKey :: any) :: { number }, nonce)
110
113
 
111
- local result = nonce
112
- for _, value in ipairs(ciphertext) do
114
+ local result: { number } = nonce
115
+ for _, value in ipairs(ciphertext :: any) do
113
116
  table.insert(result, value)
114
117
  end
115
118
 
116
- local mac = sha256.hmac(result, macKey)
117
- for _, value in ipairs(mac) do
119
+ local mac = sha256.hmac(result, (macKey :: any) :: { number })
120
+ for _, value in ipairs((mac :: any) :: { number }) do
118
121
  table.insert(result, value)
119
122
  end
120
123
 
@@ -135,21 +138,22 @@ end
135
138
  @param key ByteTable
136
139
  @return ByteTable
137
140
  ]=]
138
- function EllipticCurveCryptography.decrypt(data, key)
141
+ function EllipticCurveCryptography.decrypt(data: string | ByteTable, key: ByteTable): ByteTable
139
142
  assert(type(data) == "string" or EllipticCurveCryptography.isByteTable(data), "Bad data")
140
143
  assert(EllipticCurveCryptography.isByteTable(key), "Bad key")
141
144
 
142
- local actualData = type(data) == "table" and { table.unpack(data) } or { string.byte(tostring(data), 1, -1) }
143
- local encKey = sha256.hmac("encKey", key)
144
- local macKey = sha256.hmac("macKey", key)
145
- local mac = sha256.hmac({ table.unpack(actualData, 1, #actualData - 32) }, macKey)
145
+ local actualData: { number } = type(data) == "table" and { table.unpack(data :: any) }
146
+ or { string.byte(tostring(data), 1, -1) }
147
+ local encKey = sha256.hmac("encKey", (key :: any) :: { number })
148
+ local macKey = sha256.hmac("macKey", (key :: any) :: { number })
149
+ local mac = sha256.hmac({ table.unpack(actualData, 1, #actualData - 32) }, (macKey :: any) :: { number })
146
150
  local messageMac = { table.unpack(actualData, #actualData - 31) }
147
- assert(mac:isEqual(messageMac), "invalid mac")
151
+ assert((mac :: any):isEqual(messageMac), "invalid mac")
148
152
  local nonce = { table.unpack(actualData, 1, 12) }
149
153
  local ciphertext = { table.unpack(actualData, 13, #actualData - 32) }
150
- local result = chacha20.crypt(ciphertext, encKey, nonce)
154
+ local result: ByteTable = chacha20.crypt(ciphertext, (encKey :: any) :: { number }, nonce)
151
155
 
152
- return setmetatable(result, util.byteTableMT)
156
+ return result
153
157
  end
154
158
 
155
159
  --[=[
@@ -167,10 +171,10 @@ end
167
171
  @return ByteTable -- privateKey
168
172
  @return ByteTable -- publicKey
169
173
  ]=]
170
- function EllipticCurveCryptography.keypair(seed)
174
+ function EllipticCurveCryptography.keypair(seed: number): (ByteTable, ByteTable)
171
175
  assert(type(seed) == "number", "Bad seed")
172
176
 
173
- local x
177
+ local x: any
174
178
  if seed then
175
179
  x = modq.hashModQ(seed)
176
180
  else
@@ -179,8 +183,8 @@ function EllipticCurveCryptography.keypair(seed)
179
183
 
180
184
  local Y = curve.G * x
181
185
 
182
- local privateKey = x:encode()
183
- local publicKey = Y:encode()
186
+ local privateKey: ByteTable = x:encode()
187
+ local publicKey: ByteTable = Y:encode()
184
188
 
185
189
  return privateKey, publicKey
186
190
  end
@@ -203,15 +207,15 @@ end
203
207
  @param publicKey ByteTable
204
208
  @return ByteTable
205
209
  ]=]
206
- function EllipticCurveCryptography.exchange(privateKey, publicKey)
210
+ function EllipticCurveCryptography.exchange(privateKey: ByteTable, publicKey: ByteTable): ByteTable
207
211
  assert(EllipticCurveCryptography.isByteTable(privateKey), "Bad privateKey")
208
212
  assert(EllipticCurveCryptography.isByteTable(publicKey), "Bad publicKey")
209
213
 
210
214
  local x = modq.decodeModQ(privateKey)
211
- local Y = curve.pointDecode(publicKey)
215
+ local Y = curve.pointDecode(publicKey :: any)
212
216
  local Z = Y * x
213
217
 
214
- local sharedSecret = sha256.digest(Z:encode())
218
+ local sharedSecret: ByteTable = sha256.digest(Z:encode())
215
219
 
216
220
  return sharedSecret
217
221
  end
@@ -227,24 +231,25 @@ end
227
231
  @param message string | EncodedMessage
228
232
  @return ByteTable
229
233
  ]=]
230
- function EllipticCurveCryptography.sign(privateKey, message)
234
+ function EllipticCurveCryptography.sign(privateKey: ByteTable, message: string | ByteTable): ByteTable
231
235
  assert(EllipticCurveCryptography.isByteTable(privateKey), "Bad privateKey")
232
236
  assert(type(message) == "string" or EllipticCurveCryptography.isByteTable(message), "Bad message")
233
237
 
234
- local actualMessage = type(message) == "table" and string.char(table.unpack(message)) or tostring(message)
235
- local actualPrivateKey = type(privateKey) == "table" and string.char(table.unpack(privateKey))
238
+ local actualMessage = type(message) == "table" and string.char(table.unpack(message :: any)) or tostring(message)
239
+ local actualPrivateKey = type(privateKey) == "table" and string.char(table.unpack(privateKey :: any))
236
240
  or tostring(privateKey)
237
241
 
238
- local x = modq.decodeModQ(actualPrivateKey)
239
- local k = modq.randomModQ()
242
+ local x: any = modq.decodeModQ(actualPrivateKey)
243
+ local k: any = modq.randomModQ()
240
244
  local R = curve.G * k
241
- local e = modq.hashModQ(actualMessage .. tostring(R))
245
+ local e: any = modq.hashModQ(actualMessage .. tostring(R))
242
246
  local s = k - x * e
243
247
 
244
248
  e = e:encode()
245
249
  s = s:encode()
246
250
 
247
- local result, result_len = e, #e
251
+ local result: { number } = e
252
+ local result_len = #e
248
253
  for index, value in ipairs(s) do
249
254
  result[result_len + index] = value
250
255
  end
@@ -265,16 +270,20 @@ end
265
270
  @param message ByteTable | string
266
271
  @param signature ByteTable
267
272
  ]=]
268
- function EllipticCurveCryptography.verify(publicKey, message, signature)
273
+ function EllipticCurveCryptography.verify(
274
+ publicKey: ByteTable,
275
+ message: string | ByteTable,
276
+ signature: ByteTable
277
+ ): boolean
269
278
  assert(EllipticCurveCryptography.isByteTable(publicKey), "Bad privateKey")
270
279
  assert(type(message) == "string" or EllipticCurveCryptography.isByteTable(message), "Bad message")
271
280
  assert(EllipticCurveCryptography.isByteTable(signature), "Bad signature")
272
281
 
273
- local actualMessage = type(message) == "table" and string.char(table.unpack(message)) or tostring(message)
282
+ local actualMessage = type(message) == "table" and string.char(table.unpack(message :: any)) or tostring(message)
274
283
  local sigLen = #signature
275
- local Y = curve.pointDecode(publicKey)
276
- local e = modq.decodeModQ({ table.unpack(signature, 1, sigLen / 2) })
277
- local s = modq.decodeModQ({ table.unpack(signature, sigLen / 2 + 1) })
284
+ local Y = curve.pointDecode(publicKey :: any)
285
+ local e = modq.decodeModQ({ table.unpack(signature :: any, 1, sigLen / 2) })
286
+ local s = modq.decodeModQ({ table.unpack(signature :: any, sigLen / 2 + 1) })
278
287
  local Rv = curve.G * s + Y * e
279
288
  local ev = modq.hashModQ(actualMessage .. tostring(Rv))
280
289
 
@@ -1,4 +1,4 @@
1
- --!nonstrict
1
+ --!strict
2
2
  -- Arithmetic on the finite field of integers modulo p
3
3
  -- Where p is the finite field modulus
4
4
  local arith = require(script.Parent.arith)
@@ -8,17 +8,20 @@ local addDouble = arith.addDouble
8
8
  local mult = arith.mult
9
9
  local square = arith.square
10
10
 
11
- local p = { 3, 0, 0, 0, 0, 0, 15761408 }
11
+ type BigInt = { number }
12
+ type DoubleInt = { number }
13
+
14
+ local p: BigInt = { 3, 0, 0, 0, 0, 0, 15761408 }
12
15
 
13
16
  -- We're using the Montgomery Reduction for fast modular multiplication.
14
17
  -- https://en.wikipedia.org/wiki/Montgomery_modular_multiplication
15
18
  -- r = 2^168
16
19
  -- p * pInverse = -1 (mod r)
17
20
  -- r2 = r * r (mod p)
18
- local pInverse = { 5592405, 5592405, 5592405, 5592405, 5592405, 5592405, 14800213 }
19
- local r2 = { 13533400, 837116, 6278376, 13533388, 837116, 6278376, 7504076 }
21
+ local pInverse: BigInt = { 5592405, 5592405, 5592405, 5592405, 5592405, 5592405, 14800213 }
22
+ local r2: BigInt = { 13533400, 837116, 6278376, 13533388, 837116, 6278376, 7504076 }
20
23
 
21
- local function multByP(a)
24
+ local function multByP(a: BigInt): DoubleInt
22
25
  local a1, a2, a3, a4, a5, a6, a7 = a[1], a[2], a[3], a[4], a[5], a[6], a[7]
23
26
 
24
27
  local c1 = a1 * 3
@@ -82,7 +85,7 @@ local function multByP(a)
82
85
  end
83
86
 
84
87
  -- Reduces a number from [0, 2p - 1] to [0, p - 1]
85
- local function reduceModP(a)
88
+ local function reduceModP(a: BigInt): BigInt
86
89
  -- a < p
87
90
  if a[7] < 15761408 or a[7] == 15761408 and a[1] < 3 then
88
91
  return { table.unpack(a) }
@@ -133,11 +136,11 @@ local function reduceModP(a)
133
136
  return { c1, c2, c3, c4, c5, c6, c7 }
134
137
  end
135
138
 
136
- local function addModP(a, b)
139
+ local function addModP(a: BigInt, b: BigInt): BigInt
137
140
  return reduceModP(add(a, b))
138
141
  end
139
142
 
140
- local function subModP(a, b)
143
+ local function subModP(a: BigInt, b: BigInt): BigInt
141
144
  local result = sub(a, b)
142
145
 
143
146
  if result[7] < 0 then
@@ -149,29 +152,29 @@ end
149
152
 
150
153
  -- Montgomery REDC algorithn
151
154
  -- Reduces a number from [0, p^2 - 1] to [0, p - 1]
152
- local function REDC(T)
155
+ local function REDC(T: DoubleInt): BigInt
153
156
  local m = mult(T, pInverse, true)
154
- local t = { table.unpack(addDouble(T, multByP(m)), 8, 14) }
157
+ local t: BigInt = { table.unpack(addDouble(T, multByP(m)), 8, 14) }
155
158
 
156
159
  return reduceModP(t)
157
160
  end
158
161
 
159
- local function multModP(a, b)
162
+ local function multModP(a: BigInt, b: BigInt): BigInt
160
163
  -- Only works with a, b in Montgomery form
161
- return REDC(mult(a, b))
164
+ return REDC(mult(a, b, false))
162
165
  end
163
166
 
164
- local function squareModP(a)
167
+ local function squareModP(a: BigInt): BigInt
165
168
  -- Only works with a in Montgomery form
166
169
  return REDC(square(a))
167
170
  end
168
171
 
169
- local function montgomeryModP(a)
172
+ local function montgomeryModP(a: BigInt): BigInt
170
173
  return multModP(a, r2)
171
174
  end
172
175
 
173
- local function inverseMontgomeryModP(a)
174
- local newA = { table.unpack(a) }
176
+ local function inverseMontgomeryModP(a: BigInt): BigInt
177
+ local newA: DoubleInt = { table.unpack(a) }
175
178
 
176
179
  for i = 8, 14 do
177
180
  newA[i] = 0
@@ -180,11 +183,11 @@ local function inverseMontgomeryModP(a)
180
183
  return REDC(newA)
181
184
  end
182
185
 
183
- local ONE = montgomeryModP({ 1, 0, 0, 0, 0, 0, 0 })
186
+ local ONE: BigInt = montgomeryModP({ 1, 0, 0, 0, 0, 0, 0 })
184
187
 
185
- local function expModP(base, exponentBinary)
186
- local newBase = { table.unpack(base) }
187
- local result = { table.unpack(ONE) }
188
+ local function expModP(base: BigInt, exponentBinary: { number }): BigInt
189
+ local newBase: BigInt = { table.unpack(base) }
190
+ local result: BigInt = { table.unpack(ONE) }
188
191
 
189
192
  for i = 1, 168 do
190
193
  if exponentBinary[i] == 1 then
@@ -1,4 +1,4 @@
1
- --!nonstrict
1
+ --!strict
2
2
  --!native
3
3
 
4
4
  -- Arithmetic on the Finite Field of Integers modulo q
@@ -8,6 +8,8 @@ local random = require(script.Parent.random)
8
8
  local sha256 = require(script.Parent.sha256)
9
9
  local util = require(script.Parent.util)
10
10
 
11
+ type BigInt = { number }
12
+
11
13
  local isEqual = arith.isEqual
12
14
  local compare = arith.compare
13
15
  local add = arith.add
@@ -18,11 +20,11 @@ local square = arith.square
18
20
  local encodeInt = arith.encodeInt
19
21
  local decodeInt = arith.decodeInt
20
22
 
21
- local modQMT
23
+ local modQMT: any
22
24
 
23
- local q = { 9622359, 6699217, 13940450, 16775734, 16777215, 16777215, 3940351 }
25
+ local q: BigInt = { 9622359, 6699217, 13940450, 16775734, 16777215, 16777215, 3940351 }
24
26
  -- this isn't an optimization, it just shortens the amount of time I have to scroll
25
- local qMinusTwoBinary = table.create(166, 1)
27
+ local qMinusTwoBinary: { number } = table.create(166, 1)
26
28
  qMinusTwoBinary[2] = 0
27
29
  qMinusTwoBinary[4] = 0
28
30
  qMinusTwoBinary[6] = 0
@@ -76,59 +78,59 @@ qMinusTwoBinary[162] = 0
76
78
  -- r = 2^168
77
79
  -- q * qInverse = -1 (mod r)
78
80
  -- r2 = r * r (mod q)
79
- local qInverse = { 15218585, 5740955, 3271338, 9903997, 9067368, 7173545, 6988392 }
80
- local r2 = { 1336213, 11071705, 9716828, 11083885, 9188643, 1494868, 3306114 }
81
+ local qInverse: BigInt = { 15218585, 5740955, 3271338, 9903997, 9067368, 7173545, 6988392 }
82
+ local r2: BigInt = { 1336213, 11071705, 9716828, 11083885, 9188643, 1494868, 3306114 }
81
83
 
82
84
  -- Reduces a number from [0, 2q - 1] to [0, q - 1]
83
- local function reduceModQ(a)
84
- local result = { table.unpack(a) }
85
+ local function reduceModQ(a: BigInt): BigInt
86
+ local result: BigInt = { table.unpack(a) }
85
87
 
86
88
  if compare(result, q) >= 0 then
87
89
  result = sub(result, q)
88
90
  end
89
91
 
90
- return setmetatable(result, modQMT)
92
+ return setmetatable(result, modQMT) :: any
91
93
  end
92
94
 
93
- local function addModQ(a, b)
95
+ local function addModQ(a: BigInt, b: BigInt): BigInt
94
96
  return reduceModQ(add(a, b))
95
97
  end
96
98
 
97
- local function subModQ(a, b)
98
- local result = sub(a, b)
99
+ local function subModQ(a: BigInt, b: BigInt): BigInt
100
+ local result: BigInt = sub(a, b)
99
101
 
100
102
  if result[7] < 0 then
101
103
  result = add(result, q)
102
104
  end
103
105
 
104
- return setmetatable(result, modQMT)
106
+ return setmetatable(result, modQMT) :: any
105
107
  end
106
108
 
107
109
  -- Montgomery REDC algorithn
108
110
  -- Reduces a number from [0, q^2 - 1] to [0, q - 1]
109
- local function REDC(T)
110
- local m = { table.unpack(mult({ table.unpack(T, 1, 7) }, qInverse, true), 1, 7) }
111
- local t = { table.unpack(addDouble(T, mult(m, q)), 8, 14) }
111
+ local function REDC(T: { number }): BigInt
112
+ local m: BigInt = { table.unpack(mult({ table.unpack(T, 1, 7) }, qInverse, true), 1, 7) }
113
+ local t: BigInt = { table.unpack(addDouble(T, mult(m, q, false)), 8, 14) }
112
114
 
113
115
  return reduceModQ(t)
114
116
  end
115
117
 
116
- local function multModQ(a, b)
118
+ local function multModQ(a: BigInt, b: BigInt): BigInt
117
119
  -- Only works with a, b in Montgomery form
118
- return REDC(mult(a, b))
120
+ return REDC(mult(a, b, false))
119
121
  end
120
122
 
121
- local function squareModQ(a)
123
+ local function squareModQ(a: BigInt): BigInt
122
124
  -- Only works with a in Montgomery form
123
125
  return REDC(square(a))
124
126
  end
125
127
 
126
- local function montgomeryModQ(a)
128
+ local function montgomeryModQ(a: BigInt): BigInt
127
129
  return multModQ(a, r2)
128
130
  end
129
131
 
130
- local function inverseMontgomeryModQ(a)
131
- local newA = { table.unpack(a) }
132
+ local function inverseMontgomeryModQ(a: BigInt): BigInt
133
+ local newA: { number } = { table.unpack(a) }
132
134
 
133
135
  for i = 8, 14 do
134
136
  newA[i] = 0
@@ -137,11 +139,11 @@ local function inverseMontgomeryModQ(a)
137
139
  return REDC(newA)
138
140
  end
139
141
 
140
- local ONE = montgomeryModQ({ 1, 0, 0, 0, 0, 0, 0 })
142
+ local ONE: BigInt = montgomeryModQ({ 1, 0, 0, 0, 0, 0, 0 })
141
143
 
142
- local function expModQ(base, exponentBinary)
143
- local newBase = { table.unpack(base) }
144
- local result = { table.unpack(ONE) }
144
+ local function expModQ(base: BigInt, exponentBinary: { number }): BigInt
145
+ local newBase: BigInt = { table.unpack(base) }
146
+ local result: BigInt = { table.unpack(ONE) }
145
147
 
146
148
  for i = 1, 168 do
147
149
  if exponentBinary[i] == 1 then
@@ -154,9 +156,9 @@ local function expModQ(base, exponentBinary)
154
156
  return result
155
157
  end
156
158
 
157
- local function intExpModQ(base, exponent)
158
- local newBase = { table.unpack(base) }
159
- local result = setmetatable({ table.unpack(ONE) }, modQMT)
159
+ local function intExpModQ(base: BigInt, exponent: number): BigInt
160
+ local newBase: BigInt = { table.unpack(base) }
161
+ local result: BigInt = setmetatable({ table.unpack(ONE) }, modQMT) :: any
160
162
 
161
163
  if exponent < 0 then
162
164
  newBase = expModQ(newBase, qMinusTwoBinary)
@@ -175,46 +177,46 @@ local function intExpModQ(base, exponent)
175
177
  return result
176
178
  end
177
179
 
178
- local function encodeModQ(a)
180
+ local function encodeModQ(a: BigInt): { number }
179
181
  local result = encodeInt(a)
180
182
 
181
- return setmetatable(result, util.byteTableMT)
183
+ return setmetatable(result, util.byteTableMT) :: any
182
184
  end
183
185
 
184
- local function decodeModQ(s)
185
- s = type(s) == "table" and { table.unpack(s, 1, 21) } or { string.byte(tostring(s), 1, 21) }
186
- local result = decodeInt(s)
186
+ local function decodeModQ(s: any): BigInt
187
+ s = type(s) == "table" and { table.unpack(s :: { number }, 1, 21) } or { string.byte(tostring(s), 1, 21) }
188
+ local result: BigInt = decodeInt(s)
187
189
  result[7] %= q[7]
188
190
 
189
- return setmetatable(result, modQMT)
191
+ return setmetatable(result, modQMT) :: any
190
192
  end
191
193
 
192
- local function randomModQ()
194
+ local function randomModQ(): BigInt
193
195
  while true do
194
- local s = { table.unpack(random.random(), 1, 21) }
195
- local result = decodeInt(s)
196
+ local s: { number } = { table.unpack(random.random() :: any, 1, 21) }
197
+ local result: BigInt = decodeInt(s)
196
198
  if result[7] < q[7] then
197
- return setmetatable(result, modQMT)
199
+ return setmetatable(result, modQMT) :: any
198
200
  end
199
201
  end
200
202
  end
201
203
 
202
- local function hashModQ(data)
204
+ local function hashModQ(data: any): BigInt
203
205
  return decodeModQ(sha256.digest(data))
204
206
  end
205
207
 
206
208
  modQMT = {
207
209
  __index = {
208
- encode = function(self)
210
+ encode = function(self: BigInt): { number }
209
211
  return encodeModQ(self)
210
212
  end,
211
213
  },
212
214
 
213
- __tostring = function(self)
214
- return self:encode():toHex()
215
+ __tostring = function(self: BigInt): string
216
+ return (self :: any):encode():toHex()
215
217
  end,
216
218
 
217
- __add = function(self, other)
219
+ __add = function(self: any, other: any): BigInt
218
220
  if type(self) == "number" then
219
221
  return other + self
220
222
  end
@@ -227,7 +229,7 @@ modQMT = {
227
229
  return addModQ(self, other)
228
230
  end,
229
231
 
230
- __sub = function(a, b)
232
+ __sub = function(a: any, b: any): BigInt
231
233
  if type(a) == "number" then
232
234
  assert(a < 16777216, "number operand too big")
233
235
  a = montgomeryModQ({ a, 0, 0, 0, 0, 0, 0 })
@@ -241,15 +243,15 @@ modQMT = {
241
243
  return subModQ(a, b)
242
244
  end,
243
245
 
244
- __unm = function(self)
246
+ __unm = function(self: BigInt): BigInt
245
247
  return subModQ(q, self)
246
248
  end,
247
249
 
248
- __eq = function(self, other)
250
+ __eq = function(self: BigInt, other: BigInt): boolean
249
251
  return isEqual(self, other)
250
252
  end,
251
253
 
252
- __mul = function(self, other)
254
+ __mul = function(self: any, other: any): BigInt
253
255
  if type(self) == "number" then
254
256
  return other * self
255
257
  end
@@ -268,7 +270,7 @@ modQMT = {
268
270
  return multModQ(self, other)
269
271
  end,
270
272
 
271
- __div = function(a, b)
273
+ __div = function(a: any, b: any): BigInt
272
274
  if type(a) == "number" then
273
275
  assert(a < 16777216, "number operand too big")
274
276
  a = montgomeryModQ({ a, 0, 0, 0, 0, 0, 0 })
@@ -279,12 +281,12 @@ modQMT = {
279
281
  b = montgomeryModQ({ b, 0, 0, 0, 0, 0, 0 })
280
282
  end
281
283
 
282
- local bInv = expModQ(b, qMinusTwoBinary)
284
+ local bInv: BigInt = expModQ(b, qMinusTwoBinary)
283
285
 
284
286
  return multModQ(a, bInv)
285
287
  end,
286
288
 
287
- __pow = function(self, other)
289
+ __pow = function(self: BigInt, other: number): BigInt
288
290
  return intExpModQ(self, other)
289
291
  end,
290
292
  }
@@ -1,15 +1,16 @@
1
- --!nonstrict
1
+ --!strict
2
2
  --!native
3
3
 
4
4
  -- random.lua - Random Byte Generator
5
5
  local sha256 = require(script.Parent.sha256)
6
6
 
7
- local entropy = ""
8
- local accumulator, accumulator_len = {}, 0
7
+ local entropy: string = ""
8
+ local accumulator: { string } = {}
9
+ local accumulator_len: number = 0
9
10
 
10
11
  local random = {}
11
12
 
12
- local function feed(data)
13
+ local function feed(data: any)
13
14
  accumulator_len += 1
14
15
  accumulator[accumulator_len] = tostring(data or "")
15
16
  end
@@ -21,7 +22,7 @@ local function digest()
21
22
  accumulator_len = 0
22
23
  end
23
24
 
24
- local entropyInitialized = false
25
+ local entropyInitialized: boolean = false
25
26
 
26
27
  -- Defer this initialization until requested
27
28
  local function ensureEntropyInit()
@@ -55,7 +56,7 @@ local function ensureEntropyInit()
55
56
  -- TODO: Suppress this warning
56
57
  warn(
57
58
  string.format(
58
- "[EllipticCurveCryptography.random] - Generating entropy took %s ms",
59
+ "[EllipticCurveCryptography.random] - Generating entropy took %g ms",
59
60
  1000 * (os.clock() - startTime)
60
61
  )
61
62
  )
@@ -72,7 +73,7 @@ function random.save()
72
73
  entropy = tostring(sha256.digest(entropy))
73
74
  end
74
75
 
75
- function random.seed(data)
76
+ function random.seed(data: any)
76
77
  ensureEntropyInit()
77
78
 
78
79
  feed("seed")
@@ -83,7 +84,7 @@ function random.seed(data)
83
84
  random.save()
84
85
  end
85
86
 
86
- function random.random()
87
+ function random.random(): any
87
88
  ensureEntropyInit()
88
89
 
89
90
  feed("random")