A high-performance C++ implementation of the Cuid2 specification for generating collision-resistant, sortable unique identifiers using cryptographic primitives.
Table of Contents
- Collision-Resistant: Uses NIST FIPS-202 SHA3-512 hashing and cryptographically secure random number generation
- Sortable: Contains timestamp component for chronological ordering
- URL-Safe: Base-36 encoded (lowercase alphanumeric)
- Configurable Length: 4-32 characters (default: 24)
- Thread-Safe: Atomic counter with comprehensive concurrent access testing
- Cross-Platform: Windows (MSVC/MinGW), Linux, macOS, FreeBSD, OpenBSD, NetBSD
- Standards-Compliant: C++20, NIST FIPS-202, POSIX
- Well-Documented: Doxygen API docs + Unix manpages
- Security-Hardened: Stack protection, fortify source, control flow integrity
#include <cuid2/cuid2.hpp>
#include <iostream>
int main() {
// Generate default length (24 characters)
std::string id = cuid2::generate_cuid2();
std::cout << id << std::endl;
// Output: c9k2l3m4n5o6p7q8r9s0t1u2
// Generate custom length
std::string short_id = cuid2::generate_cuid2(16);
std::cout << short_id << std::endl;
// Output: a1b2c3d4e5f6g7h8
return 0;
}This project requires CMake 3.22+. Most modern Linux distributions ship with CMake 3.22 or newer by default.
cmake --versionsudo apt-get update
sudo apt-get install cmakeUbuntu 22.04 LTS and later include CMake 3.22+. For older versions, use the Kitware APT repository:
# Add Kitware APT repository
wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null
sudo apt-add-repository "deb https://apt.kitware.com/ubuntu/ $(lsb_release -cs) main"
sudo apt-get update
sudo apt-get install cmakesudo dnf install cmakesudo pacman -S cmakebrew install cmakepkg install cmakepkg_add cmake # OpenBSD
pkgin install cmake # NetBSDOption 1: Official Installer
- Download from https://cmake.org/download/
- Run the installer and add CMake to system PATH
Option 2: Chocolatey
choco install cmakeOption 3: Winget
winget install Kitware.CMakebrew install openssl@3 boost fmtsudo apt-get install libssl-dev libboost-all-dev libfmt-devsudo dnf install openssl-devel boost-devel fmt-develsudo pacman -S openssl boost fmtpkg install openssl boost-all libfmtNo system package installation required - vcpkg will build all dependencies automatically (see vcpkg Setup below).
The project uses vcpkg for dependency management with manifest mode (vcpkg.json). Dependencies are automatically installed during CMake configuration.
Installation:
# Clone vcpkg
git clone https://github.com/microsoft/vcpkg.git
cd vcpkg && ./bootstrap-vcpkg.sh # or bootstrap-vcpkg.bat on Windows
# Set environment variable
export VCPKG_ROOT=/path/to/vcpkg # Add to your shell profileHow it works:
- Non-Windows platforms (macOS, Linux, BSD): Uses overlay ports to redirect to system-installed libraries (see System Dependencies above)
- Windows: Automatically builds all dependencies via vcpkg's standard ports
Windows/Visual Studio users:
# Optional: Integrate vcpkg system-wide with Visual Studio
vcpkg integrate installThis makes vcpkg packages available to all Visual Studio projects without manually specifying the toolchain file.
The CMake presets expect VCPKG_ROOT to be set. Alternatively, specify the toolchain file manually:
cmake --preset macos-arm64-release \
-DCMAKE_TOOLCHAIN_FILE=/path/to/vcpkg/scripts/buildsystems/vcpkg.cmakeFor detailed information about the overlay ports system, see cmake/vcpkg/ports/README.md.
# Configure (adjust platform/architecture as needed)
cmake --preset macos-arm64-release
# Build
cmake --build --preset macos-arm64-release
# Install (optional)
sudo cmake --install build-macos-arm64-releaseAvailable presets for common platforms:
# List all available presets
cmake --list-presets
# Examples:
cmake --preset linux-x64-debug
cmake --preset windows-x64-release
cmake --preset freebsd-arm64-debugThe easiest way to install libcuid2 on Ubuntu is via the official PPA:
# Add the PPA
sudo add-apt-repository ppa:xaevik/libcuid2
sudo apt-get update
# Install packages
sudo apt-get install libcuid2-0 libcuid2-dev cuid2genAvailable packages:
libcuid2-0- Runtime shared librarylibcuid2-dev- Development headers and CMake configcuid2gen- Command-line tool
PPA homepage: https://launchpad.net/~xaevik/+archive/ubuntu/libcuid2
Note: Building DEB packages requires CMake 3.22+. See CMake Installation above if you don't have it installed.
Build DEB packages:
# Install build dependencies
sudo apt-get install debhelper-compat pkg-config \
libssl-dev libboost-dev libfmt-dev
# Build packages
dpkg-buildpackage -us -uc -b
# Install packages
sudo dpkg -i ../libcuid2-0_*.deb ../libcuid2-dev_*.deb ../cuid2gen_*.debNote: Building RPM packages requires CMake 3.22+ and a C++20 compiler. RHEL 8 requires GCC Toolset 12.
Build RPM packages:
# Fedora / RHEL 9+
sudo dnf install rpm-build rpmdevtools gcc-c++ cmake \
openssl-devel boost-devel fmt-devel
# RHEL 8 (requires EPEL and GCC Toolset)
sudo dnf install epel-release
sudo dnf install gcc-toolset-12-gcc-c++ cmake3 rpm-build rpmdevtools \
openssl3-devel boost-devel fmt-devel
# Set up RPM build environment
rpmdev-setuptree
# Copy spec file and create source tarball
cp rpm/libcuid2.spec ~/rpmbuild/SPECS/
git archive --format=tar.gz --prefix=libcuid2-1.0.1/ \
-o ~/rpmbuild/SOURCES/libcuid2-1.0.1.tar.gz HEAD
# Build packages
rpmbuild -ba ~/rpmbuild/SPECS/libcuid2.spec
# Install packages
sudo dnf install ~/rpmbuild/RPMS/*/libcuid2-1.0.1-1.*.rpm \
~/rpmbuild/RPMS/*/libcuid2-devel-1.0.1-1.*.rpm \
~/rpmbuild/RPMS/*/cuid2gen-1.0.1-1.*.rpmAvailable packages:
libcuid2- Runtime shared librarylibcuid2-devel- Development headers and CMake configcuid2gen- Command-line tool
For detailed RPM packaging documentation including mock builds and Copr cloud builds, see rpm/README.md.
# Generate default length (24)
cuid2gen
# Output: c9k2l3m4n5o6p7q8r9s0t1u2
# Generate custom length
cuid2gen -l 16
# Output: a1b2c3d4e5f6g7h8
# Use in shell scripts
USER_ID=$(cuid2gen)
echo "Created user: $USER_ID"#include <cuid2/cuid2.hpp>
// Generate default length (24)
std::string id = cuid2::generate_cuid2();
// Generate custom length (4-32)
std::string short_id = cuid2::generate_cuid2(16);#include <cuid2/cuid2.hpp>
#include <iostream>
try {
std::string id = cuid2::generate_cuid2(64); // Invalid length
} catch (const std::invalid_argument& e) {
std::cerr << "Error: " << e.what() << std::endl;
}#include <cuid2/cuid2.hpp>
#include <thread>
#include <vector>
void generate_ids(std::vector<std::string>& ids, size_t count) {
for (size_t i = 0; i < count; ++i) {
ids.push_back(cuid2::generate_cuid2());
}
}
int main() {
constexpr size_t num_threads = 10;
constexpr size_t ids_per_thread = 1000;
std::vector<std::thread> threads;
std::vector<std::vector<std::string>> results(num_threads);
for (size_t i = 0; i < num_threads; ++i) {
threads.emplace_back(generate_ids, std::ref(results[i]), ids_per_thread);
}
for (auto& thread : threads) {
thread.join();
}
// All IDs are guaranteed unique
return 0;
}find_package(cuid2 REQUIRED)
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE cuid2::cuid2)Cuid2 combines five components for uniqueness:
- Random Prefix (a-z) - Ensures valid identifiers
- Timestamp (Unix epoch) - Enables sortability
- Counter (atomic, thread-safe) - Prevents collisions in rapid generation
- Fingerprint (hostname + PID + environment) - System uniqueness
- Random Bytes (CSPRNG) - Cryptographic collision resistance
All components are hashed with NIST FIPS-202 SHA3-512 and encoded as base-36.
After installation, access documentation via man:
man cuid2gen # CLI tool reference
man 3 libcuid2 # API reference with examples
man 7 libcuid2 # Architecture and designManpages currently available in English. The project includes localization infrastructure ready for translations into 11 additional languages (German, Spanish, French, Italian, Japanese, Korean, Polish, Portuguese (European), Portuguese (Brazilian), Russian, Chinese (Simplified)).
Translation contributions are welcome! See man/LOCALIZATION.md for guidelines.
Full Doxygen documentation available in source:
- Headers:
include/cuid2/*.hpp - Implementation:
src/*.cpp
# Build with tests
cmake --preset macos-arm64-debug
cmake --build --preset macos-arm64-debug
# Run all tests
ctest --preset macos-arm64-debug
# Run specific test suites
./build-macos-arm64-debug/cuid2_test
./build-macos-arm64-debug/counter_test
./build-macos-arm64-debug/fingerprint_test37 test cases across 5 suites:
- cuid2_test (15 tests) - Generation, validation, uniqueness, thread safety
- counter_test (3 tests) - Thread safety, atomic increments
- fingerprint_test (6 tests) - Deterministic structure, singleton behavior
- utils_test (7 tests) - Base-36 encoding, prefix generation
- platform_test (6 tests) - Cross-platform abstractions
| Platform | Architectures |
|---|---|
| Linux | x86_64, ARM64 |
| macOS | x86_64, ARM64 (Apple Silicon) |
| Windows | x86_64, ARM64 (MSVC/MinGW) |
| FreeBSD | x86_64, ARM64 |
| OpenBSD | x86_64, ARM64 |
| NetBSD | x86_64, ARM64 |
- C++20 compiler (GCC 10+, Clang 11+, MSVC 2019+)
- CMake 3.22+
- OpenSSL 3.x (NIST FIPS-202 SHA3-512, CSPRNG)
- Boost (Endian, Multiprecision, Nowide, Test)
- fmt (Modern formatting library)
Single unified implementation (src/platform.cpp) with preprocessor directives:
- Windows:
GetComputerNameA(),GetCurrentProcessId(), UTF-16 conversion - POSIX (Linux/macOS/BSD):
gethostname(),getpid(),environ - CSPRNG: OpenSSL
RAND_bytes()(cross-platform)
- Hashing: NIST FIPS-202 SHA3-512 via OpenSSL EVP interface
- Random:
RAND_bytes()(FIPS 140-3 validated) - Encoding: Base-36 using Boost.Multiprecision arbitrary precision integers
- Counter:
std::atomic<int64_t>with.fetch_add() - Fingerprint: Singleton pattern (C++11+ thread-safe static initialization)
- Extensively tested with 10-20 concurrent threads generating up to 50,000 IDs
Contributions welcome! Please follow these guidelines:
- Fork the repository
- Install system dependencies (see Installation section)
- Create a feature branch
- Make changes following existing code style
- Run tests:
ctest --preset <platform>-<arch>-debug - Update documentation if adding features or changing behavior
- Submit a pull request with clear description of changes
- Follow C++20 best practices
- Maintain Doxygen documentation for all public APIs
- Ensure cross-platform compatibility (Windows, Linux, macOS, BSD)
- Add test coverage for new functionality
- Pass all existing tests and linters
- debian/README.md - Debian packaging documentation
- rpm/README.md - RPM packaging documentation
- man/README.md - Manual pages overview
- man/LOCALIZATION.md - Translation guidelines
- cmake/vcpkg/ports/README.md - vcpkg overlay ports information