-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Basic Twofish implementation added #41
- Loading branch information
Showing
6 changed files
with
752 additions
and
0 deletions.
There are no files selected for viewing
304 changes: 304 additions & 0 deletions
304
include/nil/crypto3/block/detail/twofish/basic_twofish_policy.hpp
Large diffs are not rendered by default.
Oops, something went wrong.
76 changes: 76 additions & 0 deletions
76
include/nil/crypto3/block/detail/twofish/twofish_functions.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
//---------------------------------------------------------------------------// | ||
// 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_TWOFISH_FUNCTIONS_CPP_HPP | ||
#define CRYPTO3_TWOFISH_FUNCTIONS_CPP_HPP | ||
|
||
#include <nil/crypto3/block/detail/twofish/basic_twofish_policy.hpp> | ||
|
||
#include <nil/crypto3/detail/basic_functions.hpp> | ||
#include <nil/crypto3/detail/make_uint_t.hpp> | ||
|
||
namespace nil { | ||
namespace crypto3 { | ||
namespace block { | ||
namespace detail { | ||
template<std::size_t KeyBits> | ||
struct twofish_functions : public basic_twofish_policy<KeyBits> { | ||
typedef basic_twofish_policy<KeyBits> policy_type; | ||
typedef typename policy_type::word_type word_type; | ||
|
||
typedef | ||
typename basic_twofish_policy<KeyBits>::expanded_substitution_type expanded_substitution_type; | ||
|
||
inline static void tf_e(word_type A, word_type B, word_type &C, word_type &D, word_type RK1, | ||
word_type RK2, const expanded_substitution_type &SB) { | ||
word_type X = SB[::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(A, 3)] ^ | ||
SB[512 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(A, 1)] ^ | ||
SB[256 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(A, 2)] ^ | ||
SB[768 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(A, 0)]; | ||
word_type Y = SB[::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(B, 0)] ^ | ||
SB[256 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(B, 3)] ^ | ||
SB[512 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(B, 2)] ^ | ||
SB[768 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(B, 1)]; | ||
|
||
X += Y; | ||
Y += X; | ||
|
||
X += RK1; | ||
Y += RK2; | ||
|
||
C = policy_type::template rotr<1>(C ^ X); | ||
D = policy_type::template rotl<1>(D) ^ Y; | ||
} | ||
|
||
inline static void tf_d(word_type A, word_type B, word_type &C, word_type &D, word_type RK1, | ||
word_type RK2, const expanded_substitution_type &SB) { | ||
word_type X = SB[::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(A, 3)] ^ | ||
SB[256 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(A, 2)] ^ | ||
SB[512 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(A, 1)] ^ | ||
SB[768 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(A, 0)]; | ||
word_type Y = SB[::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(B, 0)] ^ | ||
SB[256 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(B, 3)] ^ | ||
SB[512 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(B, 2)] ^ | ||
SB[768 + ::nil::crypto3::detail::extract_uint_t<CHAR_BIT>(B, 1)]; | ||
|
||
X += Y; | ||
Y += X; | ||
|
||
X += RK1; | ||
Y += RK2; | ||
|
||
C = policy_type::template rotl<1>(C) ^ X; | ||
D = policy_type::template rotr<1>(D ^ Y); | ||
} | ||
}; | ||
} // namespace detail | ||
} // namespace block | ||
} // namespace crypto3 | ||
} // namespace nil | ||
|
||
#endif // CRYPTO3_MISTY1_FUNCTIONS_CPP_HPP |
184 changes: 184 additions & 0 deletions
184
include/nil/crypto3/block/detail/twofish/twofish_policy.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
//---------------------------------------------------------------------------// | ||
// 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_TWOFISH_POLICY_HPP | ||
#define CRYPTO3_TWOFISH_POLICY_HPP | ||
|
||
#include <nil/crypto3/block/detail/twofish/twofish_functions.hpp> | ||
|
||
namespace nil { | ||
namespace crypto3 { | ||
namespace block { | ||
namespace detail { | ||
template<std::size_t KeyBits> | ||
struct twofish_policy : public twofish_functions<KeyBits> { }; | ||
|
||
template<> | ||
struct twofish_policy<128> : public twofish_functions<128> { | ||
inline void static schedule_key(const key_type &key, | ||
expanded_substitution_type &expanded_substitution, | ||
key_schedule_type &round_key) { | ||
std::array<byte_type, 16> S = {0}; | ||
|
||
for (size_t i = 0; i != key.size(); ++i) { | ||
/* | ||
* Do one column of the RS matrix multiplication | ||
*/ | ||
if (key[i]) { | ||
byte_type X = poly_to_exp[key[i] - 1]; | ||
|
||
byte_type RS1 = round_substitution[(4 * i) % 32]; | ||
byte_type RS2 = round_substitution[(4 * i + 1) % 32]; | ||
byte_type RS3 = round_substitution[(4 * i + 2) % 32]; | ||
byte_type RS4 = round_substitution[(4 * i + 3) % 32]; | ||
|
||
S[4 * (i / 8)] ^= exp_to_poly[(X + poly_to_exp[RS1 - 1]) % 255]; | ||
S[4 * (i / 8) + 1] ^= exp_to_poly[(X + poly_to_exp[RS2 - 1]) % 255]; | ||
S[4 * (i / 8) + 2] ^= exp_to_poly[(X + poly_to_exp[RS3 - 1]) % 255]; | ||
S[4 * (i / 8) + 3] ^= exp_to_poly[(X + poly_to_exp[RS4 - 1]) % 255]; | ||
} | ||
} | ||
|
||
for (size_t i = 0; i != key_schedule_size / 4; ++i) { | ||
expanded_substitution[i] = mds0[q0[q0[i] ^ S[0]] ^ S[4]]; | ||
expanded_substitution[256 + i] = mds1[q0[q1[i] ^ S[1]] ^ S[5]]; | ||
expanded_substitution[512 + i] = mds2[q1[q0[i] ^ S[2]] ^ S[6]]; | ||
expanded_substitution[768 + i] = mds3[q1[q1[i] ^ S[3]] ^ S[7]]; | ||
} | ||
|
||
for (size_t i = 0; i < expanded_substitution_size; i += 2) { | ||
word_type X = mds0[q0[q0[i] ^ key[8]] ^ key[0]] ^ mds1[q0[q1[i] ^ key[9]] ^ key[1]] ^ | ||
mds2[q1[q0[i] ^ key[10]] ^ key[2]] ^ mds3[q1[q1[i] ^ key[11]] ^ key[3]]; | ||
word_type Y = | ||
mds0[q0[q0[i + 1] ^ key[12]] ^ key[4]] ^ mds1[q0[q1[i + 1] ^ key[13]] ^ key[5]] ^ | ||
mds2[q1[q0[i + 1] ^ key[14]] ^ key[6]] ^ mds3[q1[q1[i + 1] ^ key[15]] ^ key[7]]; | ||
Y = policy_type::template rotl<8>(Y); | ||
X += Y; | ||
Y += X; | ||
|
||
round_key[i] = X; | ||
round_key[i + 1] = policy_type::template rotl<9>(Y); | ||
} | ||
|
||
S.fill(0); | ||
} | ||
}; | ||
|
||
template<> | ||
struct twofish_policy<192> : public twofish_functions<192> { | ||
inline void static schedule_key(const key_type &key, | ||
expanded_substitution_type &expanded_substitution, | ||
key_schedule_type &round_key) { | ||
std::array<byte_type, 16> S = {0}; | ||
|
||
for (size_t i = 0; i != key.size(); ++i) { | ||
/* | ||
* Do one column of the RS matrix multiplication | ||
*/ | ||
if (key[i]) { | ||
byte_type X = poly_to_exp[key[i] - 1]; | ||
|
||
byte_type RS1 = round_substitution[(4 * i) % 32]; | ||
byte_type RS2 = round_substitution[(4 * i + 1) % 32]; | ||
byte_type RS3 = round_substitution[(4 * i + 2) % 32]; | ||
byte_type RS4 = round_substitution[(4 * i + 3) % 32]; | ||
|
||
S[4 * (i / 8)] ^= exp_to_poly[(X + poly_to_exp[RS1 - 1]) % 255]; | ||
S[4 * (i / 8) + 1] ^= exp_to_poly[(X + poly_to_exp[RS2 - 1]) % 255]; | ||
S[4 * (i / 8) + 2] ^= exp_to_poly[(X + poly_to_exp[RS3 - 1]) % 255]; | ||
S[4 * (i / 8) + 3] ^= exp_to_poly[(X + poly_to_exp[RS4 - 1]) % 255]; | ||
} | ||
} | ||
|
||
for (size_t i = 0; i != key_schedule_size / 4; ++i) { | ||
expanded_substitution[i] = mds0[q0[q0[q1[i] ^ S[0]] ^ S[4]] ^ S[8]]; | ||
expanded_substitution[256 + i] = mds1[q0[q1[q1[i] ^ S[1]] ^ S[5]] ^ S[9]]; | ||
expanded_substitution[512 + i] = mds2[q1[q0[q0[i] ^ S[2]] ^ S[6]] ^ S[10]]; | ||
expanded_substitution[768 + i] = mds3[q1[q1[q0[i] ^ S[3]] ^ S[7]] ^ S[11]]; | ||
} | ||
|
||
for (size_t i = 0; i < expanded_substitution_size; i += 2) { | ||
word_type X = mds0[q0[q0[q1[i] ^ key[16]] ^ key[8]] ^ key[0]] ^ | ||
mds1[q0[q1[q1[i] ^ key[17]] ^ key[9]] ^ key[1]] ^ | ||
mds2[q1[q0[q0[i] ^ key[18]] ^ key[10]] ^ key[2]] ^ | ||
mds3[q1[q1[q0[i] ^ key[19]] ^ key[11]] ^ key[3]]; | ||
word_type Y = mds0[q0[q0[q1[i + 1] ^ key[20]] ^ key[12]] ^ key[4]] ^ | ||
mds1[q0[q1[q1[i + 1] ^ key[21]] ^ key[13]] ^ key[5]] ^ | ||
mds2[q1[q0[q0[i + 1] ^ key[22]] ^ key[14]] ^ key[6]] ^ | ||
mds3[q1[q1[q0[i + 1] ^ key[23]] ^ key[15]] ^ key[7]]; | ||
Y = policy_type::template rotl<8>(Y); | ||
X += Y; | ||
Y += X; | ||
|
||
round_key[i] = X; | ||
round_key[i + 1] = policy_type::template rotl<9>(Y); | ||
} | ||
|
||
S.fill(0); | ||
} | ||
}; | ||
|
||
template<> | ||
struct twofish_policy<256> : public twofish_functions<256> { | ||
inline static void schedule_key(const key_type &key, | ||
expanded_substitution_type &expanded_substitution, | ||
key_schedule_type &round_key) { | ||
std::array<byte_type, 16> S = {0}; | ||
|
||
for (size_t i = 0; i != key.size(); ++i) { | ||
/* | ||
* Do one column of the RS matrix multiplication | ||
*/ | ||
if (key[i]) { | ||
byte_type X = poly_to_exp[key[i] - 1]; | ||
|
||
byte_type RS1 = round_substitution[(4 * i) % 32]; | ||
byte_type RS2 = round_substitution[(4 * i + 1) % 32]; | ||
byte_type RS3 = round_substitution[(4 * i + 2) % 32]; | ||
byte_type RS4 = round_substitution[(4 * i + 3) % 32]; | ||
|
||
S[4 * (i / 8)] ^= exp_to_poly[(X + poly_to_exp[RS1 - 1]) % 255]; | ||
S[4 * (i / 8) + 1] ^= exp_to_poly[(X + poly_to_exp[RS2 - 1]) % 255]; | ||
S[4 * (i / 8) + 2] ^= exp_to_poly[(X + poly_to_exp[RS3 - 1]) % 255]; | ||
S[4 * (i / 8) + 3] ^= exp_to_poly[(X + poly_to_exp[RS4 - 1]) % 255]; | ||
} | ||
} | ||
|
||
for (size_t i = 0; i != key_schedule_size / 4; ++i) { | ||
expanded_substitution[i] = mds0[q0[q0[q1[q1[i] ^ S[0]] ^ S[4]] ^ S[8]] ^ S[12]]; | ||
expanded_substitution[256 + i] = mds1[q0[q1[q1[q0[i] ^ S[1]] ^ S[5]] ^ S[9]] ^ S[13]]; | ||
expanded_substitution[512 + i] = mds2[q1[q0[q0[q0[i] ^ S[2]] ^ S[6]] ^ S[10]] ^ S[14]]; | ||
expanded_substitution[768 + i] = mds3[q1[q1[q0[q1[i] ^ S[3]] ^ S[7]] ^ S[11]] ^ S[15]]; | ||
} | ||
|
||
for (size_t i = 0; i < expanded_substitution_size; i += 2) { | ||
word_type X = mds0[q0[q0[q1[q1[i] ^ key[24]] ^ key[16]] ^ key[8]] ^ key[0]] ^ | ||
mds1[q0[q1[q1[q0[i] ^ key[25]] ^ key[17]] ^ key[9]] ^ key[1]] ^ | ||
mds2[q1[q0[q0[q0[i] ^ key[26]] ^ key[18]] ^ key[10]] ^ key[2]] ^ | ||
mds3[q1[q1[q0[q1[i] ^ key[27]] ^ key[19]] ^ key[11]] ^ key[3]]; | ||
word_type Y = mds0[q0[q0[q1[q1[i + 1] ^ key[28]] ^ key[20]] ^ key[12]] ^ key[4]] ^ | ||
mds1[q0[q1[q1[q0[i + 1] ^ key[29]] ^ key[21]] ^ key[13]] ^ key[5]] ^ | ||
mds2[q1[q0[q0[q0[i + 1] ^ key[30]] ^ key[22]] ^ key[14]] ^ key[6]] ^ | ||
mds3[q1[q1[q0[q1[i + 1] ^ key[31]] ^ key[23]] ^ key[15]] ^ key[7]]; | ||
Y = policy_type::template rotl<8>(Y); | ||
X += Y; | ||
Y += X; | ||
|
||
round_key[i] = X; | ||
round_key[i + 1] = policy_type::template rotl<9>(Y); | ||
} | ||
|
||
S.fill(0); | ||
} | ||
}; | ||
} // namespace detail | ||
} // namespace block | ||
} // namespace crypto3 | ||
} // namespace nil | ||
|
||
#endif // CRYPTO3_TWOFISH_POLICY_HPP |
Oops, something went wrong.