Getting Started with the QuantaCore SDK

QCSDK-GS-001 Rev 1.0 — January 2026

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.

Tip: All examples in this guide work identically on real QUAC 100 hardware. Simply remove the simulator flag and the SDK automatically uses the hardware accelerator.

Prerequisites #

Before starting, ensure you have the QuantaCore SDK installed. If not, follow the Installation Guide.

RequirementDetails
QuantaCore SDKv1.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
HardwareOptional — 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
FeatureHardwareSimulator
All algorithms (ML-KEM, ML-DSA, SLH-DSA)✅✅
Key storage (256 slots)✅ Hardware-isolated✅ In-memory
Async/batch operations✅✅
QRNG entropyHardware quantum sourcesCSPRNG fallback
Performance1M+ 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 #

GuideWhat You'll Learn
Developer GuideOpenSSL provider, PKCS#11, async/batch ops, multi-threading, performance tuning
API ReferenceComplete function signatures, error codes, constants, and type definitions
Installation GuideDriver setup, platform-specific builds, CMake options, container deployment
QUAC 100 Quick StartPhysical hardware installation, driver loading, and first hardware-accelerated operation
TroubleshootingBuild errors, linker issues, debug logging, and common integration problems