Getting Started with the QuantaCore SDK
Write your first post-quantum cryptographic application in under 10 minutes. This guide walks through ML-KEM key exchange, ML-DSA digital signatures, and QRNG entropy generation using the QuantaCore SDK's software simulator — no QUAC 100 hardware required.
Prerequisites #
Before starting, ensure you have the QuantaCore SDK installed. If not, follow the Installation Guide.
| Requirement | Details |
|---|---|
| QuantaCore SDK | v1.0.0+ installed (libquac100 on Linux, or MSI/vcpkg on Windows) |
| C Compiler (for C examples) | GCC 7+, Clang 6+, or MSVC 2019+ (C11 standard) |
| Python (for Python examples) | Python 3.8+ with pip install quantacore-sdk |
| Rust (for Rust examples) | Rust 1.70+ with cargo add quantacore-sdk |
| Hardware | Optional — software simulator provides full API compatibility |
Verify your installation:
# Check SDK version
quac100-cli --version
# Expected: quac100-cli 1.0.0 (QuantaCore SDK)
# Test simulator mode
quac100-cli --simulator info
# Expected: Device: QUAC 100 Simulator, Status: OK
Simulator Mode #
The SDK ships with a full software simulator that implements all cryptographic algorithms with bit-exact correctness. The simulator uses CSPRNG instead of hardware QRNG and runs at approximately 10–100× slower than hardware, but produces identical outputs for the same inputs.
Enable the simulator in any of these ways:
/* C: Enable before quac_init() */
quac_set_simulator_mode(true);
quac_init(NULL);
# Python: Pass SIMULATOR flag
quantacore.initialize(flags=quantacore.InitFlags.SIMULATOR)
// Rust: Use the simulator feature
quantacore::initialize_with_flags(InitFlags::SIMULATOR)?;
# Environment variable (any language)
export QUAC_SIMULATOR=1
./your_application
| Feature | Hardware | Simulator |
|---|---|---|
| All algorithms (ML-KEM, ML-DSA, SLH-DSA) | ✅ | ✅ |
| Key storage (256 slots) | ✅ Hardware-isolated | ✅ In-memory |
| Async/batch operations | ✅ | ✅ |
| QRNG entropy | Hardware quantum sources | CSPRNG fallback |
| Performance | 1M+ ops/sec | ~10K–100K ops/sec |
| FIPS 140-3 mode | ✅ | ⌠|
First ML-KEM Key Exchange (C) #
ML-KEM (FIPS 203), formerly Kyber, is a lattice-based key encapsulation mechanism. This example generates a keypair, encapsulates a shared secret, and decapsulates it — the core operation used in post-quantum TLS handshakes.
#include <stdio.h>
#include <quac100.h>
int main(void) {
quac_result_t result;
quac_device_t device;
/* Initialize SDK in simulator mode */
quac_set_simulator_mode(true);
result = quac_init(NULL);
if (QUAC_FAILED(result)) {
fprintf(stderr, "Init failed: %s\n", quac_error_string(result));
return 1;
}
/* Open first available device (simulator) */
result = quac_open(0, &device);
if (QUAC_FAILED(result)) {
fprintf(stderr, "Open failed: %s\n", quac_error_string(result));
quac_shutdown();
return 1;
}
/* ── Alice: Generate ML-KEM-768 keypair ── */
uint8_t public_key[QUAC_KYBER768_PUBLIC_KEY_SIZE]; /* 1,184 bytes */
uint8_t secret_key[QUAC_KYBER768_SECRET_KEY_SIZE]; /* 2,400 bytes */
result = quac_kem_keygen(device, QUAC_ALGORITHM_KYBER768,
public_key, sizeof(public_key),
secret_key, sizeof(secret_key));
printf("KeyGen: %s (pk=%zu bytes)\n",
quac_error_string(result), sizeof(public_key));
/* ── Bob: Encapsulate shared secret using Alice's public key ── */
uint8_t ciphertext[QUAC_KYBER768_CIPHERTEXT_SIZE]; /* 1,088 bytes */
uint8_t bob_shared[QUAC_KYBER768_SHARED_SECRET_SIZE]; /* 32 bytes */
result = quac_kem_encaps(device, QUAC_ALGORITHM_KYBER768,
public_key, sizeof(public_key),
ciphertext, sizeof(ciphertext),
bob_shared, sizeof(bob_shared));
printf("Encaps: %s (ct=%zu bytes)\n",
quac_error_string(result), sizeof(ciphertext));
/* ── Alice: Decapsulate shared secret ── */
uint8_t alice_shared[QUAC_KYBER768_SHARED_SECRET_SIZE]; /* 32 bytes */
result = quac_kem_decaps(device, QUAC_ALGORITHM_KYBER768,
ciphertext, sizeof(ciphertext),
secret_key, sizeof(secret_key),
alice_shared, sizeof(alice_shared));
printf("Decaps: %s\n", quac_error_string(result));
/* Verify shared secrets match */
if (memcmp(alice_shared, bob_shared, 32) == 0)
printf("✅ Shared secrets match! Key exchange successful.\n");
else
printf("⌠Shared secrets differ — error.\n");
/* Print first 16 bytes of shared secret */
printf("Shared secret: ");
for (int i = 0; i < 16; i++) printf("%02x", alice_shared[i]);
printf("...\n");
quac_close(device);
quac_shutdown();
return 0;
}
Build and run:
gcc -o kem_example kem_example.c -lquac100
./kem_example
# Expected output:
KeyGen: Success (pk=1184 bytes)
Encaps: Success (ct=1088 bytes)
Decaps: Success
✅ Shared secrets match! Key exchange successful.
Shared secret: 7a4f2c8d1e3b9a05f6c2d8e4a1b7c3d9...
First ML-DSA Signature (C) #
ML-DSA (FIPS 204), formerly Dilithium, provides post-quantum digital signatures. ML-DSA-65 (NIST Level 3) is the recommended parameter set for most applications.
#include <quac100.h>
int main(void) {
quac_result_t result;
quac_device_t device;
quac_set_simulator_mode(true);
quac_init(NULL);
quac_open(0, &device);
/* Generate ML-DSA-65 signing keypair */
uint8_t pk[QUAC_DILITHIUM3_PUBLIC_KEY_SIZE]; /* 1,952 bytes */
uint8_t sk[QUAC_DILITHIUM3_SECRET_KEY_SIZE]; /* 4,000 bytes */
quac_sign_keygen(device, QUAC_ALGORITHM_DILITHIUM3,
pk, sizeof(pk), sk, sizeof(sk));
/* Sign a message */
const uint8_t message[] = "Post-quantum secure document";
uint8_t signature[QUAC_DILITHIUM3_SIGNATURE_SIZE]; /* 3,293 bytes */
size_t sig_len;
quac_sign(device, QUAC_ALGORITHM_DILITHIUM3,
sk, sizeof(sk),
message, sizeof(message),
signature, sizeof(signature), &sig_len);
printf("Signature: %zu bytes\n", sig_len);
/* Verify the signature */
result = quac_verify(device, QUAC_ALGORITHM_DILITHIUM3,
pk, sizeof(pk),
message, sizeof(message),
signature, sig_len);
printf("Verify: %s %s\n", quac_error_string(result),
QUAC_SUCCEEDED(result) ? "✅" : "âŒ");
quac_close(device);
quac_shutdown();
return 0;
}
First QRNG Generation (C) #
The QUAC 100 contains 8 avalanche noise sources producing hardware-grade quantum entropy at 500 Mbps conditioned. In simulator mode, a CSPRNG provides the random bytes.
/* Generate 256 bytes of quantum random data */
uint8_t entropy[256];
result = quac_random_bytes(device, entropy, sizeof(entropy));
if (QUAC_SUCCEEDED(result)) {
printf("Generated %zu random bytes\n", sizeof(entropy));
for (int i = 0; i < 32; i++) printf("%02x", entropy[i]);
printf("...\n");
}
/* Check available entropy */
uint32_t avail_bits;
quac_random_available(device, &avail_bits);
printf("Available entropy: %u bits\n", avail_bits);
Python Quick Start #
The Python bindings use ctypes for zero-overhead native calls. Install with pip install quantacore-sdk.
import quantacore
# Initialize in simulator mode
quantacore.initialize(flags=quantacore.InitFlags.SIMULATOR)
try:
# Open first device
device = quantacore.open_first_device()
# ── ML-KEM-768 Key Exchange ──
kem = device.kem()
keypair = kem.generate_keypair(quantacore.KemAlgorithm.ML_KEM_768)
print(f"Public key: {len(keypair.public_key)} bytes")
encap = kem.encapsulate(keypair.public_key)
bob_secret = encap.shared_secret
alice_secret = kem.decapsulate(keypair.secret_key, encap.ciphertext)
assert alice_secret == bob_secret
print(f"✅ Key exchange successful!")
print(f"Shared secret: {quantacore.to_hex(alice_secret[:16])}...")
# ── ML-DSA-65 Digital Signature ──
sign = device.sign()
sig_keypair = sign.generate_keypair(quantacore.SignAlgorithm.ML_DSA_65)
signature = sign.sign(sig_keypair.secret_key, b"Hello, post-quantum world!")
print(f"Signature: {len(signature)} bytes")
valid = sign.verify(sig_keypair.public_key, b"Hello, post-quantum world!", signature)
print(f"Verify: {'✅' if valid else 'âŒ'}")
# ── QRNG ──
random_bytes = device.random().bytes(64)
print(f"Random: {random_bytes.hex()[:32]}...")
device.close()
finally:
quantacore.cleanup()
Rust Quick Start #
The Rust crate provides safe, zero-cost abstractions with RAII resource management. Add to Cargo.toml: quantacore-sdk = "1.0"
use quantacore::{
initialize_with_flags, cleanup, open_first_device,
InitFlags, KemAlgorithm, SignAlgorithm
};
fn main() -> quantacore::Result<()> {
// Initialize in simulator mode
initialize_with_flags(InitFlags::SIMULATOR)?;
let device = open_first_device()?;
// ML-KEM-768 key exchange
let kem = device.kem();
let keypair = kem.generate_keypair(KemAlgorithm::MlKem768)?;
println!("Public key: {} bytes", keypair.public_key().len());
let (ciphertext, sender_secret) =
kem.encapsulate(keypair.public_key(), KemAlgorithm::MlKem768)?;
let receiver_secret =
kem.decapsulate(keypair.secret_key(), &ciphertext, KemAlgorithm::MlKem768)?;
assert_eq!(sender_secret, receiver_secret);
println!("✅ Key exchange successful!");
// ML-DSA-65 digital signature
let sign = device.sign();
let sig_kp = sign.generate_keypair(SignAlgorithm::MlDsa65)?;
let signature = sign.sign(sig_kp.secret_key(), b"Quantum-safe message")?;
let valid = sign.verify(sig_kp.public_key(), b"Quantum-safe message", &signature)?;
println!("Verify: {}", if valid { "✅" } else { "âŒ" });
// QRNG
let random_data = device.random().bytes(32)?;
println!("Random: {:02x?}", &random_data[..16]);
drop(device);
cleanup()?;
Ok(())
}
Go Quick Start #
Install: go get github.com/dyber-pqc/quantacore-go
package main
import (
"fmt"
quac "github.com/dyber-pqc/quantacore-go"
)
func main() {
quac.InitializeSimulator()
defer quac.Cleanup()
device, _ := quac.OpenFirstDevice()
defer device.Close()
// ML-KEM-768 key exchange
kem := device.KEM()
keypair, _ := kem.GenerateKeypair768()
fmt.Printf("Public key: %d bytes\n", len(keypair.PublicKey))
encap, _ := kem.Encapsulate(keypair.PublicKey)
shared, _ := kem.Decapsulate(keypair.SecretKey, encap.Ciphertext)
fmt.Printf("✅ Shared secret: %x...\n", shared[:16])
// QRNG
randomData, _ := device.Random().Bytes(64)
fmt.Printf("Random: %x...\n", randomData[:16])
}
Java Quick Start #
Maven: <artifactId>quantacore-sdk</artifactId> Gradle: implementation 'com.dyber:quantacore-sdk:1.0.0'
import com.dyber.quantacore.*;
public class QuickStart {
public static void main(String[] args) {
QuantaCore.initializeSimulator();
try (Device device = QuantaCore.openFirstDevice()) {
// ML-KEM-768
KEM kem = device.kem();
KeyPair keypair = kem.generateKeypair768();
System.out.printf("Public key: %d bytes%n",
keypair.getPublicKey().length);
EncapsulationResult encap = kem.encapsulate(keypair.getPublicKey());
byte[] shared = kem.decapsulate(
keypair.getSecretKey(), encap.getCiphertext());
System.out.println("✅ Key exchange successful!");
// ML-DSA-65
Sign sign = device.sign();
KeyPair sigKP = sign.generateKeypair65();
byte[] signature = sign.sign(
sigKP.getSecretKey(), "Hello PQC".getBytes());
boolean valid = sign.verify(
sigKP.getPublicKey(), "Hello PQC".getBytes(), signature);
System.out.println("Verify: " + (valid ? "✅" : "âŒ"));
}
QuantaCore.cleanup();
}
}
CLI Tools Quick Tour #
The SDK includes three command-line tools for testing and device management without writing code.
# Device info
quac100-cli --simulator info
# Generate ML-KEM-768 keypair and save to files
quac100-cli -s kem keygen -a ml-kem-768 --pk alice_pk.bin --sk alice_sk.bin
# Encapsulate (Bob)
quac100-cli -s kem encaps -a ml-kem-768 -p alice_pk.bin --ct ct.bin --ss bob_ss.bin
# Decapsulate (Alice)
quac100-cli -s kem decaps -a ml-kem-768 -s alice_sk.bin -c ct.bin --ss alice_ss.bin
# Sign and verify
quac100-cli -s sign keygen -a ml-dsa-65 --pk sig_pk.bin --sk sig_sk.bin
quac100-cli -s sign sign -a ml-dsa-65 -s sig_sk.bin -m document.pdf -o sig.bin
quac100-cli -s sign verify -a ml-dsa-65 -p sig_pk.bin -m document.pdf -g sig.bin
# Generate random bytes
quac100-cli -s random 64 --hex
# Run benchmarks
quac100-bench --simulator --algorithm ml-kem-768 --iterations 10000
# Run self-test diagnostics
quac100-diag --simulator --fips-test
Next Steps #
| Guide | What You'll Learn |
|---|---|
| Developer Guide | OpenSSL provider, PKCS#11, async/batch ops, multi-threading, performance tuning |
| API Reference | Complete function signatures, error codes, constants, and type definitions |
| Installation Guide | Driver setup, platform-specific builds, CMake options, container deployment |
| QUAC 100 Quick Start | Physical hardware installation, driver loading, and first hardware-accelerated operation |
| Troubleshooting | Build errors, linker issues, debug logging, and common integration problems |