libzupt is a library that provides encryption and decryption of files and binary data in memory using post-quantum hybrid cryptography ML-KEM-768 + X25519 in various languages.
The libzupt is an SDK designed to simplify the implementation of encryption and decryption for files and in-memory binary data, using a modern approach based on hybrid post-quantum cryptography ML-KEM-768 + X25519. Initially developed in C++ and Python, the library is built to be efficient, portable, and easy to integrate into applications that require advanced security. There are also plans to expand support to Java and Node.js, further increasing its adoption across different development ecosystems.
The main goal of libzupt is to enable current applications to be protected against emerging threats from quantum computing, even when running on classical computers. By combining traditional cryptographic techniques with quantum-resistant mechanisms, the library provides an additional layer of security that anticipates future scenarios where classical algorithms may be broken. This allows developers to build more resilient systems, ensuring long-term data confidentiality and integrity.
The name zupt is a tribute to the original project created by Cristian Cezar Moisés, acknowledging his fundamental contribution to the conceptual and technical foundation of this solution. This inspiration reinforces the library’s commitment to innovation, security, and the evolution of ideas that drive modern applied cryptography forward.
The library provides:
- Post-quantum hybrid encryption: Combines ML-KEM-768 (FIPS 203) with X25519 (RFC 7748)
- Fail-safe security: Secure as long as at least one of the algorithms (ML-KEM-768 or X25519) remains secure
- Modern C++ API: Object-oriented interface with exception handling
- File and memory support: Encryption for files and memory buffers
- Secure memory cleanup: Sensitive data is wiped after use
- CMake 3.10 or higher
- C++17 compiler (GCC 7+, Clang 5+, MSVC 2017+)
- System libraries:
libm
# Clone libzupt
git clone https://github.com/cabelo/libzupt.git
# Build
cd libzupt
mkdir build && cd build
cmake ..
make -j$(nproc)
# Install (optional)
sudo make installvcpkg install libzupt:x64-linux
# ou
vcpkg install libzupt:x64-windowshttps://software.opensuse.org/download.html?project=home%3Acabelo&package=libzupt
#include "zupt.hpp"
zupt::KeyGenerator keygen;
zupt::KeyPair keypair = keygen.generateKeyPair();
// Salvar chaves em arquivos
keygen.saveKeyPair(keypair, "private.key");
keygen.exportPublicKey("private.key", "public.key");#include "zupt.hpp"
// Carregar chave pública
zupt::KeyGenerator keygen;
std::vector<uint8_t> publicKey = keygen.loadPublicKey("public.key");
// Criptografar
zupt::Encryptor encryptor(publicKey);
const std::string plaintext = "Mensagem secreta";
auto [ciphertext, encHeader] = encryptor.encryptMemory(
reinterpret_cast<const uint8_t*>(plaintext.data()),
plaintext.size()
);#include "zupt.hpp"
// Carregar chave privada
zupt::KeyGenerator keygen;
zupt::KeyPair keypair = keygen.loadKeyPair("private.key");
// Descriptografar
zupt::Decryptor decryptor(keypair.secret_key);
std::vector<uint8_t> decrypted = decryptor.decryptMemory(ciphertext, encHeader);
std::string result(decrypted.begin(), decrypted.end());#include "zupt.hpp"
zupt::KeyGenerator keygen;
std::vector<uint8_t> publicKey = keygen.loadPublicKey("public.key");
zupt::Encryptor encryptor(publicKey);
auto [ciphertext, encHeader] = encryptor.encryptFile("input.txt");
// Salvar ciphertext e header
std::ofstream("output.zupt", std::ios::binary).write(
reinterpret_cast<const char*>(ciphertext.data()), ciphertext.size());
std::ofstream("output.zupt.header", std::ios::binary).write(
reinterpret_cast<const char*>(encHeader.data()), encHeader.size());Generates and manages hybrid key pairs.
class KeyGenerator {
public:
KeyPair generateKeyPair(); // Gera novo par de chaves
void saveKeyPair(const KeyPair&, const string&); // Salva chaves em arquivo
KeyPair loadKeyPair(const string&); // Carrega chaves de arquivo
void exportPublicKey(const string&, const string&); // Exporta chave pública
vector<uint8_t> loadPublicKey(const string&); // Carrega chave pública
};Performs encryption using a public key.
class Encryptor {
public:
explicit Encryptor(const vector<uint8_t>& publicKey);
pair<vector<uint8_t>, vector<uint8_t>> encryptMemory(const uint8_t*, size_t);
pair<vector<uint8_t>, vector<uint8_t>> encryptFile(const string&);
};Performs decryption using a private key.
class Decryptor {
public:
explicit Decryptor(const vector<uint8_t>& privateKey);
vector<uint8_t> decryptMemory(const uint8_t*, size_t, const vector<uint8_t>&);
vector<uint8_t> decryptFile(const string&, const vector<uint8_t>&);
SecureBuffer decryptMemorySecure(const SecureBuffer&, const vector<uint8_t>&);
};Buffer that automatically wipes its memory upon destruction.
class SecureBuffer {
public:
explicit SecureBuffer(size_t size);
SecureBuffer(const uint8_t* data, size_t size);
void zeroize() noexcept; // Limpa buffer manualmente
uint8_t* data() noexcept;
size_t size() const noexcept;
};std::vector<uint8_t> randomBytes(size_t size); // Generates safe random bytes.
std::vector<uint8_t> sha256(const uint8_t* data, size_t size); // SHA-256
std::vector<uint8_t> sha3_512(const uint8_t* data, size_t size); // SHA3-512
void secureWipe(void* ptr, size_t size); // Safely clears memory.
const char* getVersion(); // Library version
const char* getLibraryName(); // Library nameSee the complete examples in examples/:
# Generate keys
./zupt_example_file genkey private.key public.key
# Encrypt file
./zupt_example_file encrypt public.key input.txt output.zupt
# Decrypt file
./zupt_example_file decrypt private.key output.zupt output.txt output.zupt.header
# Run basic example
./zupt_example_basicThe keys are stored in the format .zupt-key:
[4B] "ZKEY" - Magic number
[1B] Version (0x01)
[1B] Flags (bit 0 = 1 if there is a private key)
[2B] Reserved
[1184B] ML-KEM-768 Public Key
[32B] X25519 Public Key
[2400B] ML-KEM-768 Secret Key (private key)
[32B] X25519 Secret Key (private key)
[8B] XXH64 Checksum
Total size:
- Public key: 1224 bytes
- Private key: 2504 bytes
- ML-KEM-768 (FIPS 203): Post-quantum key encapsulation algorithm
- X25519 (RFC 7748): (RFC 7748): Diffie-Hellman elliptic curve 25519
1. ML-KEM-768 Encaps: generates ciphertext (1088 bytes) and shared secret (32 bytes)
2. X25519 ECDH: generates shared secret (32 bytes) with recipient's public key
3. Hybrid IKM = ML-KEM-SS XOR X25519-SS (32 bytes)
4. Archive Key = SHA3-512(hybrid_ikm || ml_ct || eph_pk || "ZUPT-HYBRID-v1")
- enc_key = archive_key[0:32]
- mac_key = archive_key[32:64]
5. AES-256-CTR + HMAC-SHA256 for data encryption
| Component | Size |
|---|---|
| ML-KEM Public Key | 1184 bytes |
| ML-KEM Secret Key | 2400 bytes |
| X25519 Key | 32 bytes |
| ML-KEM Ciphertext | 1088 bytes |
| Encryption Header | 1137 bytes |
The library follows the security model of Signal PQXDH and iMessage PQ3:
Encryption is considered secure if at least one of the algorithms (ML-KEM-768 or X25519) remains resistant to attacks.
- Secure Memory Wipe: Keys and sensitive data are zeroed out after use
- Implicit Encapsulation: ML-KEM-768 implements implicit rejection to prevent timing attacks
- Constant Comparison: HMAC verification uses constant comparison to prevent timing attacks
- Cryptographic Randomness: Uses system CSPRNG (getrandom, /dev/urandom, RtlGenRandom)
- DO NOT use password modes (
-p) for post-quantum protection - use only--pqwith keys - Private keys must be stored in secure locations
- DO NOT reuse cryptographic headers with different keys
MIT License - see the LICENSE file for details.
Alessandro de Oliveira Faria (A.K.A.CABELO)
- Founder MultiCortex
- Intel Innvator
- openSUSE Ambassador and Member
- Chapter Leader OWASP SP
- Senior AI Researcher - Soberania Project
- Member of the Foton Institute
- Professor at FIA
- Member i2Ai and ABRIA
Contact: cabelo@opensuse.org