Compare commits
96 Commits
a8141cb708
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0647a7c3dc | ||
|
|
7c86d704b7 | ||
|
|
9f6265395d | ||
|
|
151c93560c | ||
|
|
3059bd4c66 | ||
|
|
ccf1397595 | ||
|
|
6a09d81ae2 | ||
|
|
b4f015f501 | ||
|
|
95e74db6ec | ||
|
|
ed22d29af0 | ||
|
|
65eb51c133 | ||
|
|
b34fda75ef | ||
|
|
15d841893c | ||
|
|
5fd27cd7b5 | ||
|
|
1bf91a90d0 | ||
|
|
2d64389d66 | ||
|
|
ccdf14d31a | ||
|
|
9734f9a517 | ||
|
|
3de69d3298 | ||
|
|
a0f17ea127 | ||
|
|
67709e5361 | ||
|
|
d194fef1af | ||
|
|
cdcab2f4f7 | ||
|
|
a97826da88 | ||
|
|
8897d7a910 | ||
|
|
73c455901b | ||
|
|
4cf79b61ad | ||
|
|
ba70abd2af | ||
|
|
9a3b6edfc3 | ||
|
|
3c98b75986 | ||
|
|
b5d1f9a6fc | ||
|
|
2c9200ab21 | ||
|
|
6246bf4538 | ||
|
|
78c59dc668 | ||
|
|
d4fa11795b | ||
|
|
3780586e63 | ||
|
|
cc9963f1ca | ||
|
|
05533e7c6b | ||
|
|
961a521c57 | ||
|
|
029055f9a3 | ||
|
|
b5f86b5633 | ||
|
|
0bc29c86e5 | ||
|
|
11561c9379 | ||
|
|
b7a31b44df | ||
|
|
4ae55f93fc | ||
|
|
8eb0c6ab12 | ||
|
|
90c44f5305 | ||
|
|
cd6014d8c0 | ||
|
|
0a8b79cd09 | ||
|
|
0c3ce4af8d | ||
|
|
01d7d19ee6 | ||
|
|
612b11b02f | ||
|
|
15bb663281 | ||
|
|
9a764c06db | ||
|
|
b02685d29f | ||
|
|
1a999a7dd3 | ||
|
|
18bcd87f81 | ||
|
|
07663decf9 | ||
|
|
2a5a2c96b5 | ||
|
|
d0e7d2b0ec | ||
|
|
4e89b2fb05 | ||
|
|
1e593ef703 | ||
|
|
9eb2a6bcde | ||
|
|
85fe3cfe88 | ||
|
|
89991c21f5 | ||
|
|
d8c8fd0ce3 | ||
|
|
5ec6fc2f20 | ||
|
|
512338df33 | ||
|
|
bdd43d8fa2 | ||
|
|
ab9220587e | ||
|
|
254c1e0e01 | ||
|
|
26d866d1cf | ||
|
|
b707e1ce68 | ||
|
|
b9eb1a5fc8 | ||
|
|
28334d1d78 | ||
|
|
d30d5f8a74 | ||
|
|
478012dd10 | ||
|
|
ff57cd0d31 | ||
|
|
3e7a0f3e53 | ||
|
|
c0685d00b5 | ||
|
|
660b13a045 | ||
|
|
cbefae2256 | ||
|
|
4da2f0e6eb | ||
|
|
0ca97cc336 | ||
|
|
66413e2cfc | ||
|
|
e8d0b93c5e | ||
|
|
5a2d802a25 | ||
|
|
15dd7398d2 | ||
|
|
5fd92e0c9d | ||
|
|
da5eaff182 | ||
|
|
3a2a665031 | ||
|
|
fa042e7abf | ||
|
|
9e67a7e4f4 | ||
|
|
d63855a505 | ||
|
|
51c2da1e48 | ||
|
|
5e35462667 |
50
.gitea/workflows/ChaosCi.yaml
Normal file
50
.gitea/workflows/ChaosCi.yaml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
name: Chaos Ci
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test-and-benchmark:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
|
||||||
|
- name: Install
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y build-essential cmake valgrind lcov
|
||||||
|
|
||||||
|
- name: Configure and build tests [Debug]
|
||||||
|
run: |
|
||||||
|
mkdir build-debug
|
||||||
|
cmake -S . -B build-debug/ -D CMAKE_BUILD_TYPE=Debug
|
||||||
|
cmake --build build-debug/ -t ChaosTests
|
||||||
|
|
||||||
|
- name: Configure and build benchmarks [Release]
|
||||||
|
run: |
|
||||||
|
mkdir build-release
|
||||||
|
cmake -S . -B build-release/ -D CMAKE_BUILD_TYPE=Release
|
||||||
|
cmake --build build-release/ -t ChaosBenches
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: valgrind --leak-check=full --track-origins=yes --show-leak-kinds=all ./build-debug/ChaosTests/ChaosTests
|
||||||
|
|
||||||
|
- name: Run benchmarks
|
||||||
|
run: ./build-release/ChaosBenches/ChaosBenches
|
||||||
|
|
||||||
|
- name: Process coverage data
|
||||||
|
run: |
|
||||||
|
lcov --exclude '*/usr/*' --exclude '*/_deps/*' --exclude '*/ChaosTests/*' -c -d build-debug/ -o lcovout
|
||||||
|
genhtml lcovout -o coverage-report/
|
||||||
|
|
||||||
|
- name: Upload coverage report
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: CoverageReport
|
||||||
|
path: coverage-report/
|
||||||
|
if-no-files-found: error
|
||||||
|
include-hidden-files: true
|
||||||
|
retention-days: 10
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
name: ChaosTest CI
|
|
||||||
|
|
||||||
on: [push, pull_request]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
|
|
||||||
- name: Install
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y build-essential cmake
|
|
||||||
|
|
||||||
- name: Configure, build
|
|
||||||
run: |
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake ..
|
|
||||||
cmake --build .
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
run: |
|
|
||||||
cd build
|
|
||||||
./ChaosTests/ChaosTests
|
|
||||||
@@ -15,3 +15,4 @@ target_include_directories(Chaos INTERFACE
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(ChaosTests)
|
add_subdirectory(ChaosTests)
|
||||||
|
add_subdirectory(ChaosBenches)
|
||||||
|
|||||||
46
Chaos/Cipher/Block/Decryptor.hpp
Normal file
46
Chaos/Cipher/Block/Decryptor.hpp
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#ifndef CHAOS_CIPHER_BLOCK_DECRYPTOR_HPP
|
||||||
|
#define CHAOS_CIPHER_BLOCK_DECRYPTOR_HPP
|
||||||
|
|
||||||
|
namespace Chaos::Cipher::Block
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Decryptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template<typename OutputIt, typename InputIt>
|
||||||
|
void DecryptBlock(OutputIt outBegin, OutputIt outEnd,
|
||||||
|
InputIt inBegin, InputIt inEnd) const
|
||||||
|
{
|
||||||
|
Impl().DecryptBlock(outBegin, outEnd, inBegin, inEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Block>
|
||||||
|
auto DecryptBlock(Block block) const
|
||||||
|
{
|
||||||
|
return Impl().DecryptBlock(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto GetBlockSize() const
|
||||||
|
{
|
||||||
|
return Impl().GetBlockSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Decryptor() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const T & Impl() const
|
||||||
|
{
|
||||||
|
return static_cast<const T &>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
T & Impl()
|
||||||
|
{
|
||||||
|
return static_cast<T &>(*this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Chaos::Cipher::Block
|
||||||
|
|
||||||
|
#endif // CHAOS_CIPHER_BLOCK_DECRYPTOR_HPP
|
||||||
517
Chaos/Cipher/Block/Des/DesCrypt.hpp
Normal file
517
Chaos/Cipher/Block/Des/DesCrypt.hpp
Normal file
@@ -0,0 +1,517 @@
|
|||||||
|
#ifndef CHAOS_CIPHER_BLOCK_DES_DESCRYPT_HPP
|
||||||
|
#define CHAOS_CIPHER_BLOCK_DES_DESCRYPT_HPP
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "Service/ChaosException.hpp"
|
||||||
|
#include "Service/SeArray.hpp"
|
||||||
|
|
||||||
|
#include "Cipher/Block/Encryptor.hpp"
|
||||||
|
#include "Cipher/Block/Decryptor.hpp"
|
||||||
|
|
||||||
|
namespace Chaos::Cipher::Block::Des::Inner_
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Bitwise
|
||||||
|
{
|
||||||
|
template<uint8_t BitsUsed>
|
||||||
|
static uint8_t GetBit(uint64_t value, int_fast8_t bitNumber)
|
||||||
|
{
|
||||||
|
return (value >> (BitsUsed - bitNumber)) & 0b1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<uint8_t BitsUsed>
|
||||||
|
static void SetBit(uint64_t & value, int_fast8_t bitNumber)
|
||||||
|
{
|
||||||
|
value |= (static_cast<uint64_t>(0b1) << (BitsUsed - bitNumber));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<uint8_t BitsUsedIn, uint8_t BitsUsedOut, typename InputIt>
|
||||||
|
static uint64_t TableChoice(uint64_t value, InputIt tableBegin, InputIt tableEnd)
|
||||||
|
{
|
||||||
|
uint64_t result = 0;
|
||||||
|
|
||||||
|
int_fast8_t i = 1;
|
||||||
|
for (InputIt it = tableBegin; it != tableEnd; ++it, ++i)
|
||||||
|
{
|
||||||
|
if (GetBit<BitsUsedIn>(value, *it))
|
||||||
|
{
|
||||||
|
SetBit<BitsUsedOut>(result, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<uint8_t Bits>
|
||||||
|
static constexpr uint64_t Mask()
|
||||||
|
{
|
||||||
|
return (static_cast<uint64_t>(0b1) << Bits) - static_cast<uint64_t>(0b1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<uint8_t BitsUsed>
|
||||||
|
static void Rotl(uint64_t & value, int_fast8_t shift)
|
||||||
|
{
|
||||||
|
value = ((value << shift) | (value >> (BitsUsed - shift))) & Mask<BitsUsed>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<uint8_t BitsUsedOut>
|
||||||
|
static std::pair<uint64_t, uint64_t> Split(uint64_t value)
|
||||||
|
{
|
||||||
|
return { value >> BitsUsedOut, value & Mask<BitsUsedOut>() };
|
||||||
|
}
|
||||||
|
|
||||||
|
template<uint8_t BitsUsedIn>
|
||||||
|
static uint64_t Merge(uint64_t lhs, uint64_t rhs)
|
||||||
|
{
|
||||||
|
return (lhs << BitsUsedIn) | rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename InputIt>
|
||||||
|
static uint64_t PackUInt64(InputIt begin, InputIt end)
|
||||||
|
{
|
||||||
|
uint64_t result = 0;
|
||||||
|
|
||||||
|
int_fast8_t i = 0;
|
||||||
|
for (InputIt it = begin; i < 8 && it != end; ++i, ++it)
|
||||||
|
{
|
||||||
|
result |= static_cast<uint64_t>(*it) << (56 - (i * 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OutputIt>
|
||||||
|
static void CrunchUInt64(OutputIt outBegin, OutputIt outEnd, uint64_t value)
|
||||||
|
{
|
||||||
|
int_fast8_t i = 0;
|
||||||
|
for (OutputIt out = outBegin; i < 8 && out != outEnd; ++i, ++out)
|
||||||
|
{
|
||||||
|
*out = (value >> (56 - (i * 8))) & Mask<8>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using RawKey = Service::SeArray<uint8_t, 8>;
|
||||||
|
|
||||||
|
class KeySchedule
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Key64 = uint64_t;
|
||||||
|
using Key56 = uint64_t;
|
||||||
|
|
||||||
|
using RoundKey48 = uint64_t;
|
||||||
|
|
||||||
|
enum class Direction
|
||||||
|
{
|
||||||
|
Encrypt,
|
||||||
|
Decrypt
|
||||||
|
};
|
||||||
|
|
||||||
|
KeySchedule(Direction direction, const RawKey & rawKey)
|
||||||
|
{
|
||||||
|
Key56 key56 = Pc1(Bitwise::PackUInt64(rawKey.Begin(), rawKey.End()));
|
||||||
|
|
||||||
|
auto [c28, d28] = Bitwise::Split<28>(key56);
|
||||||
|
|
||||||
|
for (int_fast8_t i = 0; i < Schedule_.Size(); ++i)
|
||||||
|
{
|
||||||
|
if (i == 0 || i == 1 || i == 8 || i == 15)
|
||||||
|
{
|
||||||
|
Bitwise::Rotl<28>(c28, 1);
|
||||||
|
Bitwise::Rotl<28>(d28, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Bitwise::Rotl<28>(c28, 2);
|
||||||
|
Bitwise::Rotl<28>(d28, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Schedule_[i] = Pc2(Bitwise::Merge<28>(c28, d28));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (direction == Direction::Decrypt)
|
||||||
|
{
|
||||||
|
std::reverse(Schedule_.Begin(), Schedule_.End());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RoundKey48 operator[](int_fast8_t i) const
|
||||||
|
{
|
||||||
|
return Schedule_[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Service::SeArray<RoundKey48, 16> Schedule_;
|
||||||
|
|
||||||
|
static Key56 Pc1(Key64 key)
|
||||||
|
{
|
||||||
|
constexpr int_fast8_t PC1_TABLE[] =
|
||||||
|
{
|
||||||
|
57, 49, 41, 33, 25, 17, 9,
|
||||||
|
1, 58, 50, 42, 34, 26, 18,
|
||||||
|
10, 2, 59, 51, 43, 35, 27,
|
||||||
|
19, 11, 3, 60, 52, 44, 36,
|
||||||
|
63, 55, 47, 39, 31, 23, 15,
|
||||||
|
7, 62, 54, 46, 38, 30, 22,
|
||||||
|
14, 6, 61, 53, 45, 37, 29,
|
||||||
|
21, 13, 5, 28, 20, 12, 4
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(std::size(PC1_TABLE) == 56);
|
||||||
|
|
||||||
|
return Bitwise::TableChoice<64, 56>(key,
|
||||||
|
PC1_TABLE,
|
||||||
|
PC1_TABLE + std::size(PC1_TABLE));
|
||||||
|
}
|
||||||
|
|
||||||
|
static RoundKey48 Pc2(Key56 key)
|
||||||
|
{
|
||||||
|
constexpr int_fast8_t PC2_TABLE[] =
|
||||||
|
{
|
||||||
|
14, 17, 11, 24, 1, 5,
|
||||||
|
3, 28, 15, 6, 21, 10,
|
||||||
|
23, 19, 12, 4, 26, 8,
|
||||||
|
16, 7, 27, 20, 13, 2,
|
||||||
|
41, 52, 31, 37, 47, 55,
|
||||||
|
30, 40, 51, 45, 33, 48,
|
||||||
|
44, 49, 39, 56, 34, 53,
|
||||||
|
46, 42, 50, 36, 29, 32
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(std::size(PC2_TABLE) == 48);
|
||||||
|
|
||||||
|
return Bitwise::TableChoice<56, 48>(key,
|
||||||
|
PC2_TABLE,
|
||||||
|
PC2_TABLE + std::size(PC2_TABLE));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Chaos::Cipher::Block::Des::Inner_
|
||||||
|
|
||||||
|
namespace Chaos::Cipher::Block::Des
|
||||||
|
{
|
||||||
|
|
||||||
|
class DesCrypt
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Block = uint64_t;
|
||||||
|
static constexpr size_t BlockSize = 8;
|
||||||
|
static constexpr size_t KeySize = 8;
|
||||||
|
|
||||||
|
static_assert(BlockSize == sizeof(Block));
|
||||||
|
static_assert(KeySize == Inner_::RawKey::Size());
|
||||||
|
|
||||||
|
DesCrypt() = delete;
|
||||||
|
|
||||||
|
class Key
|
||||||
|
{
|
||||||
|
friend class DesCrypt;
|
||||||
|
public:
|
||||||
|
template<typename InputIt>
|
||||||
|
Key(InputIt keyBegin, InputIt keyEnd)
|
||||||
|
{
|
||||||
|
int_fast8_t i = 0;
|
||||||
|
InputIt keyIt = keyBegin;
|
||||||
|
for (; i < Key_.Size() && keyIt != keyEnd; ++i, ++keyIt)
|
||||||
|
{
|
||||||
|
Key_[i] = *keyIt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i != Key_.Size() || keyIt != keyEnd)
|
||||||
|
{
|
||||||
|
throw Service::ChaosException("DesCrypt::Key: invalid key length "
|
||||||
|
"(8 bytes required)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Inner_::RawKey Key_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DesEncryptor : public Encryptor<DesEncryptor>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Key = DesCrypt::Key;
|
||||||
|
static constexpr size_t BlockSize = DesCrypt::BlockSize;
|
||||||
|
static constexpr size_t KeySize = DesCrypt::KeySize;
|
||||||
|
|
||||||
|
DesEncryptor(const Key & key)
|
||||||
|
: Schedule_(Inner_::KeySchedule::Direction::Encrypt, key.Key_)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
template<typename OutputIt, typename InputIt>
|
||||||
|
void EncryptBlock(OutputIt outBegin, OutputIt outEnd,
|
||||||
|
InputIt inBegin, InputIt inEnd) const
|
||||||
|
{
|
||||||
|
RawBlockArray block;
|
||||||
|
|
||||||
|
int_fast8_t i = 0;
|
||||||
|
for (InputIt in = inBegin; i < block.Size() && in != inEnd; ++i, ++in)
|
||||||
|
{
|
||||||
|
block[i] = *in;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block encrypted
|
||||||
|
= DesCrypt::ProcessBlock(Inner_::Bitwise::PackUInt64(block.Begin(),
|
||||||
|
block.End()),
|
||||||
|
Schedule_);
|
||||||
|
|
||||||
|
Inner_::Bitwise::CrunchUInt64(outBegin, outEnd, encrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
Block EncryptBlock(Block block) const
|
||||||
|
{
|
||||||
|
return DesCrypt::ProcessBlock(block, Schedule_);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t GetBlockSize() const
|
||||||
|
{
|
||||||
|
return BlockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Inner_::KeySchedule Schedule_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DesDecryptor : public Decryptor<DesDecryptor>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Key = DesCrypt::Key;
|
||||||
|
static constexpr size_t BlockSize = DesCrypt::BlockSize;
|
||||||
|
static constexpr size_t KeySize = DesCrypt::KeySize;
|
||||||
|
|
||||||
|
DesDecryptor(const Key & key)
|
||||||
|
: Schedule_(Inner_::KeySchedule::Direction::Decrypt, key.Key_)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
template<typename OutputIt, typename InputIt>
|
||||||
|
void DecryptBlock(OutputIt outBegin, OutputIt outEnd,
|
||||||
|
InputIt inBegin, InputIt inEnd) const
|
||||||
|
{
|
||||||
|
RawBlockArray block;
|
||||||
|
|
||||||
|
int_fast8_t i = 0;
|
||||||
|
for (InputIt in = inBegin; i < block.Size() && in != inEnd; ++i, ++in)
|
||||||
|
{
|
||||||
|
block[i] = *in;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block decrypted
|
||||||
|
= DesCrypt::ProcessBlock(Inner_::Bitwise::PackUInt64(block.Begin(),
|
||||||
|
block.End()),
|
||||||
|
Schedule_);
|
||||||
|
|
||||||
|
Inner_::Bitwise::CrunchUInt64(outBegin, outEnd, decrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
Block DecryptBlock(Block block) const
|
||||||
|
{
|
||||||
|
return DesCrypt::ProcessBlock(block, Schedule_);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t GetBlockSize() const
|
||||||
|
{
|
||||||
|
return BlockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Inner_::KeySchedule Schedule_;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
using BlockHalf = uint32_t;
|
||||||
|
using RawBlockArray = Service::SeArray<uint8_t, 8>;
|
||||||
|
using Data48 = uint64_t;
|
||||||
|
using Data32 = uint32_t;
|
||||||
|
using Data6 = uint8_t;
|
||||||
|
using Data4 = uint8_t;
|
||||||
|
|
||||||
|
static Data48 E(Data32 value)
|
||||||
|
{
|
||||||
|
constexpr int_fast8_t E_TABLE[] =
|
||||||
|
{
|
||||||
|
32, 1, 2, 3, 4, 5,
|
||||||
|
4, 5, 6, 7, 8, 9,
|
||||||
|
8, 9, 10, 11, 12, 13,
|
||||||
|
12, 13, 14, 15, 16, 17,
|
||||||
|
16, 17, 18, 19, 20, 21,
|
||||||
|
20, 21, 22, 23, 24, 25,
|
||||||
|
24, 25, 26, 27, 28, 29,
|
||||||
|
28, 29, 30, 31, 32, 1
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(std::size(E_TABLE) == 48);
|
||||||
|
|
||||||
|
return Inner_::Bitwise::TableChoice<32, 48>(value,
|
||||||
|
E_TABLE,
|
||||||
|
E_TABLE + std::size(E_TABLE));
|
||||||
|
}
|
||||||
|
|
||||||
|
static Data32 SBlock(Data48 value)
|
||||||
|
{
|
||||||
|
constexpr Data4 SBOX_TABLES[][64] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1,
|
||||||
|
3, 10, 10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8,
|
||||||
|
4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7,
|
||||||
|
15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13
|
||||||
|
},
|
||||||
|
{
|
||||||
|
15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14,
|
||||||
|
9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5,
|
||||||
|
0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2,
|
||||||
|
5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10,
|
||||||
|
1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1,
|
||||||
|
13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7,
|
||||||
|
11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12
|
||||||
|
},
|
||||||
|
{
|
||||||
|
7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3,
|
||||||
|
1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9,
|
||||||
|
10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8,
|
||||||
|
15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14
|
||||||
|
},
|
||||||
|
{
|
||||||
|
2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1,
|
||||||
|
8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6,
|
||||||
|
4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13,
|
||||||
|
15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5,
|
||||||
|
0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8,
|
||||||
|
9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10,
|
||||||
|
7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13
|
||||||
|
},
|
||||||
|
{
|
||||||
|
4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10,
|
||||||
|
3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6,
|
||||||
|
1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7,
|
||||||
|
10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12
|
||||||
|
},
|
||||||
|
{
|
||||||
|
13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4,
|
||||||
|
10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2,
|
||||||
|
7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13,
|
||||||
|
0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(std::size(SBOX_TABLES) == 8);
|
||||||
|
|
||||||
|
Data32 result = 0;
|
||||||
|
|
||||||
|
for (int_fast8_t i = 0; i < 8; ++i)
|
||||||
|
{
|
||||||
|
Data6 input = (value >> (42 - (i * 6))) & Inner_::Bitwise::Mask<6>();
|
||||||
|
result |= static_cast<Data32>(SBOX_TABLES[i][input]) << (28 - (i * 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Data32 P(Data32 value)
|
||||||
|
{
|
||||||
|
constexpr int_fast8_t P_TABLE[] =
|
||||||
|
{
|
||||||
|
16, 7, 20, 21,
|
||||||
|
29, 12, 28, 17,
|
||||||
|
1, 15, 23, 26,
|
||||||
|
5, 18, 31, 10,
|
||||||
|
2, 8, 24, 14,
|
||||||
|
32, 27, 3, 9,
|
||||||
|
19, 13, 30, 6,
|
||||||
|
22, 11, 4, 25
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(std::size(P_TABLE) == 32);
|
||||||
|
|
||||||
|
return Inner_::Bitwise::TableChoice<32, 32>(value,
|
||||||
|
P_TABLE,
|
||||||
|
P_TABLE + std::size(P_TABLE));
|
||||||
|
}
|
||||||
|
|
||||||
|
static BlockHalf F(BlockHalf value, Inner_::KeySchedule::RoundKey48 roundKey)
|
||||||
|
{
|
||||||
|
Data48 expanded = E(value);
|
||||||
|
expanded = (expanded ^ roundKey) & Inner_::Bitwise::Mask<48>();
|
||||||
|
|
||||||
|
return P(SBlock(expanded));
|
||||||
|
}
|
||||||
|
|
||||||
|
static Block Ip(Block block)
|
||||||
|
{
|
||||||
|
constexpr int_fast8_t IP_TABLE[] =
|
||||||
|
{
|
||||||
|
58, 50, 42, 34, 26, 18, 10, 2,
|
||||||
|
60, 52, 44, 36, 28, 20, 12, 4,
|
||||||
|
62, 54, 46, 38, 30, 22, 14, 6,
|
||||||
|
64, 56, 48, 40, 32, 24, 16, 8,
|
||||||
|
57, 49, 41, 33, 25, 17, 9, 1,
|
||||||
|
59, 51, 43, 35, 27, 19, 11, 3,
|
||||||
|
61, 53, 45, 37, 29, 21, 13, 5,
|
||||||
|
63, 55, 47, 39, 31, 23, 15, 7
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(std::size(IP_TABLE) == 64);
|
||||||
|
|
||||||
|
return Inner_::Bitwise::TableChoice<64, 64>(block,
|
||||||
|
IP_TABLE,
|
||||||
|
IP_TABLE + std::size(IP_TABLE));
|
||||||
|
}
|
||||||
|
|
||||||
|
static Block Fp(Block block)
|
||||||
|
{
|
||||||
|
constexpr int_fast8_t FP_TABLE[] =
|
||||||
|
{
|
||||||
|
40, 8, 48, 16, 56, 24, 64, 32,
|
||||||
|
39, 7, 47, 15, 55, 23, 63, 31,
|
||||||
|
38, 6, 46, 14, 54, 22, 62, 30,
|
||||||
|
37, 5, 45, 13, 53, 21, 61, 29,
|
||||||
|
36, 4, 44, 12, 52, 20, 60, 28,
|
||||||
|
35, 3, 43, 11, 51, 19, 59, 27,
|
||||||
|
34, 2, 42, 10, 50, 18, 58, 26,
|
||||||
|
33, 1, 41, 9, 49, 17, 57, 25
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(std::size(FP_TABLE) == 64);
|
||||||
|
|
||||||
|
return Inner_::Bitwise::TableChoice<64, 64>(block,
|
||||||
|
FP_TABLE,
|
||||||
|
FP_TABLE + std::size(FP_TABLE));
|
||||||
|
}
|
||||||
|
|
||||||
|
static Block ProcessBlock(Block block, const Inner_::KeySchedule & schedule)
|
||||||
|
{
|
||||||
|
block = Ip(block);
|
||||||
|
|
||||||
|
uint32_t l32;
|
||||||
|
uint32_t r32;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto [l, r] = Inner_::Bitwise::Split<32>(block);
|
||||||
|
l32 = static_cast<uint32_t>(l);
|
||||||
|
r32 = static_cast<uint32_t>(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int_fast8_t i = 0; i < 16; ++i)
|
||||||
|
{
|
||||||
|
uint32_t l32Old = l32;
|
||||||
|
|
||||||
|
l32 = r32;
|
||||||
|
r32 = l32Old ^ F(r32, schedule[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Fp(Inner_::Bitwise::Merge<32>(r32, l32));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Chaos::Cipher::Block::Des
|
||||||
|
|
||||||
|
#endif // CHAOS_CIPHER_BLOCK_DES_DESCRYPT_HPP
|
||||||
46
Chaos/Cipher/Block/Encryptor.hpp
Normal file
46
Chaos/Cipher/Block/Encryptor.hpp
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#ifndef CHAOS_CIPHER_BLOCK_ENCRYPTOR_HPP
|
||||||
|
#define CHAOS_CIPHER_BLOCK_ENCRYPTOR_HPP
|
||||||
|
|
||||||
|
namespace Chaos::Cipher::Block
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Encryptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template<typename OutputIt, typename InputIt>
|
||||||
|
void EncryptBlock(OutputIt outBegin, OutputIt outEnd,
|
||||||
|
InputIt inBegin, InputIt inEnd) const
|
||||||
|
{
|
||||||
|
Impl().EncryptBlock(outBegin, outEnd, inBegin, inEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Block>
|
||||||
|
auto EncryptBlock(Block block) const
|
||||||
|
{
|
||||||
|
return Impl().EncryptBlock(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto GetBlockSize() const
|
||||||
|
{
|
||||||
|
return Impl().GetBlockSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Encryptor() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const T & Impl() const
|
||||||
|
{
|
||||||
|
return static_cast<const T &>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
T & Impl()
|
||||||
|
{
|
||||||
|
return static_cast<T &>(*this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Chaos::Cipher::Block
|
||||||
|
|
||||||
|
#endif // CHAOS_CIPHER_BLOCK_ENCRYPTOR_HPP
|
||||||
@@ -20,6 +20,9 @@ public:
|
|||||||
return Impl().ToHexString();
|
return Impl().ToHexString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Hash() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const T & Impl() const
|
const T & Impl() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ public:
|
|||||||
return Impl().Finish();
|
return Impl().Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Hasher() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const T & Impl() const
|
const T & Impl() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -58,11 +58,6 @@ public:
|
|||||||
return Storage_.data() + Storage_.size();
|
return Storage_.data() + Storage_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr size_t Size() const noexcept
|
|
||||||
{
|
|
||||||
return Storage_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fill(const T & value)
|
void Fill(const T & value)
|
||||||
{
|
{
|
||||||
Storage_.fill(value);
|
Storage_.fill(value);
|
||||||
@@ -73,6 +68,11 @@ public:
|
|||||||
EraseImpl();
|
EraseImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr size_t Size() noexcept
|
||||||
|
{
|
||||||
|
return S;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::array<T, S> Storage_;
|
std::array<T, S> Storage_;
|
||||||
|
|
||||||
|
|||||||
3
ChaosBenches/BenchmarkMain.cpp
Normal file
3
ChaosBenches/BenchmarkMain.cpp
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#include <benchmark/benchmark.h>
|
||||||
|
|
||||||
|
BENCHMARK_MAIN();
|
||||||
25
ChaosBenches/CMakeLists.txt
Normal file
25
ChaosBenches/CMakeLists.txt
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
cmake_policy(SET CMP0135 NEW)
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
googlebenchmark
|
||||||
|
URL https://git.hashlag.net/hashlag/chaos-deps/raw/branch/main/google_benchmark/benchmark-1.9.5.tar.gz
|
||||||
|
URL_HASH SHA256=9631341c82bac4a288bef951f8b26b41f69021794184ece969f8473977eaa340
|
||||||
|
)
|
||||||
|
|
||||||
|
set(BENCHMARK_ENABLE_WERROR OFF CACHE BOOL "" FORCE)
|
||||||
|
set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE)
|
||||||
|
FetchContent_MakeAvailable(googlebenchmark)
|
||||||
|
|
||||||
|
set(ChaosBenches_SOURCE BenchmarkMain.cpp
|
||||||
|
Hash/Md4HasherBenches.cpp
|
||||||
|
Hash/Md5HasherBenches.cpp
|
||||||
|
Hash/Sha1HasherBenches.cpp
|
||||||
|
Mac/HmacBenches.cpp)
|
||||||
|
|
||||||
|
add_executable(ChaosBenches ${ChaosBenches_SOURCE})
|
||||||
|
target_link_libraries(ChaosBenches benchmark::benchmark)
|
||||||
|
target_include_directories(ChaosBenches PRIVATE
|
||||||
|
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/Chaos>
|
||||||
|
)
|
||||||
65
ChaosBenches/Hash/Md4HasherBenches.cpp
Normal file
65
ChaosBenches/Hash/Md4HasherBenches.cpp
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#include <benchmark/benchmark.h>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include <Hash/Md4.hpp>
|
||||||
|
|
||||||
|
using namespace Chaos::Hash::Md4;
|
||||||
|
|
||||||
|
static const char * DATA_BEGIN
|
||||||
|
= "All states, all powers, that have held and hold rule over men have been and are either republics or principalities.\n"
|
||||||
|
"Principalities are either hereditary, in which the family has been long established; or they are new.\n"
|
||||||
|
"The new are either entirely new, as was Milan to Francesco Sforza, or they are, as it were, members annexed to the hereditary state of the "
|
||||||
|
"prince who has acquired them, as was the kingdom of Naples to that of the King of Spain.\n"
|
||||||
|
"Such dominions thus acquired are either accustomed to live under a prince, or to live in freedom; and are acquired either by the arms of the "
|
||||||
|
"prince himself, or of others, or else by fortune or by ability.";
|
||||||
|
static const size_t DATA_LEN = strlen(DATA_BEGIN);
|
||||||
|
static const char * DATA_END = DATA_BEGIN + DATA_LEN;
|
||||||
|
|
||||||
|
static void Md4Hasher_CreateComputeDeleteBench(benchmark::State & state)
|
||||||
|
{
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
Md4Hasher hasher;
|
||||||
|
hasher.Update(DATA_BEGIN, DATA_END);
|
||||||
|
Md4Hash result = hasher.Finish();
|
||||||
|
|
||||||
|
benchmark::DoNotOptimize(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(Md4Hasher_CreateComputeDeleteBench);
|
||||||
|
|
||||||
|
static void Md4Hasher_ReuseBench(benchmark::State & state)
|
||||||
|
{
|
||||||
|
Md4Hasher hasher;
|
||||||
|
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
hasher.Reset();
|
||||||
|
hasher.Update(DATA_BEGIN, DATA_END);
|
||||||
|
Md4Hash result = hasher.Finish();
|
||||||
|
|
||||||
|
benchmark::DoNotOptimize(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(Md4Hasher_ReuseBench);
|
||||||
|
|
||||||
|
static void Md4Hasher_PartialUpdate100Bench(benchmark::State & state)
|
||||||
|
{
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
Md4Hasher hasher;
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; ++i)
|
||||||
|
{
|
||||||
|
hasher.Update(DATA_BEGIN, DATA_END);
|
||||||
|
}
|
||||||
|
|
||||||
|
Md4Hash result = hasher.Finish();
|
||||||
|
|
||||||
|
benchmark::DoNotOptimize(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(Md4Hasher_PartialUpdate100Bench);
|
||||||
65
ChaosBenches/Hash/Md5HasherBenches.cpp
Normal file
65
ChaosBenches/Hash/Md5HasherBenches.cpp
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#include <benchmark/benchmark.h>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include <Hash/Md5.hpp>
|
||||||
|
|
||||||
|
using namespace Chaos::Hash::Md5;
|
||||||
|
|
||||||
|
static const char * DATA_BEGIN
|
||||||
|
= "All states, all powers, that have held and hold rule over men have been and are either republics or principalities.\n"
|
||||||
|
"Principalities are either hereditary, in which the family has been long established; or they are new.\n"
|
||||||
|
"The new are either entirely new, as was Milan to Francesco Sforza, or they are, as it were, members annexed to the hereditary state of the "
|
||||||
|
"prince who has acquired them, as was the kingdom of Naples to that of the King of Spain.\n"
|
||||||
|
"Such dominions thus acquired are either accustomed to live under a prince, or to live in freedom; and are acquired either by the arms of the "
|
||||||
|
"prince himself, or of others, or else by fortune or by ability.";
|
||||||
|
static const size_t DATA_LEN = strlen(DATA_BEGIN);
|
||||||
|
static const char * DATA_END = DATA_BEGIN + DATA_LEN;
|
||||||
|
|
||||||
|
static void Md5Hasher_CreateComputeDeleteBench(benchmark::State & state)
|
||||||
|
{
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
Md5Hasher hasher;
|
||||||
|
hasher.Update(DATA_BEGIN, DATA_END);
|
||||||
|
Md5Hash result = hasher.Finish();
|
||||||
|
|
||||||
|
benchmark::DoNotOptimize(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(Md5Hasher_CreateComputeDeleteBench);
|
||||||
|
|
||||||
|
static void Md5Hasher_ReuseBench(benchmark::State & state)
|
||||||
|
{
|
||||||
|
Md5Hasher hasher;
|
||||||
|
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
hasher.Reset();
|
||||||
|
hasher.Update(DATA_BEGIN, DATA_END);
|
||||||
|
Md5Hash result = hasher.Finish();
|
||||||
|
|
||||||
|
benchmark::DoNotOptimize(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(Md5Hasher_ReuseBench);
|
||||||
|
|
||||||
|
static void Md5Hasher_PartialUpdate100Bench(benchmark::State & state)
|
||||||
|
{
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
Md5Hasher hasher;
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; ++i)
|
||||||
|
{
|
||||||
|
hasher.Update(DATA_BEGIN, DATA_END);
|
||||||
|
}
|
||||||
|
|
||||||
|
Md5Hash result = hasher.Finish();
|
||||||
|
|
||||||
|
benchmark::DoNotOptimize(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(Md5Hasher_PartialUpdate100Bench);
|
||||||
65
ChaosBenches/Hash/Sha1HasherBenches.cpp
Normal file
65
ChaosBenches/Hash/Sha1HasherBenches.cpp
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#include <benchmark/benchmark.h>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include <Hash/Sha1.hpp>
|
||||||
|
|
||||||
|
using namespace Chaos::Hash::Sha1;
|
||||||
|
|
||||||
|
static const char * DATA_BEGIN
|
||||||
|
= "All states, all powers, that have held and hold rule over men have been and are either republics or principalities.\n"
|
||||||
|
"Principalities are either hereditary, in which the family has been long established; or they are new.\n"
|
||||||
|
"The new are either entirely new, as was Milan to Francesco Sforza, or they are, as it were, members annexed to the hereditary state of the "
|
||||||
|
"prince who has acquired them, as was the kingdom of Naples to that of the King of Spain.\n"
|
||||||
|
"Such dominions thus acquired are either accustomed to live under a prince, or to live in freedom; and are acquired either by the arms of the "
|
||||||
|
"prince himself, or of others, or else by fortune or by ability.";
|
||||||
|
static const size_t DATA_LEN = strlen(DATA_BEGIN);
|
||||||
|
static const char * DATA_END = DATA_BEGIN + DATA_LEN;
|
||||||
|
|
||||||
|
static void Sha1Hasher_CreateComputeDeleteBench(benchmark::State & state)
|
||||||
|
{
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
Sha1Hasher hasher;
|
||||||
|
hasher.Update(DATA_BEGIN, DATA_END);
|
||||||
|
Sha1Hash result = hasher.Finish();
|
||||||
|
|
||||||
|
benchmark::DoNotOptimize(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(Sha1Hasher_CreateComputeDeleteBench);
|
||||||
|
|
||||||
|
static void Sha1Hasher_ReuseBench(benchmark::State & state)
|
||||||
|
{
|
||||||
|
Sha1Hasher hasher;
|
||||||
|
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
hasher.Reset();
|
||||||
|
hasher.Update(DATA_BEGIN, DATA_END);
|
||||||
|
Sha1Hash result = hasher.Finish();
|
||||||
|
|
||||||
|
benchmark::DoNotOptimize(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(Sha1Hasher_ReuseBench);
|
||||||
|
|
||||||
|
static void Sha1Hasher_PartialUpdate100Bench(benchmark::State & state)
|
||||||
|
{
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
Sha1Hasher hasher;
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; ++i)
|
||||||
|
{
|
||||||
|
hasher.Update(DATA_BEGIN, DATA_END);
|
||||||
|
}
|
||||||
|
|
||||||
|
Sha1Hash result = hasher.Finish();
|
||||||
|
|
||||||
|
benchmark::DoNotOptimize(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(Sha1Hasher_PartialUpdate100Bench);
|
||||||
173
ChaosBenches/Mac/HmacBenches.cpp
Normal file
173
ChaosBenches/Mac/HmacBenches.cpp
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
#include <benchmark/benchmark.h>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "Mac/Hmac.hpp"
|
||||||
|
#include "Hash/Md4.hpp"
|
||||||
|
#include "Hash/Md5.hpp"
|
||||||
|
#include "Hash/Sha1.hpp"
|
||||||
|
|
||||||
|
using namespace Chaos::Mac::Hmac;
|
||||||
|
using namespace Chaos::Hash::Md4;
|
||||||
|
using namespace Chaos::Hash::Md5;
|
||||||
|
using namespace Chaos::Hash::Sha1;
|
||||||
|
|
||||||
|
static const char * KEY_BEGIN = "Niccolo01234567";
|
||||||
|
static const size_t KEY_LEN = strlen(KEY_BEGIN);
|
||||||
|
static const char * KEY_END = KEY_BEGIN + KEY_LEN;
|
||||||
|
|
||||||
|
static const char * DATA_BEGIN
|
||||||
|
= "All states, all powers, that have held and hold rule over men have been and are either republics or principalities.\n"
|
||||||
|
"Principalities are either hereditary, in which the family has been long established; or they are new.\n"
|
||||||
|
"The new are either entirely new, as was Milan to Francesco Sforza, or they are, as it were, members annexed to the hereditary state of the "
|
||||||
|
"prince who has acquired them, as was the kingdom of Naples to that of the King of Spain.\n"
|
||||||
|
"Such dominions thus acquired are either accustomed to live under a prince, or to live in freedom; and are acquired either by the arms of the "
|
||||||
|
"prince himself, or of others, or else by fortune or by ability.";
|
||||||
|
static const size_t DATA_LEN = strlen(DATA_BEGIN);
|
||||||
|
static const char * DATA_END = DATA_BEGIN + DATA_LEN;
|
||||||
|
|
||||||
|
static void HmacMd4_CreateComputeDeleteBench(benchmark::State & state)
|
||||||
|
{
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
Hmac<Md4Hasher> hmac(KEY_BEGIN, KEY_END);
|
||||||
|
hmac.Update(DATA_BEGIN, DATA_END);
|
||||||
|
Md4Hash result = hmac.Finish();
|
||||||
|
|
||||||
|
benchmark::DoNotOptimize(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(HmacMd4_CreateComputeDeleteBench);
|
||||||
|
|
||||||
|
static void HmacMd4_ReuseBench(benchmark::State & state)
|
||||||
|
{
|
||||||
|
Hmac<Md4Hasher> hmac;
|
||||||
|
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
hmac.Rekey(KEY_BEGIN, KEY_END);
|
||||||
|
hmac.Update(DATA_BEGIN, DATA_END);
|
||||||
|
Md4Hash result = hmac.Finish();
|
||||||
|
|
||||||
|
benchmark::DoNotOptimize(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(HmacMd4_ReuseBench);
|
||||||
|
|
||||||
|
static void HmacMd4_PartialUpdate100Bench(benchmark::State & state)
|
||||||
|
{
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
Hmac<Md4Hasher> hmac(KEY_BEGIN, KEY_END);
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; ++i)
|
||||||
|
{
|
||||||
|
hmac.Update(DATA_BEGIN, DATA_END);
|
||||||
|
}
|
||||||
|
|
||||||
|
Md4Hash result = hmac.Finish();
|
||||||
|
|
||||||
|
benchmark::DoNotOptimize(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(HmacMd4_PartialUpdate100Bench);
|
||||||
|
|
||||||
|
static void HmacMd5_CreateComputeDeleteBench(benchmark::State & state)
|
||||||
|
{
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
Hmac<Md5Hasher> hmac(KEY_BEGIN, KEY_END);
|
||||||
|
hmac.Update(DATA_BEGIN, DATA_END);
|
||||||
|
Md5Hash result = hmac.Finish();
|
||||||
|
|
||||||
|
benchmark::DoNotOptimize(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(HmacMd5_CreateComputeDeleteBench);
|
||||||
|
|
||||||
|
static void HmacMd5_ReuseBench(benchmark::State & state)
|
||||||
|
{
|
||||||
|
Hmac<Md5Hasher> hmac;
|
||||||
|
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
hmac.Rekey(KEY_BEGIN, KEY_END);
|
||||||
|
hmac.Update(DATA_BEGIN, DATA_END);
|
||||||
|
Md5Hash result = hmac.Finish();
|
||||||
|
|
||||||
|
benchmark::DoNotOptimize(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(HmacMd5_ReuseBench);
|
||||||
|
|
||||||
|
static void HmacMd5_PartialUpdate100Bench(benchmark::State & state)
|
||||||
|
{
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
Hmac<Md5Hasher> hmac(KEY_BEGIN, KEY_END);
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; ++i)
|
||||||
|
{
|
||||||
|
hmac.Update(DATA_BEGIN, DATA_END);
|
||||||
|
}
|
||||||
|
|
||||||
|
Md5Hash result = hmac.Finish();
|
||||||
|
|
||||||
|
benchmark::DoNotOptimize(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(HmacMd5_PartialUpdate100Bench);
|
||||||
|
|
||||||
|
static void HmacSha1_CreateComputeDeleteBench(benchmark::State & state)
|
||||||
|
{
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
Hmac<Sha1Hasher> hmac(KEY_BEGIN, KEY_END);
|
||||||
|
hmac.Update(DATA_BEGIN, DATA_END);
|
||||||
|
Sha1Hash result = hmac.Finish();
|
||||||
|
|
||||||
|
benchmark::DoNotOptimize(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(HmacSha1_CreateComputeDeleteBench);
|
||||||
|
|
||||||
|
static void HmacSha1_ReuseBench(benchmark::State & state)
|
||||||
|
{
|
||||||
|
Hmac<Sha1Hasher> hmac;
|
||||||
|
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
hmac.Rekey(KEY_BEGIN, KEY_END);
|
||||||
|
hmac.Update(DATA_BEGIN, DATA_END);
|
||||||
|
Sha1Hash result = hmac.Finish();
|
||||||
|
|
||||||
|
benchmark::DoNotOptimize(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(HmacSha1_ReuseBench);
|
||||||
|
|
||||||
|
static void HmacSha1_PartialUpdate100Bench(benchmark::State & state)
|
||||||
|
{
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
Hmac<Sha1Hasher> hmac(KEY_BEGIN, KEY_END);
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; ++i)
|
||||||
|
{
|
||||||
|
hmac.Update(DATA_BEGIN, DATA_END);
|
||||||
|
}
|
||||||
|
|
||||||
|
Sha1Hash result = hmac.Finish();
|
||||||
|
|
||||||
|
benchmark::DoNotOptimize(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(HmacSha1_PartialUpdate100Bench);
|
||||||
@@ -4,7 +4,7 @@ cmake_policy(SET CMP0135 NEW)
|
|||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
googletest
|
googletest
|
||||||
URL https://github.com/google/googletest/releases/download/v1.17.0/googletest-1.17.0.tar.gz
|
URL https://git.hashlag.net/hashlag/chaos-deps/raw/branch/main/google_googletest/googletest-1.17.0.tar.gz
|
||||||
URL_HASH SHA256=65fab701d9829d38cb77c14acdc431d2108bfdbf8979e40eb8ae567edf10b27c
|
URL_HASH SHA256=65fab701d9829d38cb77c14acdc431d2108bfdbf8979e40eb8ae567edf10b27c
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -17,7 +17,9 @@ set(ChaosTests_SOURCE Hash/Md4HasherTests.cpp
|
|||||||
Mac/HmacTests.cpp
|
Mac/HmacTests.cpp
|
||||||
Cipher/Arc4GenTests.cpp
|
Cipher/Arc4GenTests.cpp
|
||||||
Cipher/Arc4CryptTests.cpp
|
Cipher/Arc4CryptTests.cpp
|
||||||
Service/SeArrayTests.cpp)
|
Cipher/DesCryptTests.cpp
|
||||||
|
Service/SeArrayTests.cpp
|
||||||
|
Service/ChaosExceptionTests.cpp)
|
||||||
|
|
||||||
add_executable(ChaosTests ${ChaosTests_SOURCE})
|
add_executable(ChaosTests ${ChaosTests_SOURCE})
|
||||||
target_link_libraries(ChaosTests gtest gtest_main)
|
target_link_libraries(ChaosTests gtest gtest_main)
|
||||||
@@ -25,6 +27,13 @@ target_include_directories(ChaosTests PRIVATE
|
|||||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/Chaos>
|
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/Chaos>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
target_compile_options(ChaosTests PRIVATE -Wunused -Werror=unused)
|
||||||
|
|
||||||
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
|
target_compile_options(ChaosTests PRIVATE --coverage)
|
||||||
|
target_link_options(ChaosTests PRIVATE --coverage)
|
||||||
|
endif()
|
||||||
|
|
||||||
include(GoogleTest)
|
include(GoogleTest)
|
||||||
|
|
||||||
gtest_discover_tests(ChaosTests)
|
gtest_discover_tests(ChaosTests)
|
||||||
|
|||||||
@@ -58,11 +58,8 @@ TEST(Arc4CryptTests, UninitializedArc4CryptTest)
|
|||||||
Arc4Crypt arc4;
|
Arc4Crypt arc4;
|
||||||
|
|
||||||
{
|
{
|
||||||
std::array<uint8_t, 10> in;
|
std::array<uint8_t, 10> in = {};
|
||||||
in.fill(0);
|
std::array<uint8_t, 10> out = {};
|
||||||
|
|
||||||
std::array<uint8_t, 10> out;
|
|
||||||
out.fill(0);
|
|
||||||
|
|
||||||
ASSERT_THROW(arc4.Encrypt(out.begin(), in.begin(), in.size()), Chaos::Service::ChaosException);
|
ASSERT_THROW(arc4.Encrypt(out.begin(), in.begin(), in.size()), Chaos::Service::ChaosException);
|
||||||
ASSERT_THROW(arc4.Decrypt(out.begin(), in.begin(), in.size()), Chaos::Service::ChaosException);
|
ASSERT_THROW(arc4.Decrypt(out.begin(), in.begin(), in.size()), Chaos::Service::ChaosException);
|
||||||
@@ -107,3 +104,115 @@ TEST(Arc4CryptTests, RekeyTest)
|
|||||||
ciphertext);
|
ciphertext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Arc4CryptTests, EncryptOutIteratorUsageTest)
|
||||||
|
{
|
||||||
|
const std::vector<uint8_t> data = StrToU8Vec("The quick brown fox jumps over the lazy dog.");
|
||||||
|
|
||||||
|
{
|
||||||
|
std::array<uint8_t, 5> key = { 0x01, 0x02, 0x03, 0x04, 0x05 };
|
||||||
|
|
||||||
|
Arc4Crypt crypt(key.begin(), key.end());
|
||||||
|
|
||||||
|
std::array<uint8_t, 47> out = {};
|
||||||
|
|
||||||
|
std::array<uint8_t, 47> expected =
|
||||||
|
{
|
||||||
|
0x00, 0x00, 0x00,
|
||||||
|
0xe6, 0x51, 0x06, 0x25, 0x81, 0x48, 0xa9, 0x44, 0xa7, 0xe3, 0x30,
|
||||||
|
0x38, 0x65, 0x66, 0x76, 0x88, 0x0f, 0xed, 0xec, 0x6f, 0x72, 0x89,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
crypt.Encrypt(out.begin() + 3, data.begin(), 22);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::array<uint8_t, 5> key = { 0x01, 0x02, 0x03, 0x04, 0x05 };
|
||||||
|
|
||||||
|
Arc4Crypt crypt(key.begin(), key.end());
|
||||||
|
|
||||||
|
std::array<uint8_t, 47> out = {};
|
||||||
|
|
||||||
|
std::array<uint8_t, 47> expected =
|
||||||
|
{
|
||||||
|
0x00, 0x00, 0x00,
|
||||||
|
0xe6, 0x51, 0x06, 0x25, 0x81, 0x48, 0xa9, 0x44, 0xa7, 0xe3, 0x30,
|
||||||
|
0x38, 0x65, 0x66, 0x76, 0x88, 0x0f, 0xed, 0xec, 0x6f, 0x72, 0x89,
|
||||||
|
0xef, 0xa5, 0xfa, 0xe4, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
crypt.Encrypt(out.begin() + 3, data.begin(), 27);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::array<uint8_t, 5> key = { 0x01, 0x02, 0x03, 0x04, 0x05 };
|
||||||
|
|
||||||
|
Arc4Crypt crypt(key.begin(), key.end());
|
||||||
|
|
||||||
|
std::array<uint8_t, 44> out = {};
|
||||||
|
std::array<uint8_t, 44> expected = {};
|
||||||
|
|
||||||
|
crypt.Encrypt(out.begin() + 3, data.begin(), 0);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Arc4CryptTests, DecryptOutIteratorUsageTest)
|
||||||
|
{
|
||||||
|
const std::array<uint8_t, 14> data = { 0x45, 0xA0, 0x1F, 0x64, 0x5F, 0xC3, 0x5B,
|
||||||
|
0x38, 0x35, 0x52, 0x54, 0x4B, 0x9B, 0xF5 };
|
||||||
|
const std::vector<uint8_t> key = StrToU8Vec("Secret");
|
||||||
|
|
||||||
|
{
|
||||||
|
Arc4Crypt crypt(key.begin(), key.end());
|
||||||
|
|
||||||
|
std::array<uint8_t, 17> out = {};
|
||||||
|
|
||||||
|
std::array<uint8_t, 17> expected =
|
||||||
|
{
|
||||||
|
0x00, 0x00, 0x00,
|
||||||
|
'A', 't', 't', 'a', 'c', 'k', ' ', 'a', 't', ' ', 'd', 'a',
|
||||||
|
0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
crypt.Decrypt(out.begin() + 3, data.begin(), 12);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Arc4Crypt crypt(key.begin(), key.end());
|
||||||
|
|
||||||
|
std::array<uint8_t, 17> out = {};
|
||||||
|
|
||||||
|
std::array<uint8_t, 17> expected =
|
||||||
|
{
|
||||||
|
0x00, 0x00, 0x00,
|
||||||
|
'A', 't', 't', 'a', 'c', 'k', ' ',
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
crypt.Decrypt(out.begin() + 3, data.begin(), 7);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Arc4Crypt crypt(key.begin(), key.end());
|
||||||
|
|
||||||
|
std::array<uint8_t, 14> out = {};
|
||||||
|
std::array<uint8_t, 14> expected = {};
|
||||||
|
|
||||||
|
crypt.Decrypt(out.begin() + 3, data.begin(), 0);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -353,3 +353,56 @@ TEST(Arc4GenTests, UninitializedGenTest)
|
|||||||
ASSERT_THROW(gen.Drop(256), Chaos::Service::ChaosException);
|
ASSERT_THROW(gen.Drop(256), Chaos::Service::ChaosException);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Arc4GenTests, GenerateOutIteratorUsageTest)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
uint8_t key[] = { 0x01, 0x02, 0x03, 0x04, 0x05 };
|
||||||
|
Arc4Gen gen(key, key + std::size(key));
|
||||||
|
|
||||||
|
std::array<uint8_t, 23> out = {};
|
||||||
|
|
||||||
|
std::array<uint8_t, 23> expected =
|
||||||
|
{
|
||||||
|
0x00, 0x00, 0x00,
|
||||||
|
0xb2, 0x39, 0x63, 0x05, 0xf0, 0x3d, 0xc0, 0x27,
|
||||||
|
0xcc, 0xc3, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
gen.Generate(out.begin() + 3, 11);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
uint8_t key[] = { 0x01, 0x02, 0x03, 0x04, 0x05 };
|
||||||
|
Arc4Gen gen(key, key + std::size(key));
|
||||||
|
|
||||||
|
std::array<uint8_t, 23> out = {};
|
||||||
|
|
||||||
|
std::array<uint8_t, 23> expected =
|
||||||
|
{
|
||||||
|
0x00, 0x00, 0x00,
|
||||||
|
0xb2, 0x39, 0x63, 0x05, 0xf0, 0x3d, 0xc0, 0x27,
|
||||||
|
0xcc, 0xc3, 0x52, 0x4a, 0x0a, 0x11, 0x18, 0xa8,
|
||||||
|
0x69, 0x82, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
gen.Generate(out.begin() + 3, 18);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
uint8_t key[] = { 0x01, 0x02, 0x03, 0x04, 0x05 };
|
||||||
|
Arc4Gen gen(key, key + std::size(key));
|
||||||
|
|
||||||
|
std::array<uint8_t, 20> out = {};
|
||||||
|
std::array<uint8_t, 20> expected = {};
|
||||||
|
|
||||||
|
gen.Generate(out.begin() + 3, 0);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
554
ChaosTests/Cipher/DesCryptTests.cpp
Normal file
554
ChaosTests/Cipher/DesCryptTests.cpp
Normal file
@@ -0,0 +1,554 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "Cipher/Block/Des/DesCrypt.hpp"
|
||||||
|
#include "Cipher/Block/Encryptor.hpp"
|
||||||
|
|
||||||
|
using namespace Chaos::Cipher::Block::Des;
|
||||||
|
using namespace Chaos::Cipher::Block;
|
||||||
|
|
||||||
|
TEST(DesCryptTests, KeyScheduleTest)
|
||||||
|
{
|
||||||
|
Inner_::RawKey key;
|
||||||
|
|
||||||
|
key[0] = 0b00010011;
|
||||||
|
key[1] = 0b00110100;
|
||||||
|
key[2] = 0b01010111;
|
||||||
|
key[3] = 0b01111001;
|
||||||
|
key[4] = 0b10011011;
|
||||||
|
key[5] = 0b10111100;
|
||||||
|
key[6] = 0b11011111;
|
||||||
|
key[7] = 0b11110001;
|
||||||
|
|
||||||
|
Inner_::KeySchedule schedule(Inner_::KeySchedule::Direction::Encrypt, key);
|
||||||
|
|
||||||
|
ASSERT_EQ(0b000110110000001011101111111111000111000001110010ULL, schedule[0]);
|
||||||
|
ASSERT_EQ(0b011110011010111011011001110110111100100111100101ULL, schedule[1]);
|
||||||
|
ASSERT_EQ(0b010101011111110010001010010000101100111110011001ULL, schedule[2]);
|
||||||
|
ASSERT_EQ(0b011100101010110111010110110110110011010100011101ULL, schedule[3]);
|
||||||
|
ASSERT_EQ(0b011111001110110000000111111010110101001110101000ULL, schedule[4]);
|
||||||
|
ASSERT_EQ(0b011000111010010100111110010100000111101100101111ULL, schedule[5]);
|
||||||
|
ASSERT_EQ(0b111011001000010010110111111101100001100010111100ULL, schedule[6]);
|
||||||
|
ASSERT_EQ(0b111101111000101000111010110000010011101111111011ULL, schedule[7]);
|
||||||
|
ASSERT_EQ(0b111000001101101111101011111011011110011110000001ULL, schedule[8]);
|
||||||
|
ASSERT_EQ(0b101100011111001101000111101110100100011001001111ULL, schedule[9]);
|
||||||
|
ASSERT_EQ(0b001000010101111111010011110111101101001110000110ULL, schedule[10]);
|
||||||
|
ASSERT_EQ(0b011101010111000111110101100101000110011111101001ULL, schedule[11]);
|
||||||
|
ASSERT_EQ(0b100101111100010111010001111110101011101001000001ULL, schedule[12]);
|
||||||
|
ASSERT_EQ(0b010111110100001110110111111100101110011100111010ULL, schedule[13]);
|
||||||
|
ASSERT_EQ(0b101111111001000110001101001111010011111100001010ULL, schedule[14]);
|
||||||
|
ASSERT_EQ(0b110010110011110110001011000011100001011111110101ULL, schedule[15]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DesCryptTests, EncryptTest)
|
||||||
|
{
|
||||||
|
struct Helper
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize> operator()(const std::array<uint8_t, DesCrypt::BlockSize> & data,
|
||||||
|
const std::array<uint8_t, DesCrypt::KeySize> & key) const
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize> result = {};
|
||||||
|
|
||||||
|
DesCrypt::Key desKey(key.begin(), key.end());
|
||||||
|
DesCrypt::DesEncryptor enc(desKey);
|
||||||
|
enc.EncryptBlock(result.begin(), result.end(), data.begin(), data.end());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Helper des;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize> data = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0x13, 0x34, 0x57, 0x79, 0x9b, 0xbc, 0xdf, 0xf1 };
|
||||||
|
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize> expected = { 0x85, 0xe8, 0x13, 0x54, 0x0f, 0x0a, 0xb4, 0x05 };
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, des(data, key));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize> data = { 0xaa, 0xf3, 0x83, 0x16, 0x2d, 0x2e, 0x6b, 0xcb };
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0x44, 0xbf, 0x32, 0x19, 0x99, 0x25, 0x81, 0x51 };
|
||||||
|
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize> expected = { 0x07, 0xe8, 0x7f, 0xaa, 0xb3, 0x17, 0x13, 0x18 };
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, des(data, key));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize> data = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0xa7, 0x93, 0x44 };
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
|
||||||
|
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize> expected = { 0x42, 0x27, 0x88, 0xa6, 0x7b, 0x6c, 0x18, 0xed };
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, des(data, key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DesCryptTests, EncryptUInt64BlockTest)
|
||||||
|
{
|
||||||
|
struct Helper
|
||||||
|
{
|
||||||
|
uint64_t operator()(uint64_t data,
|
||||||
|
const std::array<uint8_t, DesCrypt::KeySize> & key) const
|
||||||
|
{
|
||||||
|
DesCrypt::Key desKey(key.begin(), key.end());
|
||||||
|
DesCrypt::DesEncryptor enc(desKey);
|
||||||
|
|
||||||
|
return enc.EncryptBlock(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Helper des;
|
||||||
|
|
||||||
|
{
|
||||||
|
uint64_t data = 0x0123456789abcdef;
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0x13, 0x34, 0x57, 0x79, 0x9b, 0xbc, 0xdf, 0xf1 };
|
||||||
|
|
||||||
|
uint64_t expected = 0x85e813540f0ab405;
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, des(data, key));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
uint64_t data = 0xaaf383162d2e6bcb;
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0x44, 0xbf, 0x32, 0x19, 0x99, 0x25, 0x81, 0x51 };
|
||||||
|
|
||||||
|
uint64_t expected = 0x07e87faab3171318;
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, des(data, key));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
uint64_t data = 0xe51a9fd419a79344;
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
|
||||||
|
|
||||||
|
uint64_t expected = 0x422788a67b6c18ed;
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, des(data, key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DesCryptTests, EncryptShortDataTest)
|
||||||
|
{
|
||||||
|
struct Helper
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> operator()(const std::vector<uint8_t> & data,
|
||||||
|
const std::vector<uint8_t> & key)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> result;
|
||||||
|
result.resize(DesCrypt::BlockSize, 0);
|
||||||
|
|
||||||
|
DesCrypt::Key desKey(key.begin(), key.end());
|
||||||
|
DesCrypt::DesEncryptor enc(desKey);
|
||||||
|
enc.EncryptBlock(result.begin(), result.end(), data.begin(), data.end());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Helper des;
|
||||||
|
|
||||||
|
{
|
||||||
|
// treated as { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0x00, 0x00, 0x00 }
|
||||||
|
std::vector<uint8_t> dataShort = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19 };
|
||||||
|
|
||||||
|
std::vector<uint8_t> data = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0x00, 0x00, 0x00 };
|
||||||
|
std::vector<uint8_t> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
|
||||||
|
|
||||||
|
std::vector<uint8_t> expected = { 0xd8, 0xa8, 0xb8, 0xb4, 0xc0, 0x9b, 0x04, 0x09 };
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, des(data, key));
|
||||||
|
ASSERT_EQ(expected, des(dataShort, key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DesCryptTests, EncryptLongDataTest)
|
||||||
|
{
|
||||||
|
struct Helper
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> operator()(const std::vector<uint8_t> & data,
|
||||||
|
const std::vector<uint8_t> & key)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> result;
|
||||||
|
result.resize(DesCrypt::BlockSize, 0);
|
||||||
|
|
||||||
|
DesCrypt::Key desKey(key.begin(), key.end());
|
||||||
|
DesCrypt::DesEncryptor enc(desKey);
|
||||||
|
enc.EncryptBlock(result.begin(), result.end(), data.begin(), data.end());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Helper des;
|
||||||
|
|
||||||
|
{
|
||||||
|
// treated as { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0xa7, 0x93, 0x44 }
|
||||||
|
std::vector<uint8_t> dataLong = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0xa7, 0x93, 0x44, 0xaa, 0xbb };
|
||||||
|
|
||||||
|
std::vector<uint8_t> data = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0xa7, 0x93, 0x44 };
|
||||||
|
std::vector<uint8_t> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
|
||||||
|
|
||||||
|
std::vector<uint8_t> expected = { 0x42, 0x27, 0x88, 0xa6, 0x7b, 0x6c, 0x18, 0xed };
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, des(data, key));
|
||||||
|
ASSERT_EQ(expected, des(dataLong, key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DesCryptTests, DecryptTest)
|
||||||
|
{
|
||||||
|
struct Helper
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize> operator()(const std::array<uint8_t, DesCrypt::BlockSize> & data,
|
||||||
|
const std::array<uint8_t, DesCrypt::KeySize> & key) const
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize> result = {};
|
||||||
|
|
||||||
|
DesCrypt::Key desKey(key.begin(), key.end());
|
||||||
|
DesCrypt::DesDecryptor dec(desKey);
|
||||||
|
dec.DecryptBlock(result.begin(), result.end(), data.begin(), data.end());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Helper des;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize> data = { 0x85, 0xe8, 0x13, 0x54, 0x0f, 0x0a, 0xb4, 0x05 };
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0x13, 0x34, 0x57, 0x79, 0x9b, 0xbc, 0xdf, 0xf1 };
|
||||||
|
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize> expected = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, des(data, key));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize> data = { 0x07, 0xe8, 0x7f, 0xaa, 0xb3, 0x17, 0x13, 0x18 };
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0x44, 0xbf, 0x32, 0x19, 0x99, 0x25, 0x81, 0x51 };
|
||||||
|
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize> expected = { 0xaa, 0xf3, 0x83, 0x16, 0x2d, 0x2e, 0x6b, 0xcb };
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, des(data, key));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize> data = { 0x42, 0x27, 0x88, 0xa6, 0x7b, 0x6c, 0x18, 0xed };
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
|
||||||
|
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize> expected = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0xa7, 0x93, 0x44 };
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, des(data, key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DesCryptTests, DecryptUInt64BlockTest)
|
||||||
|
{
|
||||||
|
struct Helper
|
||||||
|
{
|
||||||
|
uint64_t operator()(uint64_t data,
|
||||||
|
const std::array<uint8_t, DesCrypt::KeySize> & key) const
|
||||||
|
{
|
||||||
|
DesCrypt::Key desKey(key.begin(), key.end());
|
||||||
|
DesCrypt::DesDecryptor dec(desKey);
|
||||||
|
|
||||||
|
return dec.DecryptBlock(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Helper des;
|
||||||
|
|
||||||
|
{
|
||||||
|
uint64_t data = 0x85e813540f0ab405;
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0x13, 0x34, 0x57, 0x79, 0x9b, 0xbc, 0xdf, 0xf1 };
|
||||||
|
|
||||||
|
uint64_t expected = 0x0123456789abcdef;
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, des(data, key));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
uint64_t data = 0x07e87faab3171318;
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0x44, 0xbf, 0x32, 0x19, 0x99, 0x25, 0x81, 0x51 };
|
||||||
|
|
||||||
|
uint64_t expected = 0xaaf383162d2e6bcb;
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, des(data, key));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
uint64_t data = 0x422788a67b6c18ed;
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
|
||||||
|
|
||||||
|
uint64_t expected = 0xe51a9fd419a79344;
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, des(data, key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DesCryptTests, DecryptShortDataTest)
|
||||||
|
{
|
||||||
|
struct Helper
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> operator()(const std::vector<uint8_t> & data,
|
||||||
|
const std::vector<uint8_t> & key)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> result;
|
||||||
|
result.resize(DesCrypt::BlockSize, 0);
|
||||||
|
|
||||||
|
DesCrypt::Key desKey(key.begin(), key.end());
|
||||||
|
DesCrypt::DesDecryptor dec(desKey);
|
||||||
|
dec.DecryptBlock(result.begin(), result.end(), data.begin(), data.end());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Helper des;
|
||||||
|
|
||||||
|
{
|
||||||
|
// treated as { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0x00, 0x00, 0x00 }
|
||||||
|
std::vector<uint8_t> dataShort = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19 };
|
||||||
|
|
||||||
|
std::vector<uint8_t> data = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0x00, 0x00, 0x00 };
|
||||||
|
std::vector<uint8_t> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
|
||||||
|
|
||||||
|
std::vector<uint8_t> expected = { 0x90, 0xe5, 0xf6, 0x5b, 0xe1, 0xd3, 0x8a, 0x64 };
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, des(data, key));
|
||||||
|
ASSERT_EQ(expected, des(dataShort, key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DesCryptTests, DecryptLongDataTest)
|
||||||
|
{
|
||||||
|
struct Helper
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> operator()(const std::vector<uint8_t> & data,
|
||||||
|
const std::vector<uint8_t> & key)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> result;
|
||||||
|
result.resize(DesCrypt::BlockSize, 0);
|
||||||
|
|
||||||
|
DesCrypt::Key desKey(key.begin(), key.end());
|
||||||
|
DesCrypt::DesDecryptor dec(desKey);
|
||||||
|
dec.DecryptBlock(result.begin(), result.end(), data.begin(), data.end());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Helper des;
|
||||||
|
|
||||||
|
{
|
||||||
|
// treated as { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0xa7, 0x93, 0x44 }
|
||||||
|
std::vector<uint8_t> dataLong = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0xa7, 0x93, 0x44, 0xaa, 0xbb };
|
||||||
|
|
||||||
|
std::vector<uint8_t> data = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0xa7, 0x93, 0x44 };
|
||||||
|
std::vector<uint8_t> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
|
||||||
|
|
||||||
|
std::vector<uint8_t> expected = { 0x45, 0x69, 0x71, 0x17, 0x13, 0xfb, 0x3e, 0xee };
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, des(data, key));
|
||||||
|
ASSERT_EQ(expected, des(dataLong, key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DesCryptTests, ShortKeyTest)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize - 1> key = {};
|
||||||
|
ASSERT_THROW(DesCrypt::Key(key.begin(), key.end()), Chaos::Service::ChaosException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DesCryptTests, LongKeyTest)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize + 1> key = {};
|
||||||
|
ASSERT_THROW(DesCrypt::Key(key.begin(), key.end()), Chaos::Service::ChaosException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DesCryptTests, OutIteratorUsageEncryptTest)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize> data = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0xa7, 0x93, 0x44 };
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
|
||||||
|
|
||||||
|
std::array<uint8_t, 11> fact = {};
|
||||||
|
// First and last 3 bytes should be untouched.
|
||||||
|
std::array<uint8_t, 11> expected = { 0x00, 0x00, 0x00, 0x42, 0x27, 0x88, 0xa6, 0x7b, 0x00, 0x00, 0x00 };
|
||||||
|
|
||||||
|
DesCrypt::Key desKey(key.begin(), key.end());
|
||||||
|
DesCrypt::DesEncryptor enc(desKey);
|
||||||
|
enc.EncryptBlock(fact.begin() + 3, fact.end() - 3, data.begin(), data.end());
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, fact);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize + 2> data = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0xa7, 0x93, 0x44, 0x44, 0x44 };
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
|
||||||
|
|
||||||
|
std::array<uint8_t, 12> fact = {};
|
||||||
|
// First and last 4 bytes should be untouched.
|
||||||
|
std::array<uint8_t, 12> expected = { 0x00, 0x00, 0x00, 0x00, 0x42, 0x27, 0x88, 0xa6, 0x00, 0x00, 0x00, 0x00 };
|
||||||
|
|
||||||
|
DesCrypt::Key desKey(key.begin(), key.end());
|
||||||
|
DesCrypt::DesEncryptor enc(desKey);
|
||||||
|
enc.EncryptBlock(fact.begin() + 4, fact.end() - 4, data.begin(), data.end());
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, fact);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize + 2> data = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0xa7, 0x93, 0x44, 0x44, 0x44 };
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
|
||||||
|
|
||||||
|
std::array<uint8_t, 12> fact = {};
|
||||||
|
std::array<uint8_t, 12> expected = {};
|
||||||
|
|
||||||
|
DesCrypt::Key desKey(key.begin(), key.end());
|
||||||
|
DesCrypt::DesEncryptor enc(desKey);
|
||||||
|
enc.EncryptBlock(fact.begin() + 3, fact.begin() + 3, data.begin(), data.end());
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, fact);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DesCryptTests, OutIteratorUsageDecryptTest)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize> data = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0xa7, 0x93, 0x44 };
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
|
||||||
|
|
||||||
|
std::array<uint8_t, 11> fact = {};
|
||||||
|
// First and last 3 bytes should be untouched.
|
||||||
|
std::array<uint8_t, 11> expected = { 0x00, 0x00, 0x00, 0x45, 0x69, 0x71, 0x17, 0x13, 0x00, 0x00, 0x00 };
|
||||||
|
|
||||||
|
DesCrypt::Key desKey(key.begin(), key.end());
|
||||||
|
DesCrypt::DesDecryptor dec(desKey);
|
||||||
|
dec.DecryptBlock(fact.begin() + 3, fact.end() - 3, data.begin(), data.end());
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, fact);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize + 2> data = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0xa7, 0x93, 0x44, 0x44, 0x44 };
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
|
||||||
|
|
||||||
|
std::array<uint8_t, 12> fact = {};
|
||||||
|
// First and last 4 bytes should be untouched.
|
||||||
|
std::array<uint8_t, 12> expected = { 0x00, 0x00, 0x00, 0x00, 0x45, 0x69, 0x71, 0x17, 0x00, 0x00, 0x00, 0x00 };
|
||||||
|
|
||||||
|
DesCrypt::Key desKey(key.begin(), key.end());
|
||||||
|
DesCrypt::DesDecryptor dec(desKey);
|
||||||
|
dec.DecryptBlock(fact.begin() + 4, fact.end() - 4, data.begin(), data.end());
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, fact);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::BlockSize + 2> data = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0xa7, 0x93, 0x44, 0x44, 0x44 };
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
|
||||||
|
|
||||||
|
std::array<uint8_t, 12> fact = {};
|
||||||
|
std::array<uint8_t, 12> expected = {};
|
||||||
|
|
||||||
|
DesCrypt::Key desKey(key.begin(), key.end());
|
||||||
|
DesCrypt::DesDecryptor dec(desKey);
|
||||||
|
dec.DecryptBlock(fact.begin() + 3, fact.begin() + 3, data.begin(), data.end());
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, fact);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Impl, typename InputIt>
|
||||||
|
static std::vector<uint8_t> EncryptThroughBase(const Encryptor<Impl> & enc,
|
||||||
|
InputIt begin, InputIt end)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> result;
|
||||||
|
result.resize(enc.GetBlockSize(), 0);
|
||||||
|
|
||||||
|
enc.EncryptBlock(result.begin(), result.end(), begin, end);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DesCryptTests, EncryptThroughBaseTest)
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0x13, 0x34, 0x57, 0x79, 0x9b, 0xbc, 0xdf, 0xf1 };
|
||||||
|
|
||||||
|
std::vector<uint8_t> data = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
|
||||||
|
std::vector<uint8_t> expected = { 0x85, 0xe8, 0x13, 0x54, 0x0f, 0x0a, 0xb4, 0x05 };
|
||||||
|
|
||||||
|
DesCrypt::Key desKey(key.begin(), key.end());
|
||||||
|
DesCrypt::DesEncryptor enc(desKey);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, EncryptThroughBase(enc, data.begin(), data.end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Impl>
|
||||||
|
static uint64_t EncryptUInt64BlockThroughBase(const Encryptor<Impl> & enc, uint64_t block)
|
||||||
|
{
|
||||||
|
return enc.EncryptBlock(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DesCryptTests, EncryptUInt64BlockThroughBaseTest)
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0x13, 0x34, 0x57, 0x79, 0x9b, 0xbc, 0xdf, 0xf1 };
|
||||||
|
|
||||||
|
uint64_t data = 0x0123456789abcdef;
|
||||||
|
uint64_t expected = 0x85e813540f0ab405;
|
||||||
|
|
||||||
|
DesCrypt::Key desKey(key.begin(), key.end());
|
||||||
|
DesCrypt::DesEncryptor enc(desKey);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, EncryptUInt64BlockThroughBase(enc, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Impl, typename InputIt>
|
||||||
|
static std::vector<uint8_t> DecryptThroughBase(const Decryptor<Impl> & dec,
|
||||||
|
InputIt begin, InputIt end)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> result;
|
||||||
|
result.resize(dec.GetBlockSize(), 0);
|
||||||
|
|
||||||
|
dec.DecryptBlock(result.begin(), result.end(), begin, end);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DesCryptTests, DecryptThroughBaseTest)
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0x13, 0x34, 0x57, 0x79, 0x9b, 0xbc, 0xdf, 0xf1 };
|
||||||
|
|
||||||
|
std::vector<uint8_t> data = { 0x85, 0xe8, 0x13, 0x54, 0x0f, 0x0a, 0xb4, 0x05 };
|
||||||
|
std::vector<uint8_t> expected = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
|
||||||
|
|
||||||
|
DesCrypt::Key desKey(key.begin(), key.end());
|
||||||
|
DesCrypt::DesDecryptor dec(desKey);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, DecryptThroughBase(dec, data.begin(), data.end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Impl>
|
||||||
|
static uint64_t DecryptUInt64BlockThroughBase(const Decryptor<Impl> & dec, uint64_t block)
|
||||||
|
{
|
||||||
|
return dec.DecryptBlock(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DesCryptTests, DecryptUInt64BlockThroughBaseTest)
|
||||||
|
{
|
||||||
|
std::array<uint8_t, DesCrypt::KeySize> key = { 0x13, 0x34, 0x57, 0x79, 0x9b, 0xbc, 0xdf, 0xf1 };
|
||||||
|
|
||||||
|
uint64_t data = 0x85e813540f0ab405;
|
||||||
|
uint64_t expected = 0x0123456789abcdef;
|
||||||
|
|
||||||
|
DesCrypt::Key desKey(key.begin(), key.end());
|
||||||
|
DesCrypt::DesDecryptor dec(desKey);
|
||||||
|
|
||||||
|
ASSERT_EQ(expected, DecryptUInt64BlockThroughBase(dec, data));
|
||||||
|
}
|
||||||
@@ -116,6 +116,24 @@ TEST(Md4Tests, PartialUpdateTest)
|
|||||||
|
|
||||||
ASSERT_EQ("e33b4ddc9c38f2199c3e7b164fcc0536", hasher.Finish().ToHexString());
|
ASSERT_EQ("e33b4ddc9c38f2199c3e7b164fcc0536", hasher.Finish().ToHexString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Exactly 56 bytes.
|
||||||
|
// "01234567012345670123456701234567012345670123456701234567"
|
||||||
|
Md4Hasher hasher;
|
||||||
|
|
||||||
|
{
|
||||||
|
const char * in = "0123456701234567012345670";
|
||||||
|
hasher.Update(in, in + strlen(in));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const char * in = "1234567012345670123456701234567";
|
||||||
|
hasher.Update(in, in + strlen(in));
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_EQ("e058bdf6202bfa33ad91a03acc13dccd", hasher.Finish().ToHexString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Md4Tests, LongInputTest)
|
TEST(Md4Tests, LongInputTest)
|
||||||
|
|||||||
@@ -116,6 +116,24 @@ TEST(Md5Tests, PartialUpdateTest)
|
|||||||
|
|
||||||
ASSERT_EQ("57edf4a22be3c955ac49da2e2107b67a", hasher.Finish().ToHexString());
|
ASSERT_EQ("57edf4a22be3c955ac49da2e2107b67a", hasher.Finish().ToHexString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Exactly 56 bytes.
|
||||||
|
// "01234567012345670123456701234567012345670123456701234567"
|
||||||
|
Md5Hasher hasher;
|
||||||
|
|
||||||
|
{
|
||||||
|
const char * in = "0123456701234567012345670";
|
||||||
|
hasher.Update(in, in + strlen(in));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const char * in = "1234567012345670123456701234567";
|
||||||
|
hasher.Update(in, in + strlen(in));
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_EQ("19e80817ef026edb4791f2ea7dd80d5c", hasher.Finish().ToHexString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Md5Tests, LongInputTest)
|
TEST(Md5Tests, LongInputTest)
|
||||||
|
|||||||
@@ -116,6 +116,24 @@ TEST(Sha1Tests, PartialUpdateTest)
|
|||||||
|
|
||||||
ASSERT_EQ("50abf5706a150990a08b2c5ea40fa0e585554732", hasher.Finish().ToHexString());
|
ASSERT_EQ("50abf5706a150990a08b2c5ea40fa0e585554732", hasher.Finish().ToHexString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// > 56 (mod 64) bytes.
|
||||||
|
// "01234567012345670123456701234567012345670123456701234567012"
|
||||||
|
Sha1Hasher hasher;
|
||||||
|
|
||||||
|
{
|
||||||
|
const char * in = "0123456701234567012345670";
|
||||||
|
hasher.Update(in, in + strlen(in));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const char * in = "1234567012345670123456701234567012";
|
||||||
|
hasher.Update(in, in + strlen(in));
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_EQ("48a2aded798429970468e8aa77bdc1840dbca3fe", hasher.Finish().ToHexString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Sha1Tests, LongInputTest)
|
TEST(Sha1Tests, LongInputTest)
|
||||||
|
|||||||
@@ -99,8 +99,7 @@ TEST(HmacTests, LongKeyTest)
|
|||||||
|
|
||||||
TEST(HmacTests, UninitializedHmacTest)
|
TEST(HmacTests, UninitializedHmacTest)
|
||||||
{
|
{
|
||||||
std::array<uint8_t, 10> in;
|
std::array<uint8_t, 10> in = {};
|
||||||
in.fill(0);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
Hmac<Md5Hasher> hmac;
|
Hmac<Md5Hasher> hmac;
|
||||||
|
|||||||
32
ChaosTests/Service/ChaosExceptionTests.cpp
Normal file
32
ChaosTests/Service/ChaosExceptionTests.cpp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "Service/ChaosException.hpp"
|
||||||
|
|
||||||
|
using namespace Chaos::Service;
|
||||||
|
|
||||||
|
TEST(ChaosExceptionTests, RvalueRefCtorTest)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
throw ChaosException("everything's alright :D");
|
||||||
|
}
|
||||||
|
catch (const ChaosException & ex)
|
||||||
|
{
|
||||||
|
ASSERT_EQ("everything's alright :D", ex.GetMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ChaosExceptionTests, ConstLvalueRefCtorTest)
|
||||||
|
{
|
||||||
|
const std::string message = "everything's alright :D";
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
throw ChaosException(message);
|
||||||
|
}
|
||||||
|
catch (const ChaosException & ex)
|
||||||
|
{
|
||||||
|
ASSERT_EQ("everything's alright :D", ex.GetMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user