block: add initial speck implementation
This commit is contained in:
parent
0f12e8a87c
commit
8c21600805
@ -47,6 +47,8 @@ list (APPEND sources
|
||||
stream/salsa.cpp
|
||||
stream/salsa.hpp
|
||||
|
||||
block/speck.hpp
|
||||
block/speck.cpp
|
||||
block/tea.cpp
|
||||
block/tea.hpp
|
||||
block/xtea.cpp
|
||||
@ -79,6 +81,7 @@ if (TESTS)
|
||||
stream/rc4
|
||||
stream/salsa
|
||||
|
||||
block/speck
|
||||
block/tea
|
||||
block/xtea
|
||||
block/xxtea
|
||||
|
108
block/speck.cpp
Normal file
108
block/speck.cpp
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 2018 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "speck.hpp"
|
||||
|
||||
#include <cruft/util/bitwise.hpp>
|
||||
|
||||
using cruft::crypto::block::speck;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// The round function for the encryption direction.
|
||||
///
|
||||
/// Mutates the x and y values.
|
||||
///
|
||||
/// \param x first data word
|
||||
/// \param y second data word
|
||||
/// \param k key word
|
||||
static void
|
||||
round_enc (u64 &x, u64 &y, u64 const &k)
|
||||
{
|
||||
x = cruft::rotater (x, 8);
|
||||
x += y;
|
||||
|
||||
x ^= k;
|
||||
|
||||
y = cruft::rotatel (y, 3);
|
||||
y ^= x;
|
||||
}
|
||||
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// The round function for the decryption direction
|
||||
///
|
||||
/// Mutates the x and y values.
|
||||
///
|
||||
/// \param x
|
||||
/// \param y
|
||||
/// \param k
|
||||
static void
|
||||
round_dec (u64 &x, u64 &y, u64 const &k)
|
||||
{
|
||||
y ^= x;
|
||||
y = cruft::rotater (y, 3);
|
||||
|
||||
x ^= k;
|
||||
|
||||
x -= y;
|
||||
x = cruft::rotatel (x, 8);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Initialise the key schedule
|
||||
speck::speck (std::array<u64,2> _key)
|
||||
{
|
||||
auto &x = _key[0];
|
||||
auto &y = _key[1];
|
||||
|
||||
// Allocate a space to store the schedule as it's computed
|
||||
std::array<u64,32> schedule;
|
||||
schedule[0] = y;
|
||||
|
||||
// Initialise the key to be indices 0..31
|
||||
std::iota (std::begin (m_key), std::end (m_key), 0);
|
||||
|
||||
// 'encrypt' the key using the index schedule
|
||||
for (int i = 0; i < 31; ++i) {
|
||||
round_enc (x, y, m_key[i]);
|
||||
schedule[i + 1] = y;
|
||||
}
|
||||
|
||||
// Copy the computed schedule back out
|
||||
m_key = schedule;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
std::array<u64,2>
|
||||
speck::encrypt (std::array<u64,2> plaintext) const
|
||||
{
|
||||
u64 &x = plaintext[0];
|
||||
u64 &y = plaintext[1];
|
||||
|
||||
for (int i = 0; i < 32; i++)
|
||||
round_enc (x, y, m_key[i]);
|
||||
|
||||
return { x, y };
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
std::array<u64,2>
|
||||
speck::decrypt (std::array<u64,2> plaintext) const
|
||||
{
|
||||
u64 &x = plaintext[0];
|
||||
u64 &y = plaintext[1];
|
||||
|
||||
for (int i = 0; i < 32; i++)
|
||||
round_dec (x, y, m_key[31 - i]);
|
||||
|
||||
return { x, y };
|
||||
}
|
41
block/speck.hpp
Normal file
41
block/speck.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 2018 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <array>
|
||||
|
||||
#include <cruft/util/std.hpp>
|
||||
#include <cruft/util/view.hpp>
|
||||
|
||||
namespace cruft::crypto::block {
|
||||
//template <
|
||||
// std::size_t KeyBitsV,
|
||||
// std::size_t BlockBitsV
|
||||
//>
|
||||
/// An implementation of the Speck block cipher.
|
||||
/// doi: 10.1145/2744769.2747946
|
||||
///
|
||||
/// TODO: The block and key sizes are currently hard coded to 128 and 128
|
||||
/// for ease of initial implementation. They should be parameters.
|
||||
class speck {
|
||||
public:
|
||||
using key_t = std::array<u64,2>;
|
||||
using word_t = u64;
|
||||
static constexpr auto block_size = sizeof (word_t) * 2;
|
||||
|
||||
explicit speck (key_t);
|
||||
|
||||
std::array<word_t,2> encrypt (std::array<word_t,2> src) const;
|
||||
std::array<word_t,2> decrypt (std::array<word_t,2> src) const;
|
||||
|
||||
private:
|
||||
std::array<u64,32> m_key;
|
||||
};
|
||||
}
|
23
test/block/speck.cpp
Normal file
23
test/block/speck.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include <cruft/util/tap.hpp>
|
||||
|
||||
#include "block/speck.hpp"
|
||||
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
cruft::TAP::logger tap;
|
||||
|
||||
{
|
||||
// speck128/128 test vectors from the IACR paper.
|
||||
std::array<u64,2> const key { 0x0f0e0d0c0b0a0908, 0x0706050403020100 };
|
||||
std::array<u64,2> const dec { 0x6c61766975716520, 0x7469206564616d20 };
|
||||
std::array<u64,2> const enc { 0xa65d985179783265, 0x7860fedf5c570d18 };
|
||||
|
||||
cruft::crypto::block::speck const cipher (key);
|
||||
tap.expect (cipher.encrypt (dec) == enc, "speck128/128 encode");
|
||||
tap.expect (cipher.decrypt (enc) == dec, "speck128/128 decode");
|
||||
}
|
||||
|
||||
return tap.status ();
|
||||
}
|
Loading…
Reference in New Issue
Block a user