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/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/Chaos/Padding/PadderPkcs7.hpp b/Chaos/Padding/PadderPkcs7.hpp new file mode 100644 index 0000000..f94f43c --- /dev/null +++ b/Chaos/Padding/PadderPkcs7.hpp @@ -0,0 +1,38 @@ +#ifndef CHAOS_PADDING_PADDERPKCS7_HPP +#define CHAOS_PADDING_PADDERPKCS7_HPP + +#include +#include +#include + +#include "Padding/Padder.hpp" +#include "Service/ChaosException.hpp" + +namespace Chaos::Padding +{ + +class PadderPkcs7 : public Padder +{ +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("PadderPkcs7::Pad(): invalid range"); + } + } +}; + +} // namespace Chaos::Padding + +#endif // CHAOS_PADDING_PADDERPKCS7_HPP diff --git a/ChaosTests/CMakeLists.txt b/ChaosTests/CMakeLists.txt index 1aa05df..2345b8d 100644 --- a/ChaosTests/CMakeLists.txt +++ b/ChaosTests/CMakeLists.txt @@ -18,6 +18,8 @@ set(ChaosTests_SOURCE Hash/Md4HasherTests.cpp Cipher/Arc4GenTests.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); + } +} diff --git a/ChaosTests/Padding/PadderPkcs7Tests.cpp b/ChaosTests/Padding/PadderPkcs7Tests.cpp new file mode 100644 index 0000000..874a704 --- /dev/null +++ b/ChaosTests/Padding/PadderPkcs7Tests.cpp @@ -0,0 +1,143 @@ +#include +#include +#include +#include + +#include "Padding/PadderPkcs7.hpp" +#include "Service/ChaosException.hpp" + +using namespace Chaos::Padding; + +TEST(PadPkcs7Tests, PadTest) +{ + { + std::array fact = {}; + std::array expected = { 0x01 }; + + PadderPkcs7::Pad(fact.begin(), fact.end()); + ASSERT_EQ(expected, fact); + } + + { + std::array fact = {}; + std::array expected = + { + 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07 + }; + + PadderPkcs7::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 + }; + + PadderPkcs7::Pad(fact.begin(), fact.end()); + ASSERT_EQ(expected, fact); + } + + for (int i = 0; i < 256; ++i) + { + std::vector fact(i, 0x00); + + PadderPkcs7::Pad(fact.begin(), fact.end()); + ASSERT_EQ(std::vector(i, i), fact); + } +} + +TEST(PadPkcs7Tests, PadInvalidRangeTest) +{ + { + std::array out = {}; + + ASSERT_THROW(PadderPkcs7::Pad(out.begin(), out.end()), Chaos::Service::ChaosException); + } + + { + std::array out = {}; + + ASSERT_THROW(PadderPkcs7::Pad(out.begin(), out.end()), Chaos::Service::ChaosException); + } + + { + std::array out = {}; + + ASSERT_THROW(PadderPkcs7::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 + }; + + PadderPkcs7::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 + }; + + PadderPkcs7::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 + }; + + PadderPkcs7::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(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); + } +}