Skip to content

Version 1.1.0

Choose a tag to compare

@StormBytePP StormBytePP released this 13 Sep 19:41
· 19 commits to master since this release

[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::Exception names 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::Get on a missing entry now returns a dedicated exception instead of the generic Exception.
  • Header-only StormByte::Type::ByteInputRange overloads for block hashing, compression, encryption, signing and signature verification. They accept byte-convertible input ranges such as std::string_view, std::vector<uint8_t> and std::span, then delegate to the existing byte-span APIs without changing their ABI.

Fixed

  • Security hardening of KeyPair private-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::SecByteBlock copy 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 direct SecureWipe overload for std::vector<unsigned char> and wipe the original buffers (and std::string plaintext buffers) in place.
    • The shared CryptoPP::AutoSeededRandomPool used for salt/IV/key generation was a single process-wide instance accessed without synchronization. AutoSeededRandomPool is 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 it thread_local instead — confirmed race-free with ThreadSanitizer (fully-instrumented WITH_CRYPTOPP=BUNDLED build; the SYSTEM build 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 every KeyPair::Save/SavePublic/SavePrivate path) 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.
  • CMake: promote the system BZip2 imported target to global scope so WITH_BZIP2=SYSTEM resolves from the top-level directory.
  • Tests: silence -Werror=unused-variable under 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