Skip to content

Latest commit

 

History

175 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

StormByte-Crypto

Platform C++26 CMake License: LGPL v3 CI Sponsor

This repository is StormByte Crypto: hash, compress, encrypt, sign and key agreement for the StormByte C++ suite.

It depends on StormByte Base and StormByte Buffer. Public headers live under StormByte/crypto/. Crypto++ stays in the private tree: installed headers never mention CryptoPP::. With a static Crypto++ link, consumers do not install it.

The suite is split on purpose. Base, Buffer, Config, Database, Logger, Multimedia, Network and System are other repositories. This one does not implement them.

What this module does

  • Hasher — SHA-256, SHA-512, SHA3-256, SHA3-512, BLAKE2b, BLAKE2s. One-shot hex digest or a Buffer::Consumer that yields the digest when the source closes.
  • Compressor — Zlib, Gzip, BZip2. Same block / stream contract as the rest of the module.
  • Symmetric crypter — AES CBC, AES-GCM, ChaCha20-Poly1305, Camellia, Serpent, Twofish. Keys from Password via PBKDF2-HMAC-SHA256 (600 000 iterations). Authenticated modes fail closed on a bad tag or a wrong password.
  • Asymmetric crypter — RSA OAEP-SHA and ECC ECIES. Strategy::Native is one PK transform per blob. Strategy::Hybrid wraps a random AES-256-GCM session key. Decrypt auto-detects the envelope.
  • Signer — DSA, RSA PKCS#1 v1.5 + SHA-256, ECDSA, Ed25519. Block and streaming sign / verify.
  • Secret — ECDH on secp256r1 / secp384r1 / secp521r1, and X25519. The shared secret is a Password, not a std::string.
  • KeyPair — Generate, persist PEM or DER, optional PKCS#8 (PBES2 + PBKDF2 + AES-256-CBC, OpenSSL-compatible). Public key travels as Base64 SPKI; private key stays in a Password.
  • Password / Vault — reference-counted wiped buffer; named store. Last owner zeros the bytes. Vault is movable, not copyable.
  • Buffer-first I/Ostd::span<const std::byte>Buffer::WriteOnly for blocks; Buffer::Consumer in / out for pipelines (Network, Multimedia).

The rest of the suite

Module Role API
Base Exceptions, Expected, serialization, strings, UUID, concepts /StormByte
Buffer FIFO, SharedFIFO, Ring, Producer/Consumer and multi-stage pipelines /StormByte-Buffer
Config Human-readable text and versioned binary documents (groups, lists, raw bytes) /StormByte-Config
Crypto This repository /StormByte-Crypto
Database One API over SQLite, PostgreSQL and MariaDB /StormByte-Database
Logger Stream logger with levels, headers, human-readable sizes and redaction (ThreadedLog) /StormByte-Logger
Multimedia Decode, encode and containers without raw FFmpeg types; codecs enabled only if present /StormByte-Multimedia
Network Framed packets, Client/Server, IPv4/IPv6 TCP and Buffer pipelines (compress/encrypt) /StormByte-Network
System Processes, pipes and environment variables across Linux, Windows and macOS /StormByte-System

Table of Contents

Installation

Needs a C++26 compiler, CMake 3.28 or newer, StormByte Base ≥ 1.1.0 and StormByte Buffer ≥ 1.1.0. Crypto++ and libbzip2 are build dependencies. Prefer a static Crypto++ link when you redistribute.

git clone --recursive https://github.com/StormBytePP/StormByte-Crypto.git
cd StormByte-Crypto
cmake -S . -B build
cmake --build build

Usage

Headers are #include <StormByte/crypto/….hxx>. Namespace root is StormByte::Crypto.

Nothing in the public tree includes Crypto++. Private headers are not installed.

Factories

auto hasher = Hasher::Create(Hasher::Type::SHA256);
auto zip    = Compressor::Create(Compressor::Type::Zlib, 6);
auto aes    = Crypter::Create(Crypter::Type::AES_GCM, password);
auto rsaKp  = KeyPair::RSA::Generate(2048);
auto rsa    = Crypter::Create(Crypter::Type::RSA, rsaKp);          // Hybrid by default
auto signer = Signer::Create(Signer::Type::ECDSA, ecdsaKp);
auto ecdh   = Secret::Create(Secret::Type::ECDH, ecdhKp);

Concrete types (Crypter::AES_GCM, KeyPair::X25519, Signer::ED25519, …) construct the same way without going through Create.

Password and Vault

Password is the only public container for secret bytes (passphrases, private key DER, shared secrets). Copies share the buffer; the last owner wipes it.

#include <StormByte/crypto/password.hxx>
#include <StormByte/crypto/vault.hxx>
#include <StormByte/crypto/crypter/generic.hxx>

using namespace StormByte::Crypto;

Password db("s3cret-from-env");
Vault vault;
vault.Store("database", db);
vault.Store("api", Password("token-xyz"));

if (auto p = vault.Get("database")) {
	auto aes = Crypter::Create(Crypter::Type::AES_GCM, *p);
}

if (*vault.Get("database") == db)
	; // constant-time compare of the bytes

vault.Remove("api");
vault.Clear();

Vault is movable, not copyable. A move leaves the source empty.

Hash and compress

#include <StormByte/crypto/hasher/generic.hxx>
#include <StormByte/crypto/compressor/generic.hxx>
#include <StormByte/buffer/fifo.hxx>
#include <StormByte/buffer/producer.hxx>

using namespace StormByte::Crypto;

auto sha = Hasher::Create(Hasher::Type::SHA256);
auto zip = Compressor::Create(Compressor::Type::Zlib, 6);

StormByte::Buffer::FIFO digest, packed;
const char msg[] = "payload";
const auto span = std::span<const std::byte>(
	reinterpret_cast<const std::byte*>(msg), sizeof(msg) - 1);

sha->Hash(span, digest);       // hex digest
zip->Compress(span, packed);

StormByte::Buffer::Producer prod;
prod.Write(msg);
prod.Close();
auto hashed = sha->Hash(prod.Consumer());   // Consumer → hex

Symmetric encrypt

Password → random salt + PBKDF2-HMAC-SHA256 → key. AES-GCM and ChaCha20-Poly1305 authenticate; a wrong password or a flipped bit returns false.

#include <StormByte/crypto/crypter/symmetric/aes_gcm.hxx>
#include <StormByte/crypto/password.hxx>
#include <StormByte/buffer/fifo.hxx>
#include <StormByte/buffer/producer.hxx>

using namespace StormByte::Crypto;

Password password("SecurePassword123!");
Crypter::AES_GCM gcm(password);

StormByte::Buffer::FIFO encrypted, decrypted;
const char msg[] = "authenticated payload";
const auto span = std::span<const std::byte>(
	reinterpret_cast<const std::byte*>(msg), sizeof(msg) - 1);

gcm.Encrypt(span, encrypted);
gcm.Decrypt(
	std::span<const std::byte>(encrypted.Data().data(), encrypted.Data().size()),
	decrypted);

StormByte::Buffer::Producer prod;
prod.Write(msg);
prod.Close();
auto cipher = gcm.Encrypt(prod.Consumer());
auto plain  = gcm.Decrypt(cipher);

CBC siblings (AES, Camellia, Serpent, Twofish) use the same Encrypt / Decrypt names.

Asymmetric encrypt

Native is one PK operation per blob (small messages). Hybrid is a random AES-256-GCM key wrapped with the recipient public key (anything that would be painful as raw RSA/ECIES). Decrypt reads the header and picks the path.

#include <StormByte/crypto/keypair/rsa.hxx>
#include <StormByte/crypto/crypter/asymmetric/rsa.hxx>
#include <StormByte/buffer/fifo.hxx>

using namespace StormByte::Crypto;

auto kp = KeyPair::RSA::Generate(2048);
Crypter::RSA hybrid(kp);                                 // Strategy::Hybrid
Crypter::RSA native(kp, Crypter::Asymmetric::Strategy::Native);

StormByte::Buffer::FIFO out;
hybrid.Encrypt(span, out);
hybrid.Decrypt(
	std::span<const std::byte>(out.Data().data(), out.Data().size()),
	out);

ECC (Crypter::ECC + KeyPair::ECC) is the same API.

KeyPair on disk

Format Meaning
PEM OpenSSL text (BEGIN / Base64). Default.
DER Raw ASN.1. Same family as many .cer / .crt blobs.
#include <StormByte/crypto/keypair/rsa.hxx>
#include <StormByte/crypto/password.hxx>

using namespace StormByte::Crypto;

auto kp = KeyPair::RSA::Generate(2048);
kp->Save("/tmp/keys", "app", KeyPair::StorageFormat::PEM);

Password wrap("disk-secret");
kp->Save("/tmp/keys", "app-enc", KeyPair::StorageFormat::PEM, wrap);

auto loaded = KeyPair::Load("/tmp/keys/app.pub.pem", "/tmp/keys/app.pem");
auto enc    = KeyPair::Load("/tmp/keys/app-enc.pub.pem", "/tmp/keys/app-enc.pem", wrap);

Wrong or missing wrap password fails closed (nullptr). Type comes from the OID (RSA, DSA, EC, Ed25519, X25519). Generate → Save → Load stays usable for encrypt, sign and share. X25519 also understands raw 32-byte library form.

Sign and verify

#include <StormByte/crypto/keypair/ed25519.hxx>
#include <StormByte/crypto/signer/generic.hxx>
#include <StormByte/buffer/fifo.hxx>

using namespace StormByte::Crypto;

auto kp = KeyPair::ED25519::Generate();
auto signer = Signer::Create(Signer::Type::ED25519, kp);

StormByte::Buffer::FIFO sig;
signer->Sign(span, sig);
bool ok = signer->Verify(span, std::string(
	reinterpret_cast<const char*>(sig.Data().data()), sig.Data().size()));

Streaming: signer->Sign(consumer) / signer->Verify(consumer, signature).

Key agreement

#include <StormByte/crypto/keypair/x25519.hxx>
#include <StormByte/crypto/secret/x25519.hxx>

using namespace StormByte::Crypto;

auto alice = KeyPair::X25519::Generate();
auto bob   = KeyPair::X25519::Generate();

auto secret = Secret::Create(Secret::Type::X25519, alice);
auto shared = secret->Share(bob->PublicKey());   // Expected<Password>

ECDH is the same with KeyPair::ECDH::Generate(256|384|521) and Secret::Type::ECDH.

Security notes

  • Decompression of untrusted input is not size-bounded. Like the underlying zlib/libbzip2, Compressor decompresses as much as the stream decodes to; a small malicious input can expand to a very large output ("decompression bomb"). If you decompress data from an untrusted source, bound it yourself: check the expected/maximum size before decompressing, or stop draining the streaming Consumer once your own limit is hit.
  • Private key files written by KeyPair::Save/SavePrivate are created owner-only (0600 on POSIX) and refuse to write through a pre-existing symlink at the destination path. Public key files are unaffected by either restriction.

Contributing

Issues only on this repository. Fork and open a pull request against master.

License

GNU Lesser General Public License version 3 or later. See LICENSE and https://www.gnu.org/licenses/lgpl-3.0.html.

About

Hash, compress, encrypt, sign and key agreement for the StormByte C++ suite. Crypto++ stays private.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages