From 6d89ab37754462928b28ad85714af316c83f43cb Mon Sep 17 00:00:00 2001 From: Aqua-sama Date: Sun, 8 Nov 2020 12:13:01 +0200 Subject: Add compile-time key length check --- blowfish.hpp | 57 ++++++++++++++++++++++++++++++++----------------------- blowfish_init.hpp | 14 +++++++++----- main.cpp | 2 +- 3 files changed, 43 insertions(+), 30 deletions(-) diff --git a/blowfish.hpp b/blowfish.hpp index 9a6e0fe..3637335 100644 --- a/blowfish.hpp +++ b/blowfish.hpp @@ -5,32 +5,39 @@ #include "blowfish_init.hpp" #include -class Blowfish { -public: - struct Block { - constexpr Block(uint64_t x) { - L = x >> 32; - R = x & 0xffffffff; - } - constexpr Block(uint32_t l, uint32_t r) : L(l), R(r) {} +namespace Blowfish { +template concept is_valid_key_length = (sz < KEYLEN); - constexpr operator uint64_t() const { - return (static_cast(L) << 32) + R; - } - uint32_t L; - uint32_t R; - }; +struct Block { + constexpr Block(uint64_t x) { + static_assert(sizeof(Block) == sizeof(uint64_t)); + L = x >> 32; + R = x & 0xffffffff; + } + constexpr Block(uint32_t l, uint32_t r) : L(l), R(r) { + static_assert(sizeof(Block) == sizeof(uint64_t)); + } - constexpr Blowfish(const uint8_t key[], size_t keylen) { - for (size_t i = 0; i < BOXES; ++i) { + constexpr operator uint64_t() const { + return (static_cast(L) << 32) + R; + } + uint32_t L; + uint32_t R; +}; + +template +requires is_valid_key_length class Context { +public: + constexpr Context(const std::array &key) { + for (std::size_t i = 0; i < BOXES; ++i) { std::copy(S_INIT[i].begin(), S_INIT[i].end(), S[i].begin()); } // - size_t k = 0; - for (size_t i = 0; i < SUBKEYS; ++i) { + std::size_t k = 0; + for (std::size_t i = 0; i < SUBKEYS; ++i) { uint32_t qk = 0; - for (size_t j = 0; j < 4; ++j) { + for (std::size_t j = 0; j < 4; ++j) { qk = (qk << 8) | key[k]; ++k; if (k >= keylen) { @@ -42,13 +49,13 @@ public: Block x(0, 0); - for (size_t i = 0; i < SUBKEYS; i += 2) { + for (std::size_t i = 0; i < SUBKEYS; i += 2) { x = encrypt(x); P[i] = x.L; P[i + 1] = x.R; } - for (size_t i = 0; i < BOXES; ++i) { - for (size_t j = 0; j < ENTRIES; j += 2) { + for (std::size_t i = 0; i < BOXES; ++i) { + for (std::size_t j = 0; j < ENTRIES; j += 2) { x = encrypt(x); S[i][j] = x.L; S[i][j + 1] = x.R; @@ -58,7 +65,7 @@ public: constexpr Block encrypt(const Block &x) const { Block y(x); - for (size_t i = 0; i < ROUNDS; ++i) { + for (std::size_t i = 0; i < ROUNDS; ++i) { y.L = y.L ^ P[i]; y.R = F(y.L) ^ y.R; std::swap(y.L, y.R); @@ -72,7 +79,7 @@ public: constexpr Block decrypt(const Block &x) const { Block y(x); - for (size_t i = ROUNDS + 1; i > 1; --i) { + for (std::size_t i = ROUNDS + 1; i > 1; --i) { y.L = y.L ^ P[i]; y.R = F(y.L) ^ y.R; std::swap(y.L, y.R); @@ -99,3 +106,5 @@ private: std::array P; std::array, BOXES> S; }; + +} // namespace Blowfish diff --git a/blowfish_init.hpp b/blowfish_init.hpp index 9d2366d..2d7bf6c 100644 --- a/blowfish_init.hpp +++ b/blowfish_init.hpp @@ -1,12 +1,14 @@ #pragma once #include -#include #include -constexpr size_t ROUNDS = 16; -constexpr size_t SUBKEYS = ROUNDS + 2; -constexpr size_t BOXES = 4; -constexpr size_t ENTRIES = 256; +namespace Blowfish { + +constexpr std::size_t KEYLEN = 448 / sizeof(uint8_t); +constexpr std::size_t ROUNDS = 16; +constexpr std::size_t SUBKEYS = ROUNDS + 2; +constexpr std::size_t BOXES = 4; +constexpr std::size_t ENTRIES = 256; constexpr std::array P_INIT{ 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, @@ -191,3 +193,5 @@ constexpr std::array, BOXES> S_INIT{ 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6}}; + +} // namespace Blowfish diff --git a/main.cpp b/main.cpp index 263438d..2a46d8c 100644 --- a/main.cpp +++ b/main.cpp @@ -12,7 +12,7 @@ constexpr uint64_t k(const uint8_t key[8]) { template struct wrapper { constexpr void operator()() const { - constexpr Blowfish b(variable_key[i], 8); + constexpr Blowfish::Context<8> b(std::to_array(variable_key[i])); constexpr Blowfish::Block x(plaintext_l[i], plaintext_r[i]); constexpr auto y = b.encrypt(x); -- cgit v1.2.1