Compare commits

..

89 Commits

Author SHA1 Message Date
hashlag
797a5428cc Add Padder<>. A CRTP base for padding algorithms.
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m59s
2026-02-08 23:44:51 +03:00
hashlag
5baede0a1d Rename PadPkcs7 --> PadderPkcs7. 2026-02-08 23:31:24 +03:00
hashlag
2a3185406b Add PKCS#7 padding implementation.
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m58s
2026-02-08 23:05:57 +03:00
hashlag
0647a7c3dc DesEncryptor/DesDecryptor: expose key type.
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m57s
2026-02-08 02:57:00 +03:00
hashlag
7c86d704b7 Merge branch 'block-expose-key-size'
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m54s
Expose block ciphers' key sizes for usage in compile-time context.
2026-02-07 18:14:09 +03:00
hashlag
9f6265395d DesCryptTests: Replace magic const 8 (where used as the key length) with DesCrypt::KeySize.
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m51s
2026-02-07 18:09:42 +03:00
hashlag
151c93560c Expose DES key size through DesCrypt, DesCrypt::Encryptor, DesCrypt::Decryptor. 2026-02-07 18:02:27 +03:00
hashlag
3059bd4c66 Make SeArray::Size() static. 2026-02-07 17:54:37 +03:00
hashlag
ccf1397595 Merge branch 'exception-tests'
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m56s
Add missing ChaosException tests.
2026-02-06 18:18:45 +03:00
hashlag
6a09d81ae2 Add ChaosExceptionTests.
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 2m2s
2026-02-06 18:05:57 +03:00
hashlag
b4f015f501 Compile tests with -Wunused -Werror=unused.
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m54s
Promotes cleaner and less error-prone code.
2026-02-05 16:16:38 +03:00
hashlag
95e74db6ec Perform aggregate zero-init instead of .fill(0) where appropriate.
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m50s
Simpler and more consistent code.
2026-02-05 00:40:55 +03:00
hashlag
ed22d29af0 Merge branch 'explicit-bounds'
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m50s
Harden against out-of-bounds writes.
2026-02-04 23:52:50 +03:00
hashlag
65eb51c133 Remove unused CrunchUInt64() overload.
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m57s
2026-02-04 23:47:45 +03:00
hashlag
b34fda75ef DesCryptTests: IteratorUsage tests: Add testcases with begin == end.
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m57s
2026-02-04 23:37:05 +03:00
hashlag
15d841893c IteratorUsage tests: Add some canary nulled space before begin.
Hardening against write-before-begin.
2026-02-04 23:31:14 +03:00
hashlag
5fd27cd7b5 Merge branch 'stream-bounds-tests' into explicit-bounds
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m50s
Add some past-the-end write hardening tests for stream ciphers.
2026-02-04 01:02:56 +03:00
hashlag
1bf91a90d0 Add Arc4CryptTests, DecryptOutIteratorUsageTest.
Harden against past-the-end write.
2026-02-04 01:01:54 +03:00
hashlag
2d64389d66 Add Arc4CryptTests, EncryptOutIteratorUsageTest.
Harden against past-the-end write.
2026-02-04 00:43:40 +03:00
hashlag
ccdf14d31a Add Arc4GenTests, GenerateOutIteratorUsageTest.
Harden against past-the-end write.
2026-02-04 00:25:15 +03:00
hashlag
9734f9a517 Merge branch 'block-exp-bounds' into explicit-bounds
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m49s
Implement explicit bounds requirements for block ciphers.
2026-02-02 01:51:58 +03:00
hashlag
3de69d3298 Fix assertion style.
It should be expectation-first...
2026-02-02 01:15:38 +03:00
hashlag
a0f17ea127 Decryptor: Require end of the output span to be indicated explicitly.
Usage becomes much less error-prone.
2026-02-02 01:10:22 +03:00
hashlag
67709e5361 Encryptor: Require end of the output span to be indicated explicitly.
Usage becomes much less error-prone.
2026-02-02 00:52:08 +03:00
hashlag
d194fef1af Mark all Block::Decryptor<> methods const.
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m42s
This allows for convenient usage of const Decryptor<Impl> &.
2026-02-01 00:24:50 +03:00
hashlag
cdcab2f4f7 Mark all Block::Encryptor<> methods const.
This allows for convenient usage of const Encryptor<Impl> &.
2026-01-31 23:56:25 +03:00
hashlag
a97826da88 Expose block sizes of block ciphers.
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m45s
Both via static data members and Encryptor/Decryptor interfaces.
Crucial for safe memory allocation routine.
2026-01-31 19:26:51 +03:00
hashlag
8897d7a910 Merge branch 'block-cipher'
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m43s
Introduce fixed CRTP interfaces for block cipher
encryption and decryption.
2026-01-31 18:50:10 +03:00
hashlag
73c455901b Introduce Block::Decryptor<> CRTP base class.
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m43s
Inherit DesDecryptor from it.
2026-01-31 18:35:23 +03:00
hashlag
4cf79b61ad Introduce Block::Encryptor<> CRTP base class.
Inherit DesEncryptor from it.
2026-01-31 18:12:43 +03:00
hashlag
ba70abd2af Rename DesCrypt::Encryptor --> DesEncryptor, DesCrypt::Decryptor --> DesDecryptor.
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m43s
Maintain naming consistency with Hash subproject.
2026-01-31 17:22:14 +03:00
hashlag
9a3b6edfc3 Rename DesCrypt::Encryptor --> DesEncryptor, DesCrypt::Decryptor --> DesDecryptor.
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m46s
Maintain naming consistency with Hash subproject.
2026-01-31 17:18:25 +03:00
hashlag
3c98b75986 Create dedicated Cipher/Block directory for block ciphers
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m41s
Move Des there.
2026-01-30 01:01:48 +03:00
hashlag
b5d1f9a6fc Make CRTP base classes ctors protected
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m39s
This forbids to create base class instances which direct usage could lead to UB.
2026-01-30 00:44:24 +03:00
hashlag
2c9200ab21 Merge branch 'mac-bench'
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m44s
Add benchmarks for MAC algorithms.
2026-01-29 23:43:28 +03:00
hashlag
6246bf4538 Add HmacSha1_PartialUpdate100Bench 2026-01-29 23:40:39 +03:00
hashlag
78c59dc668 Add HmacSha1_ReuseBench 2026-01-29 23:39:00 +03:00
hashlag
d4fa11795b Add HmacSha1_CreateComputeDeleteBench 2026-01-29 23:38:22 +03:00
hashlag
3780586e63 Add HmacMd5_PartialUpdate100Bench 2026-01-29 23:34:53 +03:00
hashlag
cc9963f1ca Add HmacMd5_ReuseBench 2026-01-29 23:34:20 +03:00
hashlag
05533e7c6b Add HmacMd5_CreateComputeDeleteBench 2026-01-29 23:33:45 +03:00
hashlag
961a521c57 Add HmacBenches.cpp to ChaosBenches_SOURCE 2026-01-29 23:31:15 +03:00
hashlag
029055f9a3 Add HmacMd4_PartialUpdate100Bench 2026-01-29 23:30:16 +03:00
hashlag
b5f86b5633 Add HmacMd4_ReuseBench 2026-01-29 23:29:33 +03:00
hashlag
0bc29c86e5 Add HmacMd4_CreateComputeDeleteBench 2026-01-29 23:16:07 +03:00
hashlag
11561c9379 ChaosCi.yaml: fix directory path style
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m32s
2026-01-29 01:29:52 +03:00
hashlag
b7a31b44df Configure retention policy for coverage reports
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m32s
2026-01-29 00:42:20 +03:00
hashlag
4ae55f93fc Sha1HasherTests: Add a longer than 56 (mod 64) byte message testcase
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m30s
2026-01-29 00:28:16 +03:00
hashlag
8eb0c6ab12 Md5HasherTests: Add an exactly 56 byte message testcase
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m34s
2026-01-29 00:18:26 +03:00
hashlag
90c44f5305 Md4HasherTests: Add an exactly 56 byte message testcase.
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m34s
2026-01-29 00:10:49 +03:00
hashlag
cd6014d8c0 Merge branch 'tgt-builds'
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m33s
Optimize CI by not building unused binaries.
2026-01-28 23:29:57 +03:00
hashlag
0a8b79cd09 Make CI not to build currently unused targets:
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 1m36s
ChaosTests in Release and ChaosBenches in Debug.
2026-01-28 23:24:12 +03:00
hashlag
0c3ce4af8d Merge branch 'lcov-report-ci'
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 2m24s
Add coverage report generation to the CI workflow.
2026-01-28 23:15:42 +03:00
hashlag
01d7d19ee6 Remove lcov --ignore-errors flag.
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 2m28s
2026-01-28 23:06:47 +03:00
hashlag
612b11b02f Run lcov with proper --exclude flags to eliminate unwanted coverage data generation
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 2m30s
2026-01-28 22:59:55 +03:00
hashlag
15bb663281 Revert "Run lcov with --no-external flag set"
Library headers are considered externals in this case.

This reverts commit 9a764c06db.
2026-01-28 22:51:38 +03:00
hashlag
9a764c06db Run lcov with --no-external flag set
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 2m32s
2026-01-28 22:45:09 +03:00
hashlag
b02685d29f Give the upload-artifact step a proper name
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 2m26s
2026-01-28 02:25:44 +03:00
hashlag
1a999a7dd3 Downgrade to actions/upload-artifact@v3
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 2m37s
2026-01-28 02:18:02 +03:00
hashlag
18bcd87f81 Ignore lcov mismatch errors
Some checks failed
Chaos Ci / test-and-benchmark (push) Failing after 2m23s
2026-01-28 02:11:07 +03:00
hashlag
07663decf9 ChaosCi: Report coverage via lcov + genhtml
Some checks failed
Chaos Ci / test-and-benchmark (push) Failing after 2m31s
2026-01-28 02:05:36 +03:00
hashlag
2a5a2c96b5 ChaosTests: Build with --coverage in Debug 2026-01-28 02:04:17 +03:00
hashlag
d0e7d2b0ec Use self-hosted copies of dependencies distros
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 2m22s
2026-01-28 00:38:01 +03:00
hashlag
4e89b2fb05 Run tests under valgrind's memcheck
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 2m20s
2026-01-26 00:28:43 +03:00
hashlag
1e593ef703 Merge branch 'sha1bench'
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 2m9s
2026-01-25 19:17:51 +03:00
hashlag
9eb2a6bcde Add Sha1Hasher benchmarks 2026-01-25 19:17:16 +03:00
hashlag
85fe3cfe88 Refine benchmark names: use _ to highlight scope 2026-01-25 19:11:31 +03:00
hashlag
89991c21f5 Merge branch 'md5bench' 2026-01-25 19:09:17 +03:00
hashlag
d8c8fd0ce3 Add Md5Hasher benchmarks 2026-01-25 19:08:57 +03:00
hashlag
5ec6fc2f20 Add Md4HasherPartialUpdate100Bench 2026-01-25 18:55:51 +03:00
hashlag
512338df33 Add Md4HasherReuseBench 2026-01-25 18:45:38 +03:00
hashlag
bdd43d8fa2 Rename ChaosCI.yaml --> ChaosCi.yaml to match the project's abbreviation style
All checks were successful
Chaos Ci / test-and-benchmark (push) Successful in 2m1s
2026-01-25 18:33:06 +03:00
hashlag
ab9220587e Get rid of unnecessary path relativity in 'test-and-benchmark' job
All checks were successful
Chaos CI / test-and-benchmark (push) Successful in 2m1s
2026-01-25 18:26:24 +03:00
hashlag
254c1e0e01 Explicitly configure test build as 'Debug' 2026-01-25 18:18:55 +03:00
hashlag
26d866d1cf Rename job steps: 'Configure, build' --> 'Configure and build' 2026-01-25 18:16:10 +03:00
hashlag
b707e1ce68 Merge branch 'bench'
All checks were successful
Chaos CI / test-and-benchmark (push) Successful in 1m55s
2026-01-25 18:12:13 +03:00
hashlag
b9eb1a5fc8 Rename job build-and-test --> test-and-benchmark
All checks were successful
Chaos CI / test-and-benchmark (push) Successful in 1m55s
2026-01-25 18:11:26 +03:00
hashlag
28334d1d78 Run tests and benchmarks in one job
All checks were successful
Chaos CI / build-and-test (push) Successful in 1m55s
2026-01-25 18:07:41 +03:00
hashlag
d30d5f8a74 Build benchmarks with CMAKE_BUILD_TYPE=Release
All checks were successful
Chaos CI / build-and-test (push) Successful in 57s
Chaos CI / build-and-benchmark (push) Successful in 1m14s
2026-01-25 17:48:57 +03:00
hashlag
478012dd10 Place test and bench jobs in one .yaml
All checks were successful
Chaos CI / build-and-test (push) Successful in 55s
Chaos CI / build-and-benchmark (push) Successful in 1m0s
2026-01-25 17:42:24 +03:00
hashlag
ff57cd0d31 Fix #includes: Add <cstring> for strlen()
All checks were successful
ChaosBenchmark CI / build-and-benchmark (push) Successful in 57s
ChaosTest CI / build-and-test (push) Successful in 54s
2026-01-25 17:35:53 +03:00
hashlag
3e7a0f3e53 Fix benchmark job name 2026-01-25 17:34:12 +03:00
hashlag
c0685d00b5 Add ChaosBenchmarkCI.yaml workflow
Some checks failed
ChaosBenchmark CI / build-and-test (push) Failing after 57s
ChaosTest CI / build-and-test (push) Failing after 54s
2026-01-25 17:30:50 +03:00
hashlag
660b13a045 ChaosBenches: Add Md4HasherCreateComputeDeleteBench 2026-01-25 17:24:58 +03:00
hashlag
cbefae2256 Rename README.TXT --> README.txt
All checks were successful
ChaosTest CI / build-and-test (push) Successful in 33s
2026-01-25 00:00:18 +03:00
hashlag
4da2f0e6eb Merge branch 'des'
All checks were successful
ChaosTest CI / build-and-test (push) Successful in 33s
2026-01-24 23:56:07 +03:00
hashlag
0ca97cc336 Use DesCrypt::Block type alias in EncryptBlock()/DecryptBlock() signatures
All checks were successful
ChaosTest CI / build-and-test (push) Successful in 35s
2026-01-24 23:53:04 +03:00
hashlag
66413e2cfc Add .cache/ to .gitignore
All checks were successful
ChaosTest CI / build-and-test (push) Successful in 32s
2026-01-24 23:46:52 +03:00
hashlag
a8141cb708 Add .cache/ to .gitignore
All checks were successful
ChaosTest CI / build-and-test (push) Successful in 33s
2026-01-24 23:44:57 +03:00
29 changed files with 1284 additions and 209 deletions

View 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

View File

@@ -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

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
.cache/
.vscode/
build/

View File

@@ -15,3 +15,4 @@ target_include_directories(Chaos INTERFACE
)
add_subdirectory(ChaosTests)
add_subdirectory(ChaosBenches)

View 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

View File

@@ -1,5 +1,5 @@
#ifndef CHAOS_CIPHER_DES_DESCRYPT_HPP
#define CHAOS_CIPHER_DES_DESCRYPT_HPP
#ifndef CHAOS_CIPHER_BLOCK_DES_DESCRYPT_HPP
#define CHAOS_CIPHER_BLOCK_DES_DESCRYPT_HPP
#include <algorithm>
#include <utility>
@@ -7,7 +7,10 @@
#include "Service/ChaosException.hpp"
#include "Service/SeArray.hpp"
namespace Chaos::Cipher::Des::Inner_
#include "Cipher/Block/Encryptor.hpp"
#include "Cipher/Block/Decryptor.hpp"
namespace Chaos::Cipher::Block::Des::Inner_
{
struct Bitwise
@@ -80,11 +83,12 @@ struct Bitwise
}
template<typename OutputIt>
static void CrunchUInt64(OutputIt out, uint64_t value)
static void CrunchUInt64(OutputIt outBegin, OutputIt outEnd, uint64_t value)
{
for (int_fast8_t i = 0; i < 8; ++i)
int_fast8_t i = 0;
for (OutputIt out = outBegin; i < 8 && out != outEnd; ++i, ++out)
{
*out++ = (value >> (56 - (i * 8))) & Mask<8>();
*out = (value >> (56 - (i * 8))) & Mask<8>();
}
}
};
@@ -184,14 +188,21 @@ private:
}
};
} // namespace Chaos::Cipher::Des::Inner_
} // namespace Chaos::Cipher::Block::Des::Inner_
namespace Chaos::Cipher::Des
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
@@ -219,15 +230,20 @@ public:
Inner_::RawKey Key_;
};
class Encryptor
class DesEncryptor : public Encryptor<DesEncryptor>
{
public:
Encryptor(const Key & key)
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 out, InputIt inBegin, InputIt inEnd)
void EncryptBlock(OutputIt outBegin, OutputIt outEnd,
InputIt inBegin, InputIt inEnd) const
{
RawBlockArray block;
@@ -242,27 +258,37 @@ public:
block.End()),
Schedule_);
Inner_::Bitwise::CrunchUInt64(out, encrypted);
Inner_::Bitwise::CrunchUInt64(outBegin, outEnd, encrypted);
}
uint64_t EncryptBlock(uint64_t block)
Block EncryptBlock(Block block) const
{
return DesCrypt::ProcessBlock(block, Schedule_);
}
constexpr size_t GetBlockSize() const
{
return BlockSize;
}
private:
Inner_::KeySchedule Schedule_;
};
class Decryptor
class DesDecryptor : public Decryptor<DesDecryptor>
{
public:
Decryptor(const Key & key)
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 out, InputIt inBegin, InputIt inEnd)
void DecryptBlock(OutputIt outBegin, OutputIt outEnd,
InputIt inBegin, InputIt inEnd) const
{
RawBlockArray block;
@@ -277,20 +303,24 @@ public:
block.End()),
Schedule_);
Inner_::Bitwise::CrunchUInt64(out, decrypted);
Inner_::Bitwise::CrunchUInt64(outBegin, outEnd, decrypted);
}
uint64_t DecryptBlock(uint64_t block)
Block DecryptBlock(Block block) const
{
return DesCrypt::ProcessBlock(block, Schedule_);
}
constexpr size_t GetBlockSize() const
{
return BlockSize;
}
private:
Inner_::KeySchedule Schedule_;
};
private:
using Block = uint64_t;
using BlockHalf = uint32_t;
using RawBlockArray = Service::SeArray<uint8_t, 8>;
using Data48 = uint64_t;
@@ -482,6 +512,6 @@ private:
}
};
} // namespace Chaos::Cipher::Des
} // namespace Chaos::Cipher::Block::Des
#endif // CHAOS_CIPHER_DES_DESCRYPT_HPP
#endif // CHAOS_CIPHER_BLOCK_DES_DESCRYPT_HPP

View 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

View File

@@ -20,6 +20,9 @@ public:
return Impl().ToHexString();
}
protected:
Hash() = default;
private:
const T & Impl() const
{

View File

@@ -24,6 +24,9 @@ public:
return Impl().Finish();
}
protected:
Hasher() = default;
private:
const T & Impl() const
{

34
Chaos/Padding/Padder.hpp Normal file
View File

@@ -0,0 +1,34 @@
#ifndef CHAOS_PADDING_PADDER_HPP
#define CHAOS_PADDING_PADDER_HPP
namespace Chaos::Padding
{
template<typename T>
class Padder
{
public:
template<typename OutputIt>
void Pad(OutputIt begin, OutputIt end) const
{
Impl().Pad(begin, end);
}
protected:
Padder() = default;
private:
const T & Impl() const
{
return static_cast<const T &>(*this);
}
T & Impl()
{
return static_cast<T &>(*this);
}
};
} // namespace Chaos::Padding
#endif // CHAOS_PADDING_PADDER_HPP

View File

@@ -0,0 +1,38 @@
#ifndef CHAOS_PADDING_PADDERPKCS7_HPP
#define CHAOS_PADDING_PADDERPKCS7_HPP
#include <cstdint>
#include <iterator>
#include <limits>
#include "Padding/Padder.hpp"
#include "Service/ChaosException.hpp"
namespace Chaos::Padding
{
class PadderPkcs7 : public Padder<PadderPkcs7>
{
public:
template<typename OutputIt>
static void Pad(OutputIt begin, OutputIt end)
{
auto dist = std::distance(begin, end);
if (dist >= 0 && dist <= std::numeric_limits<uint8_t>::max())
{
for (OutputIt it = begin; it != end; ++it)
{
*it = static_cast<uint8_t>(dist);
}
}
else
{
throw Service::ChaosException("PadPkcs7::Pad(): invalid range");
}
}
};
} // namespace Chaos::Padding
#endif // CHAOS_PADDING_PADDERPKCS7_HPP

View File

@@ -58,11 +58,6 @@ public:
return Storage_.data() + Storage_.size();
}
constexpr size_t Size() const noexcept
{
return Storage_.size();
}
void Fill(const T & value)
{
Storage_.fill(value);
@@ -73,6 +68,11 @@ public:
EraseImpl();
}
static constexpr size_t Size() noexcept
{
return S;
}
private:
std::array<T, S> Storage_;

View File

@@ -0,0 +1,3 @@
#include <benchmark/benchmark.h>
BENCHMARK_MAIN();

View 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>
)

View 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);

View 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);

View 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);

View 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);

View File

@@ -4,7 +4,7 @@ cmake_policy(SET CMP0135 NEW)
FetchContent_Declare(
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
)
@@ -18,7 +18,9 @@ set(ChaosTests_SOURCE Hash/Md4HasherTests.cpp
Cipher/Arc4GenTests.cpp
Cipher/Arc4CryptTests.cpp
Cipher/DesCryptTests.cpp
Service/SeArrayTests.cpp)
Padding/PadderPkcs7Tests.cpp
Service/SeArrayTests.cpp
Service/ChaosExceptionTests.cpp)
add_executable(ChaosTests ${ChaosTests_SOURCE})
target_link_libraries(ChaosTests gtest gtest_main)
@@ -26,6 +28,13 @@ target_include_directories(ChaosTests PRIVATE
$<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)
gtest_discover_tests(ChaosTests)

View File

@@ -58,11 +58,8 @@ TEST(Arc4CryptTests, UninitializedArc4CryptTest)
Arc4Crypt arc4;
{
std::array<uint8_t, 10> in;
in.fill(0);
std::array<uint8_t, 10> out;
out.fill(0);
std::array<uint8_t, 10> in = {};
std::array<uint8_t, 10> out = {};
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);
@@ -107,3 +104,115 @@ TEST(Arc4CryptTests, RekeyTest)
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);
}
}

View File

@@ -353,3 +353,56 @@ TEST(Arc4GenTests, UninitializedGenTest)
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);
}
}

View File

@@ -1,8 +1,10 @@
#include <gtest/gtest.h>
#include "Cipher/Des/DesCrypt.hpp"
#include "Cipher/Block/Des/DesCrypt.hpp"
#include "Cipher/Block/Encryptor.hpp"
using namespace Chaos::Cipher::Des;
using namespace Chaos::Cipher::Block::Des;
using namespace Chaos::Cipher::Block;
TEST(DesCryptTests, KeyScheduleTest)
{
@@ -41,15 +43,14 @@ TEST(DesCryptTests, EncryptTest)
{
struct Helper
{
std::array<uint8_t, 8> operator()(const std::array<uint8_t, 8> & data,
const std::array<uint8_t, 8> & key) const
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, 8> result;
result.fill(0);
std::array<uint8_t, DesCrypt::BlockSize> result = {};
DesCrypt::Key desKey(key.begin(), key.end());
DesCrypt::Encryptor enc(desKey);
enc.EncryptBlock(result.begin(), data.begin(), data.end());
DesCrypt::DesEncryptor enc(desKey);
enc.EncryptBlock(result.begin(), result.end(), data.begin(), data.end());
return result;
}
@@ -58,28 +59,28 @@ TEST(DesCryptTests, EncryptTest)
Helper des;
{
std::array<uint8_t, 8> data = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
std::array<uint8_t, 8> key = { 0x13, 0x34, 0x57, 0x79, 0x9b, 0xbc, 0xdf, 0xf1 };
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, 8> expected = { 0x85, 0xe8, 0x13, 0x54, 0x0f, 0x0a, 0xb4, 0x05 };
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, 8> data = { 0xaa, 0xf3, 0x83, 0x16, 0x2d, 0x2e, 0x6b, 0xcb };
std::array<uint8_t, 8> key = { 0x44, 0xbf, 0x32, 0x19, 0x99, 0x25, 0x81, 0x51 };
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, 8> expected = { 0x07, 0xe8, 0x7f, 0xaa, 0xb3, 0x17, 0x13, 0x18 };
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, 8> data = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0xa7, 0x93, 0x44 };
std::array<uint8_t, 8> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
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, 8> expected = { 0x42, 0x27, 0x88, 0xa6, 0x7b, 0x6c, 0x18, 0xed };
std::array<uint8_t, DesCrypt::BlockSize> expected = { 0x42, 0x27, 0x88, 0xa6, 0x7b, 0x6c, 0x18, 0xed };
ASSERT_EQ(expected, des(data, key));
}
@@ -90,10 +91,10 @@ TEST(DesCryptTests, EncryptUInt64BlockTest)
struct Helper
{
uint64_t operator()(uint64_t data,
const std::array<uint8_t, 8> & key) const
const std::array<uint8_t, DesCrypt::KeySize> & key) const
{
DesCrypt::Key desKey(key.begin(), key.end());
DesCrypt::Encryptor enc(desKey);
DesCrypt::DesEncryptor enc(desKey);
return enc.EncryptBlock(data);
}
@@ -103,7 +104,7 @@ TEST(DesCryptTests, EncryptUInt64BlockTest)
{
uint64_t data = 0x0123456789abcdef;
std::array<uint8_t, 8> key = { 0x13, 0x34, 0x57, 0x79, 0x9b, 0xbc, 0xdf, 0xf1 };
std::array<uint8_t, DesCrypt::KeySize> key = { 0x13, 0x34, 0x57, 0x79, 0x9b, 0xbc, 0xdf, 0xf1 };
uint64_t expected = 0x85e813540f0ab405;
@@ -112,7 +113,7 @@ TEST(DesCryptTests, EncryptUInt64BlockTest)
{
uint64_t data = 0xaaf383162d2e6bcb;
std::array<uint8_t, 8> key = { 0x44, 0xbf, 0x32, 0x19, 0x99, 0x25, 0x81, 0x51 };
std::array<uint8_t, DesCrypt::KeySize> key = { 0x44, 0xbf, 0x32, 0x19, 0x99, 0x25, 0x81, 0x51 };
uint64_t expected = 0x07e87faab3171318;
@@ -121,7 +122,7 @@ TEST(DesCryptTests, EncryptUInt64BlockTest)
{
uint64_t data = 0xe51a9fd419a79344;
std::array<uint8_t, 8> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
std::array<uint8_t, DesCrypt::KeySize> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
uint64_t expected = 0x422788a67b6c18ed;
@@ -137,11 +138,11 @@ TEST(DesCryptTests, EncryptShortDataTest)
const std::vector<uint8_t> & key)
{
std::vector<uint8_t> result;
result.resize(8, 0);
result.resize(DesCrypt::BlockSize, 0);
DesCrypt::Key desKey(key.begin(), key.end());
DesCrypt::Encryptor enc(desKey);
enc.EncryptBlock(result.begin(), data.begin(), data.end());
DesCrypt::DesEncryptor enc(desKey);
enc.EncryptBlock(result.begin(), result.end(), data.begin(), data.end());
return result;
}
@@ -171,11 +172,11 @@ TEST(DesCryptTests, EncryptLongDataTest)
const std::vector<uint8_t> & key)
{
std::vector<uint8_t> result;
result.resize(8, 0);
result.resize(DesCrypt::BlockSize, 0);
DesCrypt::Key desKey(key.begin(), key.end());
DesCrypt::Encryptor enc(desKey);
enc.EncryptBlock(result.begin(), data.begin(), data.end());
DesCrypt::DesEncryptor enc(desKey);
enc.EncryptBlock(result.begin(), result.end(), data.begin(), data.end());
return result;
}
@@ -201,15 +202,14 @@ TEST(DesCryptTests, DecryptTest)
{
struct Helper
{
std::array<uint8_t, 8> operator()(const std::array<uint8_t, 8> & data,
const std::array<uint8_t, 8> & key) const
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, 8> result;
result.fill(0);
std::array<uint8_t, DesCrypt::BlockSize> result = {};
DesCrypt::Key desKey(key.begin(), key.end());
DesCrypt::Decryptor dec(desKey);
dec.DecryptBlock(result.begin(), data.begin(), data.end());
DesCrypt::DesDecryptor dec(desKey);
dec.DecryptBlock(result.begin(), result.end(), data.begin(), data.end());
return result;
}
@@ -218,28 +218,28 @@ TEST(DesCryptTests, DecryptTest)
Helper des;
{
std::array<uint8_t, 8> data = { 0x85, 0xe8, 0x13, 0x54, 0x0f, 0x0a, 0xb4, 0x05 };
std::array<uint8_t, 8> key = { 0x13, 0x34, 0x57, 0x79, 0x9b, 0xbc, 0xdf, 0xf1 };
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, 8> expected = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
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, 8> data = { 0x07, 0xe8, 0x7f, 0xaa, 0xb3, 0x17, 0x13, 0x18 };
std::array<uint8_t, 8> key = { 0x44, 0xbf, 0x32, 0x19, 0x99, 0x25, 0x81, 0x51 };
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, 8> expected = { 0xaa, 0xf3, 0x83, 0x16, 0x2d, 0x2e, 0x6b, 0xcb };
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, 8> data = { 0x42, 0x27, 0x88, 0xa6, 0x7b, 0x6c, 0x18, 0xed };
std::array<uint8_t, 8> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
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, 8> expected = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0xa7, 0x93, 0x44 };
std::array<uint8_t, DesCrypt::BlockSize> expected = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0xa7, 0x93, 0x44 };
ASSERT_EQ(expected, des(data, key));
}
@@ -250,10 +250,10 @@ TEST(DesCryptTests, DecryptUInt64BlockTest)
struct Helper
{
uint64_t operator()(uint64_t data,
const std::array<uint8_t, 8> & key) const
const std::array<uint8_t, DesCrypt::KeySize> & key) const
{
DesCrypt::Key desKey(key.begin(), key.end());
DesCrypt::Decryptor dec(desKey);
DesCrypt::DesDecryptor dec(desKey);
return dec.DecryptBlock(data);
}
@@ -263,7 +263,7 @@ TEST(DesCryptTests, DecryptUInt64BlockTest)
{
uint64_t data = 0x85e813540f0ab405;
std::array<uint8_t, 8> key = { 0x13, 0x34, 0x57, 0x79, 0x9b, 0xbc, 0xdf, 0xf1 };
std::array<uint8_t, DesCrypt::KeySize> key = { 0x13, 0x34, 0x57, 0x79, 0x9b, 0xbc, 0xdf, 0xf1 };
uint64_t expected = 0x0123456789abcdef;
@@ -272,7 +272,7 @@ TEST(DesCryptTests, DecryptUInt64BlockTest)
{
uint64_t data = 0x07e87faab3171318;
std::array<uint8_t, 8> key = { 0x44, 0xbf, 0x32, 0x19, 0x99, 0x25, 0x81, 0x51 };
std::array<uint8_t, DesCrypt::KeySize> key = { 0x44, 0xbf, 0x32, 0x19, 0x99, 0x25, 0x81, 0x51 };
uint64_t expected = 0xaaf383162d2e6bcb;
@@ -281,7 +281,7 @@ TEST(DesCryptTests, DecryptUInt64BlockTest)
{
uint64_t data = 0x422788a67b6c18ed;
std::array<uint8_t, 8> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
std::array<uint8_t, DesCrypt::KeySize> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
uint64_t expected = 0xe51a9fd419a79344;
@@ -297,11 +297,11 @@ TEST(DesCryptTests, DecryptShortDataTest)
const std::vector<uint8_t> & key)
{
std::vector<uint8_t> result;
result.resize(8, 0);
result.resize(DesCrypt::BlockSize, 0);
DesCrypt::Key desKey(key.begin(), key.end());
DesCrypt::Decryptor dec(desKey);
dec.DecryptBlock(result.begin(), data.begin(), data.end());
DesCrypt::DesDecryptor dec(desKey);
dec.DecryptBlock(result.begin(), result.end(), data.begin(), data.end());
return result;
}
@@ -331,11 +331,11 @@ TEST(DesCryptTests, DecryptLongDataTest)
const std::vector<uint8_t> & key)
{
std::vector<uint8_t> result;
result.resize(8, 0);
result.resize(DesCrypt::BlockSize, 0);
DesCrypt::Key desKey(key.begin(), key.end());
DesCrypt::Decryptor dec(desKey);
dec.DecryptBlock(result.begin(), data.begin(), data.end());
DesCrypt::DesDecryptor dec(desKey);
dec.DecryptBlock(result.begin(), result.end(), data.begin(), data.end());
return result;
}
@@ -360,7 +360,7 @@ TEST(DesCryptTests, DecryptLongDataTest)
TEST(DesCryptTests, ShortKeyTest)
{
{
std::array<uint8_t, 7> key = {};
std::array<uint8_t, DesCrypt::KeySize - 1> key = {};
ASSERT_THROW(DesCrypt::Key(key.begin(), key.end()), Chaos::Service::ChaosException);
}
}
@@ -368,129 +368,187 @@ TEST(DesCryptTests, ShortKeyTest)
TEST(DesCryptTests, LongKeyTest)
{
{
std::array<uint8_t, 9> key = {};
std::array<uint8_t, DesCrypt::KeySize + 1> key = {};
ASSERT_THROW(DesCrypt::Key(key.begin(), key.end()), Chaos::Service::ChaosException);
}
}
TEST(DesCryptTests, OutIteratorUsageEncryptTest)
{
struct OutputItMock
{
OutputItMock(size_t & asteriskCalls, size_t & incrementCalls)
: AsteriskCalls_(asteriskCalls)
, IncrementCalls_(incrementCalls)
{ }
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 };
uint8_t & operator*()
{
++AsteriskCalls_;
static uint8_t dummy = 0;
return dummy;
}
OutputItMock operator++(int)
{
++IncrementCalls_;
return *this;
}
size_t & AsteriskCalls_;
size_t & IncrementCalls_;
};
{
std::array<uint8_t, 8> data = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0xa7, 0x93, 0x44 };
std::array<uint8_t, 8> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
size_t asteriskCalls = 0;
size_t incrementCalls = 0;
OutputItMock it(asteriskCalls, incrementCalls);
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::Encryptor enc(desKey);
enc.EncryptBlock(it, data.begin(), data.end());
DesCrypt::DesEncryptor enc(desKey);
enc.EncryptBlock(fact.begin() + 3, fact.end() - 3, data.begin(), data.end());
ASSERT_EQ(8, asteriskCalls);
ASSERT_EQ(8, incrementCalls);
ASSERT_EQ(expected, fact);
}
{
std::array<uint8_t, 11> data = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f };
std::array<uint8_t, 8> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
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 };
size_t asteriskCalls = 0;
size_t incrementCalls = 0;
OutputItMock it(asteriskCalls, incrementCalls);
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::Encryptor enc(desKey);
enc.EncryptBlock(it, data.begin(), data.end());
DesCrypt::DesEncryptor enc(desKey);
enc.EncryptBlock(fact.begin() + 4, fact.end() - 4, data.begin(), data.end());
ASSERT_EQ(8, asteriskCalls);
ASSERT_EQ(8, incrementCalls);
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)
{
struct OutputItMock
{
OutputItMock(size_t & asteriskCalls, size_t & incrementCalls)
: AsteriskCalls_(asteriskCalls)
, IncrementCalls_(incrementCalls)
{ }
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 };
uint8_t & operator*()
{
++AsteriskCalls_;
static uint8_t dummy = 0;
return dummy;
}
OutputItMock operator++(int)
{
++IncrementCalls_;
return *this;
}
size_t & AsteriskCalls_;
size_t & IncrementCalls_;
};
{
std::array<uint8_t, 8> data = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0xa7, 0x93, 0x44 };
std::array<uint8_t, 8> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
size_t asteriskCalls = 0;
size_t incrementCalls = 0;
OutputItMock it(asteriskCalls, incrementCalls);
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::Decryptor dec(desKey);
dec.DecryptBlock(it, data.begin(), data.end());
DesCrypt::DesDecryptor dec(desKey);
dec.DecryptBlock(fact.begin() + 3, fact.end() - 3, data.begin(), data.end());
ASSERT_EQ(8, asteriskCalls);
ASSERT_EQ(8, incrementCalls);
ASSERT_EQ(expected, fact);
}
{
std::array<uint8_t, 11> data = { 0xe5, 0x1a, 0x9f, 0xd4, 0x19, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f };
std::array<uint8_t, 8> key = { 0xda, 0xec, 0x68, 0xae, 0x83, 0xe0, 0x1e, 0xab };
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 };
size_t asteriskCalls = 0;
size_t incrementCalls = 0;
OutputItMock it(asteriskCalls, incrementCalls);
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::Decryptor dec(desKey);
dec.DecryptBlock(it, data.begin(), data.end());
DesCrypt::DesDecryptor dec(desKey);
dec.DecryptBlock(fact.begin() + 4, fact.end() - 4, data.begin(), data.end());
ASSERT_EQ(8, asteriskCalls);
ASSERT_EQ(8, incrementCalls);
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));
}

View File

@@ -116,6 +116,24 @@ TEST(Md4Tests, PartialUpdateTest)
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)

View File

@@ -116,6 +116,24 @@ TEST(Md5Tests, PartialUpdateTest)
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)

View File

@@ -116,6 +116,24 @@ TEST(Sha1Tests, PartialUpdateTest)
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)

View File

@@ -99,8 +99,7 @@ TEST(HmacTests, LongKeyTest)
TEST(HmacTests, UninitializedHmacTest)
{
std::array<uint8_t, 10> in;
in.fill(0);
std::array<uint8_t, 10> in = {};
{
Hmac<Md5Hasher> hmac;

View File

@@ -0,0 +1,143 @@
#include <gtest/gtest.h>
#include <array>
#include <cstdint>
#include <vector>
#include "Padding/PadderPkcs7.hpp"
#include "Service/ChaosException.hpp"
using namespace Chaos::Padding;
TEST(PadPkcs7Tests, PadTest)
{
{
std::array<uint8_t, 1> fact = {};
std::array<uint8_t, 1> expected = { 0x01 };
PadderPkcs7::Pad(fact.begin(), fact.end());
ASSERT_EQ(expected, fact);
}
{
std::array<uint8_t, 7> fact = {};
std::array<uint8_t, 7> expected =
{
0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07
};
PadderPkcs7::Pad(fact.begin(), fact.end());
ASSERT_EQ(expected, fact);
}
{
std::array<uint8_t, 10> fact = {};
std::array<uint8_t, 10> 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<uint8_t> fact(i, 0x00);
PadderPkcs7::Pad(fact.begin(), fact.end());
ASSERT_EQ(std::vector<uint8_t>(i, i), fact);
}
}
TEST(PadPkcs7Tests, PadInvalidRangeTest)
{
{
std::array<uint8_t, 256> out = {};
ASSERT_THROW(PadderPkcs7::Pad(out.begin(), out.end()), Chaos::Service::ChaosException);
}
{
std::array<uint8_t, 500> out = {};
ASSERT_THROW(PadderPkcs7::Pad(out.begin(), out.end()), Chaos::Service::ChaosException);
}
{
std::array<uint8_t, 50> out = {};
ASSERT_THROW(PadderPkcs7::Pad(out.end(), out.begin()), Chaos::Service::ChaosException);
}
}
TEST(PadPkcs7Tests, PadOutIteratorUsageTest)
{
{
std::array<uint8_t, 28> fact = {};
std::array<uint8_t, 28> 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<uint8_t, 39> fact = {};
std::array<uint8_t, 39> 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<uint8_t, 10> fact =
{
0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
0xbb, 0xbb, 0xbb, 0xbb, 0xbb
};
std::array<uint8_t, 10> expected =
{
0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
0xbb, 0xbb, 0xbb, 0xbb, 0xbb
};
PadderPkcs7::Pad(fact.begin() + 5, fact.begin() + 5);
ASSERT_EQ(expected, fact);
}
}
template<typename Impl, typename OutputIt>
void PadThroughBase(const Padder<Impl> & padder, OutputIt begin, OutputIt end)
{
padder.Pad(begin, end);
}
TEST(PadPkcs7Tests, PadThroughBaseTest)
{
{
std::array<uint8_t, 5> fact = {};
std::array<uint8_t, 5> expected =
{
0x05, 0x05, 0x05, 0x05, 0x05
};
const PadderPkcs7 padder;
PadThroughBase(padder, fact.begin(), fact.end());
ASSERT_EQ(expected, fact);
}
}

View 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());
}
}