Constant-time algorithms written in TypeScript.
Important: This Github repository is the companion to Soatok's Guide to Side-Channel Attacks. Do not use this in production, especially if you don't have the budget for a cryptography audit.
This is just a quick outline of what each function does.
compare(a, b)
- Compare twoUint8Array
objects.- Explanation
- Returns
-1
ifa < b
- Returns
1
ifa > b
- Returns
0
ifa === b
- Throws an
Error
ifa.length !== b.length
compare_ints(a, b)
- Compare two integers.- Explanation
- Returns
-1
ifa < b
- Returns
1
ifa > b
- Returns
0
ifa === b
equals(a, b)
- Are theseUint8Array
objects equal?- Explanation
- Returns
true
if they are equal. - Returns
false
if they are not equal. - Throws an
Error
ifa.length !== b.length
hmac_equals(a, b)
- Are theseUint8Array
objects equal? (Using HMAC to compare.)- Explanation
- Returns
true
if they are equal. - Returns
false
if they are not equal. - Throws an
Error
ifa.length !== b.length
intdiv(N, D)
- DivideN
intoD
, discarding remainder.- Explanation
- Returns an integer.
modulo(N, D)
- DivideN
intoD
, return the remainder.- Explanation
- Returns an integer.
resize(buf, size)
- Return a resizedUint8Array
object (to side-step memory access leakage)select(x, a, b)
- Read it as a ternary. Ifx
is true, returnsa
. Otherwise, returnsb
.- Explanation
x
must be aboolean
a
must be aUint8Array
b
must be aUint8Array
- Throws an
Error
ifa.length !== b.length
select_ints(x, a, b)
- Read it as a ternary. Ifx
is even, returnsa
. Otherwise, returnsb
. (You should pass1
or0
forx
).- Explanation
x
must be aboolean
a
must be anumber
b
must be anumber
trim_zeroes_left(buf)
- Explanation
buf
must be aUint8Array
- Returns a
Uint8Array
trim_zeroes_right(buf)
- Explanation
buf
must be aUint8Array
- Returns a
Uint8Array
- Constant-Time Integer Multiplication
- Constant-Time Modular Inversion
32-bit v8 (and, presumably, a lot of other 32-bit implementations) do things wrong, and our implementation might be variable-time on it.
Specifically, the most significant bit of a 32-bit integer distinguishes values from pointers. As a result, accessing the highest bit of a 32-bit number in 32-bit JavaScript engines (such as v8) is potentially variable-time.
To mitigate this risk, the int32
class was created
which wraps operates on 16-bit limbs (wrapping Uint16Array
).
For science!
This is a proof-of-concept library, that will eventually implement all of the algorithms described in the accompanying blog post.
The main purpose of this library is to demonstrate the concepts in a programming language widely accessible outside of the cryptography orthodoxy (which today is largely C and sometimes Python, and hopefully soon Rust).
Hold off until v1.0.0 is tagged before you even think about relying on it for anything. APIs might break until then.
My fursona is a dhole, not a wolf.
I don't owe you anything. I don't owe your manager anything.
Besides, if anyone is bigoted against a predominantly LGBTQIA+ community, they're precisely the sort of person whose career I don't want to help.
In sum: