Fix Blowfish and Blowfish2 correctness issues and improve initialization safety

In Blowfish
- Fix incorrect F-function byte extraction (critical bug).
- Correct key-schedule handling by using `uint8_t` key bytes.
- Initialize local variables in `initialize()` to prevent UB.
- Improve decrypt loop and XOR usage for clarity and correctness.

In Blowfish2
- Zero-initialize P-array and S-boxes to guarantee deterministic state.
- Fix incorrect key size comment (448 bits, not 4224 bits).
- Improve F-function byte extraction clarity.
- Normalize round loop logic and use XOR-assignment.

Others
- Replace macro `N` with `constexpr N`.
- Add `noexcept` to internal operations.
- Add `initialize(const uint8_t*, size_t)` overload for binary keys.
- Clean up readability and internal consistency across both ciphers.

Signed-off-by: Avinal Kumar <avinal.xlvii@gmail.com>
This commit is contained in:
2025-12-04 21:11:16 +05:30
parent 4075aed708
commit f9ae6fddfd
4 changed files with 76 additions and 63 deletions
+12 -10
View File
@@ -4,32 +4,34 @@
// Original Blowfish Algorithm copyright:
// SPDX-FileCopyrightText: 1997 Paul Kocher
#include <algorithm>
#pragma once
#include <array>
#include <cstdint>
#include <string>
#define MAXKEYBYTES 56 // 448 bits max
#define N 16
static constexpr uint32_t N = 16;
#if !defined(BLOWFISH_BLOWFISH_H_)
#define BLOWFISH_BLOWFISH_H_
class Blowfish {
private:
std::array<uint32_t, N + 2> PArray;
std::array<std::array<uint32_t, 256>, 4> Sboxes;
uint32_t F(uint32_t x);
std::array<uint32_t, N + 2> PArray{};
std::array<std::array<uint32_t, 256>, 4> Sboxes{};
uint32_t F(uint32_t x) const noexcept;
public:
Blowfish() {}
Blowfish(std::string const &key);
Blowfish() = default;
explicit Blowfish(std::string const &key);
Blowfish(Blowfish const &) = delete;
void initialize(std::string const &key);
void initialize(const uint8_t *key, size_t keylen);
void initialize(const std::string &key);
void encrypt(uint32_t &xl, uint32_t &xr);
void decrypt(uint32_t &xl, uint32_t &xr);
void encrypt(uint32_t &xl, uint32_t &xr) noexcept;
void decrypt(uint32_t &xl, uint32_t &xr) noexcept;
~Blowfish();
};
#endif // BLOWFISH_BLOWFISH_H_
+14 -11
View File
@@ -4,32 +4,35 @@
// Original Blowfish 2 Algorithm copyright:
// SPDX-FileCopyrightText: 2005 Alexander Pukall
#include <algorithm>
#pragma once
#include <array>
#include <cstdint>
#include <string>
#define MAXKEYBYTES 56 // 4224 bits max
#define N 64
#define MAXKEYBYTES 56 // 448 bits max
#if !defined(BLOWFISH_BLOWFISH2_H_)
#define BLOWFISH_BLOWFISH2_H_
class Blowfish2 {
private:
std::array<uint64_t, N + 2> PArray;
std::array<std::array<uint64_t, 256>, 8> Sboxes;
uint64_t F(uint64_t x);
static constexpr uint64_t N = 64;
std::array<uint64_t, N + 2> PArray{};
std::array<std::array<uint64_t, 256>, 8> Sboxes{};
uint64_t F(uint64_t x) const noexcept;
public:
Blowfish2() {}
Blowfish2(std::string const &key);
Blowfish2(Blowfish2 const &) = delete;
Blowfish2() = default;
explicit Blowfish2(const std::string &key) { initialize(key); }
Blowfish2(const Blowfish2 &) = delete;
Blowfish2 &operator=(const Blowfish2 &) = delete;
void initialize(std::string const &key);
void initialize(const uint8_t *key, size_t keylen);
void encrypt(uint64_t &xl, uint64_t &xr);
void decrypt(uint64_t &xl, uint64_t &xr);
void encrypt(uint64_t &xl, uint64_t &xr) noexcept;
void decrypt(uint64_t &xl, uint64_t &xr) noexcept;
};
#endif // BLOWFISH_BLOWFISH2_H_