Releases: StormByte-Suite/StormByte-Crypto
Release list
Version 2.0.0
[Summary]
StormByte Crypto is the cryptography module of the StormByte C++ suite.
It depends on StormByte Base ≥ 2.0.0, StormByte Buffer ≥ 2.0.0 and StormByte System ≥ 2.0.0. This repository is not Base, Buffer, Config, Database, Logger, Multimedia, Network or System.
Public headers under StormByte/crypto/ cover Hasher, Compressor, Crypter (symmetric and asymmetric), Signer, Secret, KeyPair, Password and Vault. Crypto++ never leaves the private tree.
If you landed here from a release link and have not read the tree:
- What this module is, how to build it, and short examples: README.md
- License: GNU Lesser General Public License version 3 or later, LICENSE
Changed
- Exception message constructors now accept
std::string_view; exception copy/move special members are defined out of line in their owning Crypto DLLs. - Port public text to Base's
StormByte::Safe::Stringand polymorphic ownership toStormByte::Safe::Clonable/Safe::Shared; Password accepts mutablestd::string&for wipeable caller-owned input. - Updated repository links to the StormByte-Suite organization and removed documentation for the retired standalone dependency.
- Shared vs static follows CMake
BUILD_SHARED_LIBS(declared in the project root, default ON). There is noSTORMBYTE_CRYPTO_SHAREDCMake option. When the library is shared, the compile definitionSTORMBYTE_CRYPTO_SHAREDis still set sovisibility.hcan distinguishdllexport/dllimport/ static. CI passes-DBUILD_SHARED_LIBS=ON. Vendored Crypto++ and BZip2 stay static BM components; their archives are closed onto consumers by the static sidecar. - Breaking: Port to StormByte Base 2.0.0, Buffer 2.0.0 and System 2.0.0. Public types follow Base 2.0:
Clonable+MakePointer/Sharedinstead ofstd::shared_ptr,StormByte::BinaryDatainstead of BufferDataType/ raw vectors at the public edge,StormByte::Sizefor abstract counts andStormByte::ByteSizefor octet lengths (Password::Size()isByteSize).std::sizeis gone from the public API. - Breaking: Exceptions no longer use
StormByte::Component.Crypto::ExceptionforwardsPath{"Crypto"}toStormByte::Exception. Per-office exceptions (Compressor::Exception,Crypter::Exception,Hasher::Exception,KeyPair::Exception,Secret::Exception,Signer::Exception) live in their own namespace and add only their own segment; Crypto concatenates before forwarding.what()isStormByte.CryptoorStormByte.Crypto.<Child>: message. - Breaking: Buffer 2.0 streaming contract. Block I/O is
std::span<const std::byte>intoBuffer::WriteOnly. Pipelines takeBuffer::Consumerand return a consumer;FIFO::Data()isBinaryData. - Breaking: Factories and keypair / signer / crypter / secret constructors take
KeyPair::Generic::PointerType(Safe::Shared), notstd::shared_ptr. Generate / Load return that pointer type.Safe::Clonable::MakePointeris used for public-only views. - Breaking: Public leaf classes are
final. Destructors of public types are declared in the header and defined out of line in the.cxx(= default) so the vtable and typeinfo stay on this side of the DLL. - Breaking: Non-secret public text is ingested as
std::string_viewand copied inside the library. That includes KeyPair leaf constructors,Secret::Share, Vault names (Store/Get/Contains/Remove),KeyPair::Generic::SavebaseName, andSigner::Verify/DoVerifysignatures.StormByte::Safe::Stringandstd::stringconvert tostring_view. Owned public text (PublicKey()) isconst StormByte::Safe::String&. Conversion tostd::stringis explicit (std::string{std::string_view{...}}). - Breaking:
Passwordno longer takesstd::stringby value. Ingest is a non-conststd::string&; the bytes are copied into wiped storage and the caller's object is overwritten and cleared. Literals useexplicit Password(const char*)and are not wiped. Raw bytes (const void*+ByteSize) are copied and not wiped.string_viewis rejected so a live password buffer cannot remain in the caller after construction, and so astd::stringis not moved across the DLL heap. - Breaking:
PasswordandVaultmove toStormByte::Crypto::Secure(StormByte/crypto/secure/{password,vault,exception}.{hxx,cxx}).Crypto::VaultExceptionis nowCrypto::Secure::VaultException(what()isStormByte.Crypto.Secure.Vault: message).Secure::ExceptionisStormByte.Crypto.Secure.ExpectedPasswordlives next to Vault. HeadersStormByte/crypto/password.hxxandStormByte/crypto/vault.hxxare gone. - Breaking: Private backend namespace
ImplementationisEngine(StormByte::Crypto::Engine). Public headers do not mention it. - Dual license on sources and
LICENSE: LGPL-3.0-or-later or commercial. Neither covers Crypto++, bundled libbzip2, or vendored StormByte trees underthirdparty/. - Tests rewritten to the suite format (section headers, snake_case functions, accumulating
main). Coverage of hasher, compressor, crypter, signer, secret, password, vault and keypair (save/load and OpenSSL fixtures) updated to the new pins. - Hybrid encrypt/decrypt tests compare plaintext with
std::string::operator==(ASSERT_TRUE), notASSERT_EQUAL. The harness C-string path false-failed prefix+4096 payloads on Ubuntu clang while the bytes already matched. - Doxygen (
ENABLE_DOC) resolves Buffer, Logger, System and Base headers viaINCLUDE_PATHand skipsthirdparty. CONTRIBUTING.mdandCODING_STYLE.mdaligned with Logger.
Notes
- Installed headers still do not include Crypto++. Crypto++ stays under
lib/privateandthirdparty. - Needs a C++26 compiler, StormByte Base ≥ 2.0.0, StormByte Buffer ≥ 2.0.0, StormByte System ≥ 2.0.0, and Crypto++ at build time.
Version 1.1.0
[Summary]
StormByte Crypto is the cryptography module of the StormByte C++ suite.
It depends on StormByte Base and StormByte Buffer. This repository is not Base, Buffer, Config, Database, Logger, Multimedia, Network or System.
Public headers under StormByte/crypto/ cover Hasher, Compressor, Crypter (symmetric and asymmetric), Signer, Secret, KeyPair, Password and Vault. Crypto++ never leaves the private tree.
If you landed here from a release link and have not read the tree:
- What this module is, how to build it, and short examples: README.md
- License: GNU Lesser General Public License version 3 or later, LICENSE
Changed
- Exception hierarchy ported to
StormByte::Component:Crypto::Exceptionnames itself"Crypto", and each per-component exception (CompressorException,CrypterException,HasherException,KeyPairException,SecretException,SignerException,VaultException) combines its own name with the parent's through its constructor instead of manual string concatenation. Removed the now-unneeded workaround for MSVC constructor-inheritance ambiguity. - Bumped the StormByte Buffer dependency to 1.1.0.
Added
VaultException:Vault::Geton a missing entry now returns a dedicated exception instead of the genericException.- Header-only
StormByte::Type::ByteInputRangeoverloads for block hashing, compression, encryption, signing and signature verification. They accept byte-convertible input ranges such asstd::string_view,std::vector<uint8_t>andstd::span, then delegate to the existing byte-span APIs without changing their ABI.
Fixed
- Security hardening of
KeyPairprivate-key handling, found and closed during a full pre-release audit:- Private-key material (PKCS#8 DER, PBES2 plaintext/ciphertext) was never actually wiped from memory. The wipe helper constructed a new
CryptoPP::SecByteBlockcopy from the buffer's pointer and zeroed that copy instead of the original —CryptoPP::SecBlock's(pointer, length)constructor always allocates and copies, it never wraps existing storage. Added a directSecureWipeoverload forstd::vector<unsigned char>and wipe the original buffers (andstd::stringplaintext buffers) in place. - The shared
CryptoPP::AutoSeededRandomPoolused for salt/IV/key generation was a single process-wide instance accessed without synchronization.AutoSeededRandomPoolis not safe for concurrent use, and the streaming encrypt/decrypt paths each spawn their own detached worker thread, so two concurrent streaming operations raced on the RNG's internal state. Made itthread_localinstead — confirmed race-free with ThreadSanitizer (fully-instrumentedWITH_CRYPTOPP=BUNDLEDbuild; theSYSTEMbuild previously produced ABI-boundary false positives). - Private key files (
KeyPair::Save/SavePrivate, encrypted or not, PEM or DER) were created with the OS-default file permissions, potentially group/world-readable depending on umask. They are now restricted to owner read/write (0600) right after writing. Public key files are unaffected. Best-effort on filesystems/platforms without POSIX permission bits. WriteFileBytes(used by everyKeyPair::Save/SavePublic/SavePrivatepath) refuses to write through a pre-existing symlink at the destination path, closing a local TOCTOU attack where a symlink planted at the target filename would redirect the write to an arbitrary file.
- Private-key material (PKCS#8 DER, PBES2 plaintext/ciphertext) was never actually wiped from memory. The wipe helper constructed a new
- CMake: promote the system BZip2 imported target to global scope so
WITH_BZIP2=SYSTEMresolves from the top-level directory. - Tests: silence
-Werror=unused-variableunder GCC in the AES/Camellia/Serpent/Twofish symmetric crypter tests, where the decrypt result is intentionally unchecked (CBC either fails padding or succeeds with garbage).
Notes
- Decompression of untrusted input is not size-bounded by this module (same as the underlying zlib/libbzip2); callers must bound it themselves. See README.md.
- Needs a C++26 compiler, StormByte Base ≥ 1.1.0, StormByte Buffer ≥ 1.1.0, and Crypto++ at build time.
Version 1.0.0
[Summary]
StormByte Crypto is the cryptography module of the StormByte C++ suite.
It depends on StormByte Base and StormByte Buffer. This repository is not Base, Buffer, Config, Database, Logger, Multimedia, Network or System.
Public headers under StormByte/crypto/ cover Hasher, Compressor, Crypter (symmetric and asymmetric), Signer, Secret, KeyPair, Password and Vault. Crypto++ never leaves the private tree.
If you landed here from a release link and have not read the tree:
- What this module is, how to build it, and short examples: README.md
- License: GNU Lesser General Public License version 3 or later, LICENSE
Initial public release of StormByte Crypto.
Added
- Hasher: SHA-256, SHA-512, SHA3-256, SHA3-512, BLAKE2b, BLAKE2s (block and stream, hex digest)
- Compressor: Zlib, Gzip, BZip2 with configurable level (block and stream)
- Symmetric crypter: AES CBC, AES-GCM, ChaCha20-Poly1305, Camellia, Serpent, Twofish
- Password-based keys via PBKDF2-HMAC-SHA256 (600 000 iterations)
- Asymmetric crypter: RSA OAEP-SHA, ECC ECIES
Strategy::NativeandStrategy::Hybrid(AES-256-GCM session key wrapped with the public key); decrypt auto-detects- Signer: DSA, RSA PKCS#1 v1.5 + SHA-256, ECDSA, Ed25519 (block and stream)
- Secret: ECDH (secp256r1 / secp384r1 / secp521r1) and X25519; result is a
Password - KeyPair generate: DSA, RSA, ECC, ECDH, ECDSA, Ed25519, X25519
- KeyPair Save / Load: PEM and DER; public Base64; private
Password; optional PKCS#8 (PBES2 + AES-256-CBC) Password— shared wiped secret; last owner zeros the bytesVault— namedPasswordstore; movable, not copyable- Factories:
Createon Hasher, Compressor, Crypter, Signer, Secret, KeyPair - StormByte Buffer pipelines (
Consumer/Producer) on every transform - Exception hierarchy with component prefixes
- Project version read from the
VERSIONfile - CMake 3.28 floor
Notes
- Installed headers do not include Crypto++. Static Crypto++ means consumers do not install it.
- Authenticated modes and wrapped private keys fail closed on a bad password or a bad tag.
- Needs a C++26 compiler, StormByte Base ≥ 1.0.0, StormByte Buffer ≥ 1.0.0, and Crypto++ at build time.