From 2a3185406b8020c747fbe32c2735eedc7022da06 Mon Sep 17 00:00:00 2001 From: hashlag Date: Sun, 8 Feb 2026 23:05:57 +0300 Subject: [PATCH 1/7] Add PKCS#7 padding implementation. --- Chaos/Padding/PadPkcs7.hpp | 37 ++++++++ ChaosTests/CMakeLists.txt | 1 + ChaosTests/Padding/PadPkcs7Tests.cpp | 121 +++++++++++++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 Chaos/Padding/PadPkcs7.hpp create mode 100644 ChaosTests/Padding/PadPkcs7Tests.cpp diff --git a/Chaos/Padding/PadPkcs7.hpp b/Chaos/Padding/PadPkcs7.hpp new file mode 100644 index 0000000..4d8548d --- /dev/null +++ b/Chaos/Padding/PadPkcs7.hpp @@ -0,0 +1,37 @@ +#ifndef CHAOS_PADDING_PADPKCS7_HPP +#define CHAOS_PADDING_PADPKCS7_HPP + +#include +#include +#include + +#include "Service/ChaosException.hpp" + +namespace Chaos::Padding +{ + +class PadPkcs7 +{ +public: + template + static void Pad(OutputIt begin, OutputIt end) + { + auto dist = std::distance(begin, end); + + if (dist >= 0 && dist <= std::numeric_limits::max()) + { + for (OutputIt it = begin; it != end; ++it) + { + *it = static_cast(dist); + } + } + else + { + throw Service::ChaosException("PadPkcs7::Pad(): invalid range"); + } + } +}; + +} // namespace Chaos::Padding + +#endif // CHAOS_PADDING_PADPKCS7_HPP diff --git a/ChaosTests/CMakeLists.txt b/ChaosTests/CMakeLists.txt index 1aa05df..3413aae 100644 --- a/ChaosTests/CMakeLists.txt +++ b/ChaosTests/CMakeLists.txt @@ -18,6 +18,7 @@ set(ChaosTests_SOURCE Hash/Md4HasherTests.cpp Cipher/Arc4GenTests.cpp Cipher/Arc4CryptTests.cpp Cipher/DesCryptTests.cpp + Padding/PadPkcs7Tests.cpp Service/SeArrayTests.cpp Service/ChaosExceptionTests.cpp) diff --git a/ChaosTests/Padding/PadPkcs7Tests.cpp b/ChaosTests/Padding/PadPkcs7Tests.cpp new file mode 100644 index 0000000..b511460 --- /dev/null +++ b/ChaosTests/Padding/PadPkcs7Tests.cpp @@ -0,0 +1,121 @@ +#include +#include +#include +#include + +#include "Padding/PadPkcs7.hpp" +#include "Service/ChaosException.hpp" + +using namespace Chaos::Padding; + +TEST(PadPkcs7Tests, PadTest) +{ + { + std::array fact = {}; + std::array expected = { 0x01 }; + + PadPkcs7::Pad(fact.begin(), fact.end()); + ASSERT_EQ(expected, fact); + } + + { + std::array fact = {}; + std::array expected = + { + 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07 + }; + + PadPkcs7::Pad(fact.begin(), fact.end()); + ASSERT_EQ(expected, fact); + } + + { + std::array fact = {}; + std::array expected = + { + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a + }; + + PadPkcs7::Pad(fact.begin(), fact.end()); + ASSERT_EQ(expected, fact); + } + + for (int i = 0; i < 256; ++i) + { + std::vector fact(i, 0x00); + + PadPkcs7::Pad(fact.begin(), fact.end()); + ASSERT_EQ(std::vector(i, i), fact); + } +} + +TEST(PadPkcs7Tests, PadInvalidRangeTest) +{ + { + std::array out = {}; + + ASSERT_THROW(PadPkcs7::Pad(out.begin(), out.end()), Chaos::Service::ChaosException); + } + + { + std::array out = {}; + + ASSERT_THROW(PadPkcs7::Pad(out.begin(), out.end()), Chaos::Service::ChaosException); + } + + { + std::array out = {}; + + ASSERT_THROW(PadPkcs7::Pad(out.end(), out.begin()), Chaos::Service::ChaosException); + } +} + +TEST(PadPkcs7Tests, PadOutIteratorUsageTest) +{ + { + std::array fact = {}; + std::array expected = + { + 0x00, 0x00, 0x00, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x00, 0x00, 0x00 + }; + + PadPkcs7::Pad(fact.begin() + 3, fact.end() - 3); + ASSERT_EQ(expected, fact); + } + + { + std::array fact = {}; + std::array expected = + { + 0x00, 0x00, 0x00, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x00, 0x00, 0x00 + }; + + PadPkcs7::Pad(fact.begin() + 3, fact.end() - 3); + ASSERT_EQ(expected, fact); + } + + { + std::array fact = + { + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb + }; + std::array expected = + { + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb + }; + + PadPkcs7::Pad(fact.begin() + 5, fact.begin() + 5); + ASSERT_EQ(expected, fact); + } +} From 5baede0a1d1698f20c094b1b650d23ced41a49d3 Mon Sep 17 00:00:00 2001 From: hashlag Date: Sun, 8 Feb 2026 23:31:24 +0300 Subject: [PATCH 2/7] Rename PadPkcs7 --> PadderPkcs7. --- .../Padding/{PadPkcs7.hpp => PadderPkcs7.hpp} | 8 +++---- ChaosTests/CMakeLists.txt | 2 +- ...PadPkcs7Tests.cpp => PadderPkcs7Tests.cpp} | 22 +++++++++---------- 3 files changed, 16 insertions(+), 16 deletions(-) rename Chaos/Padding/{PadPkcs7.hpp => PadderPkcs7.hpp} (82%) rename ChaosTests/Padding/{PadPkcs7Tests.cpp => PadderPkcs7Tests.cpp} (76%) diff --git a/Chaos/Padding/PadPkcs7.hpp b/Chaos/Padding/PadderPkcs7.hpp similarity index 82% rename from Chaos/Padding/PadPkcs7.hpp rename to Chaos/Padding/PadderPkcs7.hpp index 4d8548d..e35d891 100644 --- a/Chaos/Padding/PadPkcs7.hpp +++ b/Chaos/Padding/PadderPkcs7.hpp @@ -1,5 +1,5 @@ -#ifndef CHAOS_PADDING_PADPKCS7_HPP -#define CHAOS_PADDING_PADPKCS7_HPP +#ifndef CHAOS_PADDING_PADDERPKCS7_HPP +#define CHAOS_PADDING_PADDERPKCS7_HPP #include #include @@ -10,7 +10,7 @@ namespace Chaos::Padding { -class PadPkcs7 +class PadderPkcs7 { public: template @@ -34,4 +34,4 @@ public: } // namespace Chaos::Padding -#endif // CHAOS_PADDING_PADPKCS7_HPP +#endif // CHAOS_PADDING_PADDERPKCS7_HPP diff --git a/ChaosTests/CMakeLists.txt b/ChaosTests/CMakeLists.txt index 3413aae..796ce51 100644 --- a/ChaosTests/CMakeLists.txt +++ b/ChaosTests/CMakeLists.txt @@ -18,7 +18,7 @@ set(ChaosTests_SOURCE Hash/Md4HasherTests.cpp Cipher/Arc4GenTests.cpp Cipher/Arc4CryptTests.cpp Cipher/DesCryptTests.cpp - Padding/PadPkcs7Tests.cpp + Padding/PadderPkcs7Tests.cpp Service/SeArrayTests.cpp Service/ChaosExceptionTests.cpp) diff --git a/ChaosTests/Padding/PadPkcs7Tests.cpp b/ChaosTests/Padding/PadderPkcs7Tests.cpp similarity index 76% rename from ChaosTests/Padding/PadPkcs7Tests.cpp rename to ChaosTests/Padding/PadderPkcs7Tests.cpp index b511460..bfbcdaf 100644 --- a/ChaosTests/Padding/PadPkcs7Tests.cpp +++ b/ChaosTests/Padding/PadderPkcs7Tests.cpp @@ -3,7 +3,7 @@ #include #include -#include "Padding/PadPkcs7.hpp" +#include "Padding/PadderPkcs7.hpp" #include "Service/ChaosException.hpp" using namespace Chaos::Padding; @@ -14,7 +14,7 @@ TEST(PadPkcs7Tests, PadTest) std::array fact = {}; std::array expected = { 0x01 }; - PadPkcs7::Pad(fact.begin(), fact.end()); + PadderPkcs7::Pad(fact.begin(), fact.end()); ASSERT_EQ(expected, fact); } @@ -26,7 +26,7 @@ TEST(PadPkcs7Tests, PadTest) 0x07, 0x07 }; - PadPkcs7::Pad(fact.begin(), fact.end()); + PadderPkcs7::Pad(fact.begin(), fact.end()); ASSERT_EQ(expected, fact); } @@ -38,7 +38,7 @@ TEST(PadPkcs7Tests, PadTest) 0x0a, 0x0a, 0x0a, 0x0a, 0x0a }; - PadPkcs7::Pad(fact.begin(), fact.end()); + PadderPkcs7::Pad(fact.begin(), fact.end()); ASSERT_EQ(expected, fact); } @@ -46,7 +46,7 @@ TEST(PadPkcs7Tests, PadTest) { std::vector fact(i, 0x00); - PadPkcs7::Pad(fact.begin(), fact.end()); + PadderPkcs7::Pad(fact.begin(), fact.end()); ASSERT_EQ(std::vector(i, i), fact); } } @@ -56,19 +56,19 @@ TEST(PadPkcs7Tests, PadInvalidRangeTest) { std::array out = {}; - ASSERT_THROW(PadPkcs7::Pad(out.begin(), out.end()), Chaos::Service::ChaosException); + ASSERT_THROW(PadderPkcs7::Pad(out.begin(), out.end()), Chaos::Service::ChaosException); } { std::array out = {}; - ASSERT_THROW(PadPkcs7::Pad(out.begin(), out.end()), Chaos::Service::ChaosException); + ASSERT_THROW(PadderPkcs7::Pad(out.begin(), out.end()), Chaos::Service::ChaosException); } { std::array out = {}; - ASSERT_THROW(PadPkcs7::Pad(out.end(), out.begin()), Chaos::Service::ChaosException); + ASSERT_THROW(PadderPkcs7::Pad(out.end(), out.begin()), Chaos::Service::ChaosException); } } @@ -84,7 +84,7 @@ TEST(PadPkcs7Tests, PadOutIteratorUsageTest) 0x00, 0x00, 0x00 }; - PadPkcs7::Pad(fact.begin() + 3, fact.end() - 3); + PadderPkcs7::Pad(fact.begin() + 3, fact.end() - 3); ASSERT_EQ(expected, fact); } @@ -99,7 +99,7 @@ TEST(PadPkcs7Tests, PadOutIteratorUsageTest) 0x00, 0x00, 0x00 }; - PadPkcs7::Pad(fact.begin() + 3, fact.end() - 3); + PadderPkcs7::Pad(fact.begin() + 3, fact.end() - 3); ASSERT_EQ(expected, fact); } @@ -115,7 +115,7 @@ TEST(PadPkcs7Tests, PadOutIteratorUsageTest) 0xbb, 0xbb, 0xbb, 0xbb, 0xbb }; - PadPkcs7::Pad(fact.begin() + 5, fact.begin() + 5); + PadderPkcs7::Pad(fact.begin() + 5, fact.begin() + 5); ASSERT_EQ(expected, fact); } } From 797a5428cc3d9eb2b20a3ecd7df5a3c2ea435a40 Mon Sep 17 00:00:00 2001 From: hashlag Date: Sun, 8 Feb 2026 23:44:51 +0300 Subject: [PATCH 3/7] Add Padder<>. A CRTP base for padding algorithms. --- Chaos/Padding/Padder.hpp | 34 +++++++++++++++++++++++++ Chaos/Padding/PadderPkcs7.hpp | 3 ++- ChaosTests/Padding/PadderPkcs7Tests.cpp | 22 ++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 Chaos/Padding/Padder.hpp diff --git a/Chaos/Padding/Padder.hpp b/Chaos/Padding/Padder.hpp new file mode 100644 index 0000000..2f75e6e --- /dev/null +++ b/Chaos/Padding/Padder.hpp @@ -0,0 +1,34 @@ +#ifndef CHAOS_PADDING_PADDER_HPP +#define CHAOS_PADDING_PADDER_HPP + +namespace Chaos::Padding +{ + +template +class Padder +{ +public: + template + void Pad(OutputIt begin, OutputIt end) const + { + Impl().Pad(begin, end); + } + +protected: + Padder() = default; + +private: + const T & Impl() const + { + return static_cast(*this); + } + + T & Impl() + { + return static_cast(*this); + } +}; + +} // namespace Chaos::Padding + +#endif // CHAOS_PADDING_PADDER_HPP diff --git a/Chaos/Padding/PadderPkcs7.hpp b/Chaos/Padding/PadderPkcs7.hpp index e35d891..9cbe53c 100644 --- a/Chaos/Padding/PadderPkcs7.hpp +++ b/Chaos/Padding/PadderPkcs7.hpp @@ -5,12 +5,13 @@ #include #include +#include "Padding/Padder.hpp" #include "Service/ChaosException.hpp" namespace Chaos::Padding { -class PadderPkcs7 +class PadderPkcs7 : public Padder { public: template diff --git a/ChaosTests/Padding/PadderPkcs7Tests.cpp b/ChaosTests/Padding/PadderPkcs7Tests.cpp index bfbcdaf..874a704 100644 --- a/ChaosTests/Padding/PadderPkcs7Tests.cpp +++ b/ChaosTests/Padding/PadderPkcs7Tests.cpp @@ -119,3 +119,25 @@ TEST(PadPkcs7Tests, PadOutIteratorUsageTest) ASSERT_EQ(expected, fact); } } + +template +void PadThroughBase(const Padder & padder, OutputIt begin, OutputIt end) +{ + padder.Pad(begin, end); +} + +TEST(PadPkcs7Tests, PadThroughBaseTest) +{ + { + std::array fact = {}; + std::array expected = + { + 0x05, 0x05, 0x05, 0x05, 0x05 + }; + + const PadderPkcs7 padder; + PadThroughBase(padder, fact.begin(), fact.end()); + + ASSERT_EQ(expected, fact); + } +} From 6998d81e983476c6cb46b9c288fff842c4b8319e Mon Sep 17 00:00:00 2001 From: hashlag Date: Sun, 22 Mar 2026 23:53:33 +0300 Subject: [PATCH 4/7] Fix compilation with apple clang. Provide the template parameter for std::min<> explicitly. :) --- Chaos/Cipher/Arc4/Arc4Crypt.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Chaos/Cipher/Arc4/Arc4Crypt.hpp b/Chaos/Cipher/Arc4/Arc4Crypt.hpp index 713e86f..88ce26b 100644 --- a/Chaos/Cipher/Arc4/Arc4Crypt.hpp +++ b/Chaos/Cipher/Arc4/Arc4Crypt.hpp @@ -67,7 +67,7 @@ private: while (count > 0) { - uint64_t keyMaterialBytes = std::min(keyBuf.Size(), count); + uint64_t keyMaterialBytes = std::min(keyBuf.Size(), count); Gen_.Generate(keyBuf.Begin(), keyMaterialBytes); for (auto keyBufIt = keyBuf.Begin(); From 47b82485868c4b880453ac697dc4424911c181fa Mon Sep 17 00:00:00 2001 From: hashlag Date: Mon, 23 Mar 2026 00:14:04 +0300 Subject: [PATCH 5/7] Fix exception message. Mentioned class was renamed. --- Chaos/Padding/PadderPkcs7.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Chaos/Padding/PadderPkcs7.hpp b/Chaos/Padding/PadderPkcs7.hpp index 9cbe53c..f94f43c 100644 --- a/Chaos/Padding/PadderPkcs7.hpp +++ b/Chaos/Padding/PadderPkcs7.hpp @@ -28,7 +28,7 @@ public: } else { - throw Service::ChaosException("PadPkcs7::Pad(): invalid range"); + throw Service::ChaosException("PadderPkcs7::Pad(): invalid range"); } } }; From 5a16d154a2ba79289213fc79a9ce2d1c003bd8ca Mon Sep 17 00:00:00 2001 From: hashlag Date: Wed, 17 Jun 2026 23:44:17 +0300 Subject: [PATCH 6/7] Add .DS_Store to .gitignore. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2994ef0..8da1c69 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .cache/ .vscode/ build/ +.DS_Store From eb3da5ff75c80f377c120f2bb3ad6d2b9949a157 Mon Sep 17 00:00:00 2001 From: hashlag Date: Thu, 18 Jun 2026 01:28:38 +0300 Subject: [PATCH 7/7] Add ISO/IEC 7816-4 padding implementation. --- Chaos/Padding/PadderIso7816.hpp | 33 ++++++ ChaosTests/CMakeLists.txt | 1 + ChaosTests/Padding/PadderIso7816Tests.cpp | 131 ++++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 Chaos/Padding/PadderIso7816.hpp create mode 100644 ChaosTests/Padding/PadderIso7816Tests.cpp diff --git a/Chaos/Padding/PadderIso7816.hpp b/Chaos/Padding/PadderIso7816.hpp new file mode 100644 index 0000000..113b838 --- /dev/null +++ b/Chaos/Padding/PadderIso7816.hpp @@ -0,0 +1,33 @@ +#ifndef CHAOS_PADDING_PADDERISO7816_HPP +#define CHAOS_PADDING_PADDERISO7816_HPP + +#include + +#include "Padding/Padder.hpp" + +namespace Chaos::Padding +{ + +class PadderIso7816 : public Padder +{ +public: + template + static void Pad(OutputIt begin, OutputIt end) + { + OutputIt it = begin; + + if (it != end) + { + *it++ = static_cast(0x80); + + for (; it != end; ++it) + { + *it = 0; + } + } + } +}; + +} // namespace Chaos::Padding + +#endif // CHAOS_PADDING_PADDERISO7816_HPP diff --git a/ChaosTests/CMakeLists.txt b/ChaosTests/CMakeLists.txt index 796ce51..2345b8d 100644 --- a/ChaosTests/CMakeLists.txt +++ b/ChaosTests/CMakeLists.txt @@ -19,6 +19,7 @@ set(ChaosTests_SOURCE Hash/Md4HasherTests.cpp Cipher/Arc4CryptTests.cpp Cipher/DesCryptTests.cpp Padding/PadderPkcs7Tests.cpp + Padding/PadderIso7816Tests.cpp Service/SeArrayTests.cpp Service/ChaosExceptionTests.cpp) diff --git a/ChaosTests/Padding/PadderIso7816Tests.cpp b/ChaosTests/Padding/PadderIso7816Tests.cpp new file mode 100644 index 0000000..e29b0c0 --- /dev/null +++ b/ChaosTests/Padding/PadderIso7816Tests.cpp @@ -0,0 +1,131 @@ +#include +#include +#include +#include + +#include "Padding/PadderIso7816.hpp" + +using namespace Chaos::Padding; + +TEST(PadIso7816Tests, PadTest) +{ + { + std::array fact = {}; + std::array expected = { 0x80 }; + + PadderIso7816::Pad(fact.begin(), fact.end()); + ASSERT_EQ(expected, fact); + } + + { + std::array fact = {}; + std::array expected = + { + 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 + }; + + PadderIso7816::Pad(fact.begin(), fact.end()); + ASSERT_EQ(expected, fact); + } + + { + std::array fact = {}; + std::array expected = + { + 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + PadderIso7816::Pad(fact.begin(), fact.end()); + ASSERT_EQ(expected, fact); + } + + for (int i = 0; i < 256; ++i) + { + std::vector fact(i, 0xff); + + PadderIso7816::Pad(fact.begin(), fact.end()); + + for (int j = 0; j < i; ++j) + { + ASSERT_EQ(j == 0 ? 0x80 : 0x00, fact[j]); + } + } +} + +TEST(PadIso7816Tests, PadOutIteratorUsageTest) +{ + { + std::array fact; + fact.fill(0xff); + + std::array expected = + { + 0xff, 0xff, 0xff, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff + }; + + PadderIso7816::Pad(fact.begin() + 3, fact.end() - 3); + ASSERT_EQ(expected, fact); + } + + { + std::array fact; + fact.fill(0xff); + + std::array expected = + { + 0xff, 0xff, 0xff, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff + }; + + PadderIso7816::Pad(fact.begin() + 3, fact.end() - 3); + ASSERT_EQ(expected, fact); + } + + { + std::array fact = + { + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb + }; + std::array expected = + { + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb + }; + + PadderIso7816::Pad(fact.begin() + 5, fact.begin() + 5); + ASSERT_EQ(expected, fact); + } +} + +template +void PadThroughBase(const Padder & padder, OutputIt begin, OutputIt end) +{ + padder.Pad(begin, end); +} + +TEST(PadIso7816Tests, PadThroughBaseTest) +{ + { + std::array fact; + fact.fill(0xff); + + std::array expected = + { + 0x80, 0x00, 0x00, 0x00, 0x00 + }; + + const PadderIso7816 padder; + PadThroughBase(padder, fact.begin(), fact.end()); + + ASSERT_EQ(expected, fact); + } +}