Getting Started
This guide walks you through installing the QuantaCore SDK, discovering QUAC 100 devices, and performing your first post-quantum cryptographic operation — all in under five minutes. Whether you have physical hardware or are using the software simulator, the API experience is identical.
Overview #
The Dyber Cryptographic API is the software interface to the QUAC 100 Post-Quantum Cryptographic Accelerator. It provides a layered architecture with multiple integration points depending on your deployment requirements:
| API Layer | Library | Latency Overhead | Best For |
|---|---|---|---|
| Native C API | libquac100 | <100 ns | Maximum performance, low-level control |
| Language Bindings | quac100-{lang} | 100–500 ns | Application development in Rust, Python, Java, Go, C#, Node.js |
| OpenSSL Provider | quac100-ossl.so | 1–5 μs | Transparent TLS/SSL acceleration, zero code changes |
| PKCS#11 Module | libquac100_pkcs11.so | 2–10 μs | HSM replacement, certificate authority, token operations |
| Windows CNG | quac100cng.dll | 2–10 μs | Native Windows cryptographic infrastructure |
All layers ultimately communicate with the same hardware through the kernel driver (quac100.ko on Linux, quac100.sys on Windows). The native C API provides the foundation that all other layers build upon.
Prerequisites #
Hardware (optional): QUAC 100 PCIe accelerator card installed in a PCIe Gen4/Gen5 x16 slot. The software simulator provides full API compatibility for development without hardware.
Operating System: Linux (Ubuntu 22.04+, RHEL 8+, SLES 15+) or Windows (Server 2019+, Windows 10/11). Linux kernel 5.15+ recommended for optimal DMA performance.
Compiler Toolchain: GCC 11+ or Clang 14+ on Linux, MSVC 2019+ on Windows. CMake 3.16+ for the build system. Language-specific toolchains as needed (Rust 1.70+, Python 3.8+, JDK 11+, Go 1.20+).
Driver: QUAC 100 kernel driver must be loaded before the SDK can communicate with hardware. The driver is included in the SDK package and installs via standard package managers.
# Check if driver is loaded (Linux)
$ lsmod | grep quac100
quac100 524288 0
# Check device presence
$ lspci | grep Dyber
b3:00.0 Encryption controller: Dyber Inc. QUAC 100 PQC Accelerator (rev 01)
Installation #
Linux (Debian/Ubuntu):
# Add Dyber repository
$ curl -fsSL https://packages.dyber.com/gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/dyber.gpg
$ echo "deb [signed-by=/usr/share/keyrings/dyber.gpg] https://packages.dyber.com/apt stable main" | \
sudo tee /etc/apt/sources.list.d/dyber.list
# Install SDK and driver
$ sudo apt update
$ sudo apt install quac100-sdk quac100-dkms
# Load driver
$ sudo modprobe quac100
# Verify installation
$ quac100-info
QuantaCore SDK v1.0.0
Devices found: 1
Device 0: QUAC 100 [FW v2.1.0] Serial: QC-2025-00142
Linux (RHEL/Rocky):
$ sudo dnf config-manager --add-repo https://packages.dyber.com/rpm/dyber.repo
$ sudo dnf install quac100-sdk quac100-kmod
Windows:
:: Download and run the MSI installer
> QuantaCoreSDK-1.0.0-x64.msi
:: Or via WinGet
> winget install Dyber.QuantaCoreSDK
From Source:
$ git clone https://github.com/dyber-inc/quantacore-sdk.git
$ cd quantacore-sdk
$ mkdir build && cd build
$ cmake .. -DBUILD_SIMULATOR=ON -DBUILD_TESTS=ON
$ make -j$(nproc)
$ sudo make install
Device Discovery #
The SDK automatically discovers all QUAC 100 devices connected to the system. Each physical card appears as one device, with SR-IOV virtual functions appearing as additional devices when configured for multi-tenant operation.
#include <quac100.h>
int main(void) {
// Initialize the SDK
quac_result_t rc = quac_init();
if (rc != QUAC_SUCCESS) {
fprintf(stderr, "SDK init failed: %s\n", quac_strerror(rc));
return 1;
}
// Discover devices
uint32_t count = quac_device_count();
printf("Found %u QUAC 100 device(s)\n", count);
for (uint32_t i = 0; i < count; i++) {
quac_device_t dev;
rc = quac_open(i, &dev);
if (rc == QUAC_SUCCESS) {
quac_device_info_t info;
quac_get_info(dev, &info);
printf(" Device %u: FW %s, Serial %s\n",
i, info.firmware_version, info.serial_number);
quac_close(dev);
}
}
quac_shutdown();
return 0;
}
The quac_init() function must be called once before any other SDK function. It initializes internal data structures, scans for hardware, and establishes driver communication channels. Call quac_shutdown() when finished to release all resources.
First Cryptographic Operation #
The simplest meaningful operation is an ML-KEM (Kyber) key exchange. This demonstrates the full lifecycle: key generation, encapsulation (sender side), and decapsulation (receiver side).
quac_device_t dev;
quac_open(0, &dev);
// Generate ML-KEM-768 key pair
quac_kem_keypair_t keypair;
quac_kem_keygen(dev, QUAC_ALG_KYBER_768, &keypair);
// Sender: encapsulate a shared secret using the public key
quac_kem_ciphertext_t ct;
quac_kem_shared_secret_t sender_ss;
quac_kem_encapsulate(dev, &keypair.public_key, &ct, &sender_ss);
// Receiver: decapsulate using the secret key
quac_kem_shared_secret_t receiver_ss;
quac_kem_decapsulate(dev, &keypair.secret_key, &ct, &receiver_ss);
// Both sides now share the same 32-byte secret
assert(memcmp(sender_ss.data, receiver_ss.data, 32) == 0);
// Secure cleanup
quac_zeroize(&keypair, sizeof(keypair));
quac_close(dev);
On QUAC 100 hardware, this entire sequence completes in under 5 microseconds. The software simulator produces identical results but with higher latency (~1ms).
Software Simulator #
The QuantaCore SDK ships with a full-featured software simulator (libquac100_sim) that implements every API function using reference C implementations of ML-KEM, ML-DSA, and SLH-DSA. The simulator enables development and testing without QUAC 100 hardware.
// Enable simulator mode before quac_init()
quac_set_simulator_mode(true);
quac_init();
// All API calls now work against the software simulator
// Cryptographic results are identical to hardware
quac_device_t dev;
quac_open(0, &dev); // Opens a simulated device
// Check if running on hardware or simulator
bool is_hw = quac_is_hardware();
printf("Running on: %s\n", is_hw ? "QUAC 100 hardware" : "Software simulator");
// Optionally configure simulator timing behavior
quac_simulator_config(10, 50000); // 10μs latency, 50K ops/sec
QUAC_SIMULATOR=1 in your environment to force simulator mode without code changes. This is useful for CI/CD pipelines where hardware may not be available.
The simulator is API-compatible in every respect: the same function signatures, the same error codes, the same cryptographic output for the same inputs. The only difference is performance — hardware delivers sub-microsecond operations while the simulator operates at software speeds.
Project Setup #
CMake (C/C++):
cmake_minimum_required(VERSION 3.16)
project(my_pqc_app LANGUAGES C)
find_package(Quac100 REQUIRED)
add_executable(my_app src/main.c)
target_link_libraries(my_app PRIVATE Quac100::quac100)
pkg-config:
$ gcc -o my_app main.c $(pkg-config --cflags --libs quac100)
Rust (Cargo.toml):
[dependencies]
quac100 = "1.0"
Python:
$ pip install quac100
Java (Maven pom.xml):
<dependency>
<groupId>com.dyber</groupId>
<artifactId>quac100</artifactId>
<version>1.0.0</version>
</dependency>
Go:
$ go get github.com/dyber-inc/quac100-go@v1.0.0
Error Handling #
Every SDK function returns a quac_result_t status code. The SDK defines a structured error hierarchy that distinguishes between device errors, cryptographic failures, resource exhaustion, and parameter validation issues.
| Error Code | Value | Description |
|---|---|---|
QUAC_SUCCESS | 0x0000 | Operation completed successfully |
QUAC_ERR_NOT_INITIALIZED | 0x0001 | SDK not initialized — call quac_init() first |
QUAC_ERR_DEVICE_NOT_FOUND | 0x0010 | No device at specified index |
QUAC_ERR_DEVICE_BUSY | 0x0011 | Device is processing another request |
QUAC_ERR_INVALID_PARAM | 0x0020 | Invalid parameter passed to function |
QUAC_ERR_BUFFER_TOO_SMALL | 0x0021 | Output buffer insufficient |
QUAC_ERR_CRYPTO_FAILED | 0x0030 | Cryptographic operation failed validation |
QUAC_ERR_KEY_INVALID | 0x0031 | Key material is malformed or expired |
QUAC_ERR_HW_FAULT | 0x0040 | Hardware fault detected — device needs reset |
QUAC_ERR_SELFTEST_FAILED | 0x0041 | POST or continuous self-test failure |
quac_result_t rc = quac_kem_keygen(dev, QUAC_ALG_KYBER_768, &keypair);
if (rc != QUAC_SUCCESS) {
fprintf(stderr, "Key generation failed: %s (0x%04X)\n",
quac_strerror(rc), rc);
// quac_strerror() returns a human-readable error string
// Thread-safe, returns pointer to static string
}
Complete Example: hello_quac #
The hello_quac example demonstrates initialization, device discovery, a complete ML-KEM key exchange, an ML-DSA signature cycle, QRNG random byte generation, and cleanup. It compiles and runs identically on hardware and simulator.
#include <quac100.h>
#include <stdio.h>
#include <string.h>
int main(void) {
// Initialize (auto-detects hardware vs simulator)
quac_init();
quac_device_t dev;
quac_open(0, &dev);
quac_device_info_t info;
quac_get_info(dev, &info);
printf("Device: %s (FW %s)\n", info.product_name, info.firmware_version);
printf("Mode: %s\n\n", quac_is_hardware() ? "Hardware" : "Simulator");
// ── ML-KEM-768 Key Exchange ──
quac_kem_keypair_t kem_kp;
quac_kem_keygen(dev, QUAC_ALG_KYBER_768, &kem_kp);
quac_kem_ciphertext_t ct;
quac_kem_shared_secret_t ss_enc, ss_dec;
quac_kem_encapsulate(dev, &kem_kp.public_key, &ct, &ss_enc);
quac_kem_decapsulate(dev, &kem_kp.secret_key, &ct, &ss_dec);
printf("ML-KEM-768: %s\n",
memcmp(ss_enc.data, ss_dec.data, 32) == 0 ? "PASS" : "FAIL");
// ── ML-DSA-65 Digital Signature ──
quac_sign_keypair_t sig_kp;
quac_sign_keygen(dev, QUAC_ALG_DILITHIUM_3, &sig_kp);
uint8_t message[] = "Hello, post-quantum world!";
quac_signature_t sig;
quac_sign(dev, &sig_kp.secret_key, message, sizeof(message), &sig);
bool valid;
quac_verify(dev, &sig_kp.public_key, message, sizeof(message), &sig, &valid);
printf("ML-DSA-65: %s\n", valid ? "PASS" : "FAIL");
// ── QRNG Random Bytes ──
uint8_t random[32];
quac_random_bytes(dev, random, 32);
printf("QRNG: ");
for (int i = 0; i < 8; i++) printf("%02x", random[i]);
printf("...\n");
// Cleanup
quac_zeroize(&kem_kp, sizeof(kem_kp));
quac_zeroize(&sig_kp, sizeof(sig_kp));
quac_close(dev);
quac_shutdown();
printf("\nAll operations completed successfully.\n");
return 0;
}
Build and run:
$ gcc -o hello_quac hello_quac.c -lquac100
$ ./hello_quac
Device: QUAC 100 PQC Accelerator (FW 2.1.0)
Mode: Hardware
ML-KEM-768: PASS
ML-DSA-65: PASS
QRNG: a3f7c21b9e4d06f8...
All operations completed successfully.
Next Steps #
With the SDK installed and your first cryptographic operations running, you're ready to explore deeper integration paths. The Universal API page covers the algorithm-agnostic abstraction layer that enables crypto-agility across all supported algorithms. For drop-in acceleration of existing applications, see the OpenSSL Provider or PKCS#11 Interface documentation. If you're developing in a language other than C, the Language Bindings page provides idiomatic APIs for Rust, Python, Java, Go, C#, and Node.js.
examples/ directory. Each example includes a Makefile and README with detailed build and usage instructions. For technical support, contact support@dyber.com.
Was this page helpful? Send feedback