block: update block concept to take a data view

This commit is contained in:
Danny Robson 2018-12-02 13:45:26 +11:00
parent f1d83c4f8f
commit 38e8aa70d6
9 changed files with 103 additions and 97 deletions

View File

@ -3,7 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
* *
* Copyright 2015 Danny Robson <danny@nerdcruft.net> * Copyright 2015-2018 Danny Robson <danny@nerdcruft.net>
*/ */
#include "tea.hpp" #include "tea.hpp"
@ -15,30 +15,30 @@ using cruft::crypto::block::TEA;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
static const std::uint32_t MAGIC = 0x9E3779B9; static const u32 MAGIC = 0x9E3779B9;
// each iteration performs two feistel rounds, for a total of 64 // each iteration performs two feistel rounds, for a total of 64
static const unsigned ITERATIONS = 32; static const unsigned ITERATIONS = 32;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
TEA::TEA (key_t _key): TEA::TEA (key_t _key)
m_key (_key) : m_key (_key)
{ ; } { ; }
//----------------------------------------------------------------------------- ///////////////////////////////////////////////////////////////////////////////
void void
TEA::encrypt (uint32_t *restrict data, size_t count) TEA::encrypt (cruft::view<word_t*> data)
{ {
if (count % 2) if (data.size () % 2)
throw std::invalid_argument ("TEA requires even data count"); throw std::invalid_argument ("TEA requires even data count");
auto last = data + count; for (auto cursor = data.begin (), last = data.end (); cursor < last; ) {
while (data < last) { word_t sum = 0;
uint32_t sum = 0; word_t v0 = cursor[0];
uint32_t v0 = data[0]; word_t v1 = cursor[1];
uint32_t v1 = data[1];
for (unsigned i = 0; i < ITERATIONS; ++i) { for (unsigned i = 0; i < ITERATIONS; ++i) {
sum += MAGIC; sum += MAGIC;
@ -46,25 +46,23 @@ TEA::encrypt (uint32_t *restrict data, size_t count)
v1 += ((v0 << 4) + m_key[2]) ^ (v0 + sum) ^ ((v0 >> 5) + m_key[3]); v1 += ((v0 << 4) + m_key[2]) ^ (v0 + sum) ^ ((v0 >> 5) + m_key[3]);
} }
*data++ = v0; *cursor++ = v0;
*data++ = v1; *cursor++ = v1;
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void void
TEA::decrypt (uint32_t *restrict data, size_t count) TEA::decrypt (cruft::view<word_t*> data)
{ {
if (count % 2) if (data.size () % 2)
throw std::invalid_argument ("TEA requires even data count"); throw std::invalid_argument ("TEA requires even data count");
auto last = data + count; for (auto cursor = data.begin (), last = data.end (); cursor < last; ) {
word_t sum = MAGIC << 5;
while (data < last) { word_t v0 = cursor[0];
uint32_t sum = MAGIC << 5; word_t v1 = cursor[1];
uint32_t v0 = data[0];
uint32_t v1 = data[1];
for (unsigned i = 0; i < ITERATIONS; ++i) { for (unsigned i = 0; i < ITERATIONS; ++i) {
v1 -= ((v0 << 4) + m_key[2]) ^ (v0 + sum) ^ ((v0 >> 5) + m_key[3]); v1 -= ((v0 << 4) + m_key[2]) ^ (v0 + sum) ^ ((v0 >> 5) + m_key[3]);
@ -72,7 +70,7 @@ TEA::decrypt (uint32_t *restrict data, size_t count)
sum -= MAGIC; sum -= MAGIC;
} }
*data++ = v0; *cursor++ = v0;
*data++ = v1; *cursor++ = v1;
} }
} }

View File

@ -3,30 +3,34 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
* *
* Copyright 2015 Danny Robson <danny@nerdcruft.net> * Copyright 2015-2018 Danny Robson <danny@nerdcruft.net>
*/ */
#ifndef CRUFT_CRYPTO_BLOCK_TEA_HPP #pragma once
#define CRUFT_CRYPTO_BLOCK_TEA_HPP
#include <array> #include <array>
#include <cstdint> #include <cstdint>
#include <cstddef> #include <cstddef>
#include <cruft/util/view.hpp>
#include <cruft/util/std.hpp>
namespace cruft::crypto::block { namespace cruft::crypto::block {
// http://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm /// An implementation of the "Tiny Encryption Algorithm" block cipher.
///
/// ref: http://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm
class TEA { class TEA {
public: public:
using key_t = std::array<uint32_t,4>; using key_t = std::array<u32,4>;
using word_t = u32;
explicit TEA (key_t); explicit TEA (key_t);
void encrypt (uint32_t *restrict data, size_t count); void encrypt (cruft::view<word_t*> data);
void decrypt (uint32_t *restrict data, size_t count); void decrypt (cruft::view<word_t*> data);
private: private:
key_t m_key; key_t const m_key;
}; };
} }
#endif

View File

@ -3,7 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
* *
* Copyright 2015 Danny Robson <danny@nerdcruft.net> * Copyright 2015-2018 Danny Robson <danny@nerdcruft.net>
*/ */
#include "xtea.hpp" #include "xtea.hpp"
@ -12,7 +12,7 @@ using cruft::crypto::block::XTEA;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
static const uint32_t MAGIC = 0x9E3779B9; static const u32 MAGIC = 0x9E3779B9;
// each iteration performs two feistel rounds, for a total of 64 // each iteration performs two feistel rounds, for a total of 64
static const unsigned ITERATIONS = 32; static const unsigned ITERATIONS = 32;
@ -26,17 +26,15 @@ XTEA::XTEA (key_t _key):
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void void
XTEA::encrypt (uint32_t *restrict data, size_t count) XTEA::encrypt (cruft::view<word_t*> data)
{ {
if (count % 2) if (data.size () % 2)
throw std::invalid_argument ("XTEA requires even data count"); throw std::invalid_argument ("XTEA requires even data count");
auto last = data + count; for (auto cursor = data.begin (), last = data.end (); cursor < last; ) {
while (data < last) {
uint32_t sum = 0; uint32_t sum = 0;
uint32_t v0 = data[0]; uint32_t v0 = cursor[0];
uint32_t v1 = data[1]; uint32_t v1 = cursor[1];
for (unsigned i = 0; i < ITERATIONS; ++i) { for (unsigned i = 0; i < ITERATIONS; ++i) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + m_key[sum & 3]); v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + m_key[sum & 3]);
@ -44,25 +42,23 @@ XTEA::encrypt (uint32_t *restrict data, size_t count)
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + m_key[(sum >> 11) & 3]); v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + m_key[(sum >> 11) & 3]);
} }
*data++ = v0; *cursor++ = v0;
*data++ = v1; *cursor++ = v1;
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void void
XTEA::decrypt (uint32_t *restrict data, size_t count) XTEA::decrypt (cruft::view<word_t*> data)
{ {
if (count % 2) if (data.size () % 2)
throw std::invalid_argument ("XTEA requires even data count"); throw std::invalid_argument ("XTEA requires even data count");
auto last = data + count; for (auto cursor = data.begin (), last = data.end (); cursor < last; ) {
while (data < last) {
uint32_t sum = ITERATIONS * MAGIC; uint32_t sum = ITERATIONS * MAGIC;
uint32_t v0 = data[0]; uint32_t v0 = cursor[0];
uint32_t v1 = data[1]; uint32_t v1 = cursor[1];
for (unsigned i = 0; i < ITERATIONS; ++i) { for (unsigned i = 0; i < ITERATIONS; ++i) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + m_key[(sum >> 11) & 3]); v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + m_key[(sum >> 11) & 3]);
@ -70,7 +66,7 @@ XTEA::decrypt (uint32_t *restrict data, size_t count)
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + m_key[sum & 3]); v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + m_key[sum & 3]);
} }
*data++ = v0; *cursor++ = v0;
*data++ = v1; *cursor++ = v1;
} }
} }

View File

@ -3,30 +3,34 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
* *
* Copyright 2015 Danny Robson <danny@nerdcruft.net> * Copyright 2015-2018 Danny Robson <danny@nerdcruft.net>
*/ */
#ifndef CRUFT_CRYPTO_BLOCK_XTEA_HPP #pragma once
#define CRUFT_CRYPTO_BLOCK_XTEA_HPP
#include <array> #include <array>
#include <cstdint> #include <cstdint>
#include <cstddef> #include <cstddef>
#include <cruft/util/std.hpp>
#include <cruft/util/view.hpp>
namespace cruft::crypto::block { namespace cruft::crypto::block {
// http://en.wikipedia.org/wiki/XTEA /// An implementation of the "eXtended TEA" block cipher.
///
/// ref: http://en.wikipedia.org/wiki/XTEA
class XTEA { class XTEA {
public: public:
using key_t = std::array<uint32_t,4>; using key_t = std::array<u32,4>;
using word_t = u32;
explicit XTEA (key_t); explicit XTEA (key_t);
void encrypt (uint32_t *restrict data, size_t count); void encrypt (cruft::view<word_t*> data);
void decrypt (uint32_t *restrict data, size_t count); void decrypt (cruft::view<word_t*> data);
private: private:
key_t m_key; key_t m_key;
}; };
} }
#endif

View File

@ -3,7 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
* *
* Copyright 2015 Danny Robson <danny@nerdcruft.net> * Copyright 2015-2018 Danny Robson <danny@nerdcruft.net>
*/ */
#include "xxtea.hpp" #include "xxtea.hpp"
@ -16,18 +16,18 @@ using cruft::crypto::block::XXTEA;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static const uint32_t MAGIC = 0x9E3779B9; static const u32 MAGIC = 0x9E3779B9;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static constexpr static constexpr
uint32_t u32
mix (uint32_t Z, mix (u32 Z,
uint32_t Y, u32 Y,
uint32_t S, u32 S,
size_t E, std::size_t E,
size_t P, std::size_t P,
const uint32_t *restrict K) const u32 *restrict K)
{ {
return ((Z >> 5 ^ Y << 2) + (Y >> 3 ^ Z << 4)) ^ ((S ^ Y) + (K[(P & 3) ^ E] ^ Z)); return ((Z >> 5 ^ Y << 2) + (Y >> 3 ^ Z << 4)) ^ ((S ^ Y) + (K[(P & 3) ^ E] ^ Z));
} }
@ -41,11 +41,12 @@ XXTEA::XXTEA (key_t _key):
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void void
XXTEA::encrypt (uint32_t *restrict data, size_t count) XXTEA::encrypt (cruft::view<word_t*> data)
{ {
if (count < 2) if (data.size () < 2)
throw std::invalid_argument ("minimum blocksize is 64 bits"); throw std::invalid_argument ("minimum blocksize is 64 bits");
auto const count = data.size ();
uint32_t sum = 0; uint32_t sum = 0;
uint32_t z = data[count - 1]; uint32_t z = data[count - 1];
uint32_t y, p; uint32_t y, p;
@ -58,22 +59,23 @@ XXTEA::encrypt (uint32_t *restrict data, size_t count)
for (p = 0; p < count - 1; p++) { for (p = 0; p < count - 1; p++) {
y = data[p + 1]; y = data[p + 1];
z = data[p] += mix (z, y, sum, e, p, m_key.data ()); z = data[p] += ::mix (z, y, sum, e, p, m_key.data ());
} }
y = data[0]; y = data[0];
z = data[count - 1] += mix (z, y, sum, e, p, m_key.data ()); z = data[count - 1] += ::mix (z, y, sum, e, p, m_key.data ());
} while (--rounds); } while (--rounds);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void void
XXTEA::decrypt (uint32_t *restrict data, size_t count) XXTEA::decrypt (cruft::view<word_t*> data)
{ {
if (count < 2) if (data.size () < 2)
throw std::invalid_argument ("minimum blocksize is 64 bits"); throw std::invalid_argument ("minimum blocksize is 64 bits");
auto const count = data.size ();
uint32_t y, z, sum; uint32_t y, z, sum;
uint32_t rounds; uint32_t rounds;
size_t p; size_t p;
@ -87,11 +89,11 @@ XXTEA::decrypt (uint32_t *restrict data, size_t count)
for (p = count - 1; p > 0; p--) { for (p = count - 1; p > 0; p--) {
z = data[p - 1]; z = data[p - 1];
y = data[p ] -= mix (z, y, sum, e, p, m_key.data ()); y = data[p ] -= ::mix (z, y, sum, e, p, m_key.data ());
} }
z = data[count - 1]; z = data[count - 1];
y = data[ 0] -= mix (z, y, sum, e, p, m_key.data ()); y = data[ 0] -= ::mix (z, y, sum, e, p, m_key.data ());
sum -= MAGIC; sum -= MAGIC;
} while (--rounds); } while (--rounds);

View File

@ -3,32 +3,34 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
* *
* Copyright 2015 Danny Robson <danny@nerdcruft.net> * Copyright 2015-2018 Danny Robson <danny@nerdcruft.net>
*/ */
#ifndef CRUFT_CRYPTO_BLOCKXXTEA_HPP #pragma once
#define CRUFT_CRYPTO_BLOCKXXTEA_HPP
#include <array> #include <array>
#include <cstdint> #include <cstdint>
#include <cstddef> #include <cstddef>
#include <cruft/util/std.hpp>
#include <cruft/util/view.hpp>
namespace cruft::crypto::block { namespace cruft::crypto::block {
// http://en.wikipedia.org/wiki/XXTEA /// An implementation of the "Corrected Block TEA" block cipher.
// 'corrected' block TEA ///
/// ref: http://en.wikipedia.org/wiki/XXTEA
class XXTEA { class XXTEA {
public: public:
using key_t = std::array<uint32_t,4>; using key_t = std::array<u32,4>;
using word_t = u32;
explicit XXTEA (key_t); explicit XXTEA (key_t);
void encrypt (uint32_t *restrict data, size_t count); void encrypt (cruft::view<word_t*> data);
void decrypt (uint32_t *restrict data, size_t count); void decrypt (cruft::view<word_t*> data);
private: private:
key_t m_key; key_t m_key;
}; };
} }
#endif

View File

@ -48,10 +48,10 @@ main ()
TEA gen (t.key); TEA gen (t.key);
std::array<uint32_t,2> enc (t.dec); std::array<uint32_t,2> enc (t.dec);
gen.encrypt (enc.data (), enc.size ()); gen.encrypt (cruft::view (enc));
std::array<uint32_t,2> dec (t.enc); std::array<uint32_t,2> dec (t.enc);
gen.decrypt (dec.data (), dec.size ()); gen.decrypt (cruft::view (dec));
tap.expect (enc == t.enc, "TEA_enc %zu", i); tap.expect (enc == t.enc, "TEA_enc %zu", i);
tap.expect (dec == t.dec, "TEA_dec %zu", i); tap.expect (dec == t.dec, "TEA_dec %zu", i);

View File

@ -46,10 +46,10 @@ main ()
cruft::crypto::block::XTEA gen (t.key); cruft::crypto::block::XTEA gen (t.key);
std::array<uint32_t,2> enc (t.dec); std::array<uint32_t,2> enc (t.dec);
gen.encrypt (enc.data (), enc.size ()); gen.encrypt (cruft::view (enc));
std::array<uint32_t,2> dec (t.enc); std::array<uint32_t,2> dec (t.enc);
gen.decrypt (dec.data (), dec.size ()); gen.decrypt (cruft::view (dec));
tap.expect (enc == t.enc, "XTEA_enc %zu", i); tap.expect (enc == t.enc, "XTEA_enc %zu", i);
tap.expect (dec == t.dec, "XTEA_dec %zu", i); tap.expect (dec == t.dec, "XTEA_dec %zu", i);

View File

@ -104,10 +104,10 @@ main ()
XXTEA gen (t.key); XXTEA gen (t.key);
std::vector<uint32_t> enc (t.dec); std::vector<uint32_t> enc (t.dec);
gen.encrypt (enc.data (), enc.size ()); gen.encrypt (cruft::view (enc));
std::vector<uint32_t> dec (enc); std::vector<uint32_t> dec (enc);
gen.decrypt (dec.data (), dec.size ()); gen.decrypt (cruft::view (dec));
tap.expect (enc == t.enc, "XXTEA_enc %zu", i); tap.expect (enc == t.enc, "XXTEA_enc %zu", i);
tap.expect (dec == t.dec, "XXTEA_dec %zu", i); tap.expect (dec == t.dec, "XXTEA_dec %zu", i);