attacks but do not protect against other side-channel attacks such as power analysis or electromagnetic emanation. Additionally, the compiler and CPU may introduce timing variations through optimizations or speculative execution.
ddn.crypto.ct
Constant-Time Arithmetic Utilities for Side-Channel Resistance.
This module provides constant-time operations that do not leak information through timing side-channels. All operations execute in the same amount of time regardless of the values of their operands.
SecurityNote
These functions are designed to prevent timing
Copyright © 2025, Dejan Lekić
BSD-3-Clause
Types 1
Side-Channel Resistance Guidelines
This module provides building blocks for constant-time cryptographic implementations. To properly use these functions:
- Always use
ctEqualinstead of `==` for secret comparisons. - Use
ctSelectandctSwapinstead of conditional brancheswhen the condition depends on secret data.
- Ensure loop bounds do not depend on secret values.
- Be aware that BigInt operations like `%` and `*` may not be
fully constant-time; use Montgomery multiplication for modular arithmetic when timing is critical.
- Memory access patterns should not depend on secrets; use
constant-time table lookups or avoid tables entirely.
- Compiler optimizations may introduce timing variations.
- CPU features like branch prediction, caching, and speculative
execution can leak information.
- These functions protect against timing attacks but not against
other side-channel attacks like power analysis.
Functions 11
fn
bool ctEqual(const(ubyte)[] a, const(ubyte)[] b) pure nothrow @nogc @safeCompares two byte arrays in constant time.fn
T ctSelect(T)(uint condition, T a, T b) if (is(T == ubyte) || is(T == ushort) || is(T == uint) || is(T == ulong)) pure nothrow @nogc @safeSelects between two values in constant time.fn
void ctSwap(T)(uint doSwap, ref T a, ref T b) if (is(T == ubyte) || is(T == ushort) || is(T == uint) || is(T == ulong)) pure nothrow @nogc @safeSwaps two values conditionally in constant time.fn
void ctSwapBigInt(uint doSwap, ref BigInt a, ref BigInt b) pure nothrow @safeSwaps two BigInt values conditionally in constant time.fn
BigInt ctSelectBigInt(uint condition, BigInt a, BigInt b) pure nothrow @safeSelects between two BigInt values in constant time.fn
void ctSwapBytes(uint doSwap, ubyte[] a, ubyte[] b) pure nothrow @nogc @safeSwaps two byte arrays conditionally in constant time.fn
void ctCopyBytes(uint doCopy, ubyte[] dst, const(ubyte)[] src) pure nothrow @nogc @safeCopies `src` to `dst` conditionally in constant time.fn
uint ctLessThan(T)(T a, T b) if (is(T == ubyte) || is(T == ushort) || is(T == uint) || is(T == ulong)) pure nothrow @nogc @safeCompares two unsigned integers in constant time, returning 1 if a < b.fn
uint ctEquals(T)(T a, T b) if (is(T == ubyte) || is(T == ushort) || is(T == uint) || is(T == ulong)) pure nothrow @nogc @safeCompares two unsigned integers in constant time, returning 1 if a == b.fn
uint ctGetBit(const(ubyte)[] data, size_t bitIndex) pure nothrow @nogc @safeExtracts a bit from a byte array in constant time.fn
uint ctGetBitBigInt(BigInt scalar, size_t bitIndex) pure nothrow @safeExtracts a bit from a BigInt scalar in constant time.