Skip to content

Commit

Permalink
Basic Noekeon implementation added #35
Browse files Browse the repository at this point in the history
  • Loading branch information
nkaskov committed Jun 24, 2020
1 parent a84f3ba commit 0be17f2
Show file tree
Hide file tree
Showing 5 changed files with 346 additions and 0 deletions.
81 changes: 81 additions & 0 deletions include/nil/crypto3/block/detail/noekeon/noekeon_functions.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//---------------------------------------------------------------------------//
// Copyright (c) 2018-2020 Mikhail Komarov <nemo@nil.foundation>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//---------------------------------------------------------------------------//

#ifndef CRYPTO3_NOEKEON_FUNCTIONS_CPP_HPP
#define CRYPTO3_NOEKEON_FUNCTIONS_CPP_HPP

#include <nil/crypto3/detail/basic_functions.hpp>

namespace nil {
namespace crypto3 {
namespace block {
namespace detail {
template<std::size_t WordBits>
struct noekeon_functions : public ::nil::crypto3::detail::basic_functions<WordBits> {
typedef ::nil::crypto3::detail::basic_functions<WordBits> policy_type;
typedef typename policy_type::word_type word_type;

/*
* Noekeon's Theta Operation
*/
inline static void theta(word_type &A0, word_type &A1, word_type &A2, word_type &A3,
const word_type *EK) {
word_type T = A0 ^ A2;
T ^= policy_type::template rotl<8>(T) ^ policy_type::template rotr<8>(T);
A1 ^= T;
A3 ^= T;

A0 ^= EK[0];
A1 ^= EK[1];
A2 ^= EK[2];
A3 ^= EK[3];

T = A1 ^ A3;
T ^= policy_type::template rotl<8>(T) ^ policy_type::template rotr<8>(T);
A0 ^= T;
A2 ^= T;
}

/*
* Theta With Null Key
*/
inline static void theta(word_type &A0, word_type &A1, word_type &A2, word_type &A3) {
word_type T = A0 ^ A2;
T ^= policy_type::template rotl<8>(T) ^ policy_type::template rotr<8>(T);
A1 ^= T;
A3 ^= T;

T = A1 ^ A3;
T ^= policy_type::template rotl<8>(T) ^ policy_type::template rotr<8>(T);
A0 ^= T;
A2 ^= T;
}

/*
* Noekeon's Gamma S-Box Layer
*/
inline static void gamma(word_type &A0, word_type &A1, word_type &A2, word_type &A3) {
A1 ^= ~A3 & ~A2;
A0 ^= A2 & A1;

word_type T = A3;
A3 = A0;
A0 = T;

A2 ^= A0 ^ A1 ^ A3;

A1 ^= ~A3 & ~A2;
A0 ^= A2 & A1;
}
};
} // namespace detail
} // namespace block
} // namespace crypto3
} // namespace nil

#endif // CRYPTO3_NOEKEON_FUNCTIONS_CPP_HPP
46 changes: 46 additions & 0 deletions include/nil/crypto3/block/detail/noekeon/noekeon_policy.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//---------------------------------------------------------------------------//
// Copyright (c) 2018-2020 Mikhail Komarov <nemo@nil.foundation>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//---------------------------------------------------------------------------//

#ifndef CRYPTO3_NOEKEON_POLICY_HPP
#define CRYPTO3_NOEKEON_POLICY_HPP

#include <array>

#include <nil/crypto3/block/detail/noekeon/noekeon_functions.hpp>

namespace nil {
namespace crypto3 {
namespace block {
namespace detail {
struct noekeon_policy : noekeon_functions<32> {
constexpr static const std::size_t rounds = 16;

constexpr static const std::size_t block_bits = 128;
constexpr static const std::size_t block_words = block_bits / word_bits;
typedef std::array<word_type, block_words> block_type;

constexpr static const std::size_t key_bits = 128;
constexpr static const std::size_t key_words = block_bits / word_bits;
typedef std::array<word_type, key_words> key_type;

constexpr static const std::size_t key_schedule_size = 4;
typedef std::array<word_type, key_schedule_size> key_schedule_type;

typedef std::array<byte_type, rounds + 1> constants_type;
constexpr static const constants_type round_constants = {0x80, 0x1B, 0x36, 0x6C, 0xD8, 0xAB,
0x4D, 0x9A, 0x2F, 0x5E, 0xBC, 0x63,
0xC6, 0x97, 0x35, 0x6A, 0xD4};
};

constexpr typename noekeon_policy::constants_type const noekeon_policy::round_constants;
} // namespace detail
} // namespace block
} // namespace crypto3
} // namespace nil

#endif // CRYPTO3_NOEKEON_POLICY_HPP
179 changes: 179 additions & 0 deletions include/nil/crypto3/block/noekeon.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
//---------------------------------------------------------------------------//
// Copyright (c) 2018-2020 Mikhail Komarov <nemo@nil.foundation>
// Copyright (c) 2020 Nikita Kaskov <nbering@nil.foundation>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//---------------------------------------------------------------------------//

#ifndef CRYPTO3_BLOCK_NOEKEON_HPP
#define CRYPTO3_BLOCK_NOEKEON_HPP

#include <boost/endian/arithmetic.hpp>
#include <boost/endian/conversion.hpp>

#include <nil/crypto3/block/detail/noekeon/noekeon_policy.hpp>

#include <nil/crypto3/block/detail/block_stream_processor.hpp>
#include <nil/crypto3/block/detail/cipher_modes.hpp>

namespace nil {
namespace crypto3 {
namespace block {
/*!
* @brief Noekeon. A fast 128-bit cipher by the designers of AES.
* Easily secured against side channels.
*
* @ingroup block
*/
class noekeon {
protected:
typedef detail::noekeon_policy policy_type;

constexpr static const std::size_t key_schedule_size = policy_type::key_schedule_size;
typedef typename policy_type::key_schedule_type key_schedule_type;

public:
constexpr static const std::size_t rounds = policy_type::rounds;

constexpr static const std::size_t word_bits = policy_type::word_bits;
typedef typename policy_type::word_type word_type;

constexpr static const std::size_t block_bits = policy_type::block_bits;
constexpr static const std::size_t block_words = policy_type::block_words;
typedef typename policy_type::block_type block_type;

constexpr static const std::size_t key_bits = policy_type::key_bits;
constexpr static const std::size_t key_words = policy_type::key_words;
typedef typename policy_type::key_type key_type;

template<class Mode, typename StateAccumulator, std::size_t ValueBits>
struct stream_processor {
struct params_type {

constexpr static const std::size_t value_bits = ValueBits;
constexpr static const std::size_t length_bits = policy_type::word_bits * 2;
};

typedef block_stream_processor<Mode, StateAccumulator, params_type> type;
};

typedef typename stream_endian::little_octet_big_bit endian_type;

noekeon(const key_type &key) {
schedule_key(key);
}

~noekeon() {
encryption_key.fill(0);
decryption_key.fill(0);
}

inline block_type encrypt(const block_type &plaintext) const {
return encrypt_block(plaintext);
}

inline block_type decrypt(const block_type &ciphertext) const {
return decrypt_block(ciphertext);
}

protected:
key_schedule_type encryption_key, decryption_key;

inline block_type encrypt_block(const block_type &plaintext) const {
word_type A0 = boost::endian::native_to_big(plaintext[0]);
word_type A1 = boost::endian::native_to_big(plaintext[1]);
word_type A2 = boost::endian::native_to_big(plaintext[2]);
word_type A3 = boost::endian::native_to_big(plaintext[3]);

for (size_t j = 0; j != 16; ++j) {
A0 ^= policy_type::round_constants[j];
policy_type::theta(A0, A1, A2, A3, encryption_key.data());

A1 = policy_type::template rotl<1>(A1);
A2 = policy_type::template rotl<5>(A2);
A3 = policy_type::template rotl<2>(A3);

policy_type::gamma(A0, A1, A2, A3);

A1 = policy_type::template rotr<1>(A1);
A2 = policy_type::template rotr<5>(A2);
A3 = policy_type::template rotr<2>(A3);
}

A0 ^= policy_type::round_constants[16];
policy_type::theta(A0, A1, A2, A3, encryption_key.data());

return {boost::endian::big_to_native(A0), boost::endian::big_to_native(A1),
boost::endian::big_to_native(A2), boost::endian::big_to_native(A3)};
}

inline block_type decrypt_block(const block_type &ciphertext) const {
word_type A0 = boost::endian::native_to_big(ciphertext[0]);
word_type A1 = boost::endian::native_to_big(ciphertext[1]);
word_type A2 = boost::endian::native_to_big(ciphertext[2]);
word_type A3 = boost::endian::native_to_big(ciphertext[3]);

for (size_t j = 16; j != 0; --j) {
policy_type::theta(A0, A1, A2, A3, decryption_key.data());
A0 ^= policy_type::round_constants[j];

A1 = policy_type::template rotl<1>(A1);
A2 = policy_type::template rotl<5>(A2);
A3 = policy_type::template rotl<2>(A3);

policy_type::gamma(A0, A1, A2, A3);

A1 = policy_type::template rotr<1>(A1);
A2 = policy_type::template rotr<5>(A2);
A3 = policy_type::template rotr<2>(A3);
}

policy_type::theta(A0, A1, A2, A3, decryption_key.data());
A0 ^= policy_type::round_constants[0];

return {boost::endian::big_to_native(A0), boost::endian::big_to_native(A1),
boost::endian::big_to_native(A2), boost::endian::big_to_native(A3)};
}

inline void schedule_key(const key_type &key) {
word_type A0 = boost::endian::native_to_big(key[0]);
word_type A1 = boost::endian::native_to_big(key[1]);
word_type A2 = boost::endian::native_to_big(key[2]);
word_type A3 = boost::endian::native_to_big(key[3]);

for (size_t i = 0; i != 16; ++i) {
A0 ^= policy_type::round_constants[i];
policy_type::theta(A0, A1, A2, A3);

A1 = policy_type::template rotl<1>(A1);
A2 = policy_type::template rotl<5>(A2);
A3 = policy_type::template rotl<2>(A3);

policy_type::gamma(A0, A1, A2, A3);

A1 = policy_type::template rotr<1>(A1);
A2 = policy_type::template rotr<5>(A2);
A3 = policy_type::template rotr<2>(A3);
}

A0 ^= policy_type::round_constants[16];

decryption_key[0] = A0;
decryption_key[1] = A1;
decryption_key[2] = A2;
decryption_key[3] = A3;

policy_type::theta(A0, A1, A2, A3);

encryption_key[0] = A0;
encryption_key[1] = A1;
encryption_key[2] = A2;
encryption_key[3] = A3;
}
};
} // namespace block
} // namespace crypto3
} // namespace nil
#endif
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ set(TESTS_NAMES
"rijndael"
"md4"
"md5"
"noekeon"
"shacal"
"shacal2"
)
Expand Down
39 changes: 39 additions & 0 deletions test/noekeon.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//---------------------------------------------------------------------------//
// Copyright (c) 2018-2020 Mikhail Komarov <nemo@nil.foundation>
// Copyright (c) 2020 Nikita Kaskov <nbering@nil.foundation>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//---------------------------------------------------------------------------//

#define BOOST_TEST_MODULE noekeon_cipher_test

#include <iostream>
#include <unordered_map>

#include <boost/test/unit_test.hpp>
#include <boost/test/data/test_case.hpp>
#include <boost/test/data/monomorphic.hpp>

#include <nil/crypto3/block/algorithm/encrypt.hpp>
#include <nil/crypto3/block/algorithm/decrypt.hpp>

#include <nil/crypto3/block/noekeon.hpp>

using namespace nil::crypto3;

BOOST_AUTO_TEST_SUITE(noekeon_test_suite)

BOOST_AUTO_TEST_CASE(noekeon_1) {

std::vector<char> input = {'\xea', '\x02', '\x47', '\x14', '\xad', '\x5c', '\x4d', '\x84'};
std::vector<char> key = {'\xba', '\x69', '\x33', '\x81', '\x92', '\x99', '\xc7', '\x16',
'\x99', '\xa9', '\x9f', '\x08', '\xf6', '\x78', '\x17', '\x8b'};

std::string out = encrypt<block::noekeon>(input, key);

BOOST_CHECK_EQUAL(out, "df1f9b251c0bf45f");
}

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit 0be17f2

Please sign in to comment.