crypto: add XXTEA {en,de}cryption.
This commit is contained in:
parent
7f0c7466e4
commit
054dfa918e
@ -29,6 +29,8 @@ UTIL_FILES = \
|
|||||||
crypto/tea.hpp \
|
crypto/tea.hpp \
|
||||||
crypto/xtea.cpp \
|
crypto/xtea.cpp \
|
||||||
crypto/xtea.hpp \
|
crypto/xtea.hpp \
|
||||||
|
crypto/xxtea.cpp \
|
||||||
|
crypto/xxtea.hpp \
|
||||||
crypto/arc4.cpp \
|
crypto/arc4.cpp \
|
||||||
crypto/arc4.hpp \
|
crypto/arc4.hpp \
|
||||||
debug.cpp \
|
debug.cpp \
|
||||||
@ -270,6 +272,7 @@ TEST_BIN = \
|
|||||||
test/crypto/arc4 \
|
test/crypto/arc4 \
|
||||||
test/crypto/tea \
|
test/crypto/tea \
|
||||||
test/crypto/xtea \
|
test/crypto/xtea \
|
||||||
|
test/crypto/xxtea \
|
||||||
test/extent \
|
test/extent \
|
||||||
test/fixed \
|
test/fixed \
|
||||||
test/float \
|
test/float \
|
||||||
|
104
crypto/xxtea.cpp
Normal file
104
crypto/xxtea.cpp
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xxtea.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
// test vectors: http://www.cix.co.uk/~klockstone/teavect.htm
|
||||||
|
|
||||||
|
using util::crypto::XXTEA;
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static const uint32_t MAGIC = 0x9E3779B9;
|
||||||
|
static const unsigned ITERATIONS = 32; // each iteration performs two feistel rounds
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static constexpr uint32_t mix (uint32_t Z,
|
||||||
|
uint32_t Y,
|
||||||
|
uint32_t S,
|
||||||
|
size_t E,
|
||||||
|
size_t P,
|
||||||
|
const uint32_t *restrict K)
|
||||||
|
{
|
||||||
|
return ((Z >> 5 ^ Y << 2) + (Y >> 3 ^ Z << 4)) ^ ((S ^ Y) + (K[(P & 3) ^ E] ^ Z));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
XXTEA::XXTEA (key_t _key):
|
||||||
|
m_key (_key)
|
||||||
|
{ ; }
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
XXTEA::encrypt (uint32_t *restrict data, size_t count)
|
||||||
|
{
|
||||||
|
if (count < 2)
|
||||||
|
throw std::invalid_argument ("minimum blocksize is 64 bits");
|
||||||
|
|
||||||
|
uint32_t sum = 0;
|
||||||
|
uint32_t z = data[count - 1];
|
||||||
|
uint32_t y, e, p;
|
||||||
|
|
||||||
|
unsigned rounds = 6 + 52 / count;
|
||||||
|
|
||||||
|
do {
|
||||||
|
sum += MAGIC;
|
||||||
|
e = (sum >> 2) & 3;
|
||||||
|
|
||||||
|
for (p = 0; p < count - 1; p++) {
|
||||||
|
y = data[p + 1];
|
||||||
|
z = data[p] += mix (z, y, sum, e, p, m_key.data ());
|
||||||
|
}
|
||||||
|
|
||||||
|
y = data[0];
|
||||||
|
z = data[count - 1] += mix (z, y, sum, e, p, m_key.data ());
|
||||||
|
} while (--rounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
XXTEA::decrypt (uint32_t *restrict data, size_t count)
|
||||||
|
{
|
||||||
|
if (count < 2)
|
||||||
|
throw std::invalid_argument ("minimum blocksize is 64 bits");
|
||||||
|
|
||||||
|
uint32_t y, z, sum;
|
||||||
|
unsigned p, rounds, e;
|
||||||
|
|
||||||
|
rounds = 6 + 52 / count;
|
||||||
|
sum = rounds * MAGIC;
|
||||||
|
y = data[0];
|
||||||
|
|
||||||
|
do {
|
||||||
|
e = (sum >> 2) & 3;
|
||||||
|
|
||||||
|
for (p = count - 1; p > 0; p--) {
|
||||||
|
z = data[p - 1];
|
||||||
|
y = data[p ] -= mix (z, y, sum, e, p, m_key.data ());
|
||||||
|
}
|
||||||
|
|
||||||
|
z = data[count - 1];
|
||||||
|
y = data[ 0] -= mix (z, y, sum, e, p, m_key.data ());
|
||||||
|
|
||||||
|
sum -= MAGIC;
|
||||||
|
} while (--rounds);
|
||||||
|
}
|
42
crypto/xxtea.hpp
Normal file
42
crypto/xxtea.hpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __UTIL_TEA_HPP
|
||||||
|
#define __UTIL_TEA_HPP
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace util { namespace crypto {
|
||||||
|
// http://en.wikipedia.org/wiki/XXTEA
|
||||||
|
// 'corrected' block TEA
|
||||||
|
class XXTEA {
|
||||||
|
public:
|
||||||
|
using key_t = std::array<uint32_t,4>;
|
||||||
|
|
||||||
|
XXTEA (key_t);
|
||||||
|
|
||||||
|
void encrypt (uint32_t *restrict data, size_t count);
|
||||||
|
void decrypt (uint32_t *restrict data, size_t count);
|
||||||
|
|
||||||
|
private:
|
||||||
|
key_t m_key;
|
||||||
|
};
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
121
test/crypto/xxtea.cpp
Normal file
121
test/crypto/xxtea.cpp
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
#include "crypto/xxtea.hpp"
|
||||||
|
|
||||||
|
#include "tap.hpp"
|
||||||
|
#include "types.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
// test vectors from 'TeaCrypt', by Logan J. Drews.
|
||||||
|
static const struct {
|
||||||
|
std::array<uint32_t,4> key;
|
||||||
|
std::vector<uint32_t> dec;
|
||||||
|
std::vector<uint32_t> enc;
|
||||||
|
} TESTS[] = {
|
||||||
|
// 64 bit
|
||||||
|
{
|
||||||
|
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
|
||||||
|
{ 0x00000000, 0x00000000 },
|
||||||
|
{ 0x053704AB, 0x575D8C80 }
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||||
|
{0x01020304, 0x05060708},
|
||||||
|
{0xE6911910, 0x0C35DCDA},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
{0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF},
|
||||||
|
{0x01020304, 0x05060708},
|
||||||
|
{0x961D49FC, 0x61FF12D6},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
{0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF},
|
||||||
|
{0x01234567, 0x89ABCDEF},
|
||||||
|
{0x34354989, 0xDD7D1A7A},
|
||||||
|
},
|
||||||
|
|
||||||
|
// 96 bit
|
||||||
|
{
|
||||||
|
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||||
|
{0x00000000, 0x00000000, 0x00000000},
|
||||||
|
{0x5E3CD3F0, 0xE109E3CE, 0x79D7C945},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||||
|
{0x00010203, 0x04050607, 0x08090A0B},
|
||||||
|
{0x5A545AAC, 0x684EB2CB, 0x3E1B8AA0},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
{0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF},
|
||||||
|
{0x00010203, 0x04050607, 0x08090A0B},
|
||||||
|
{0x2E77CCEC, 0x674F5149, 0xA0E56496},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
{0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF},
|
||||||
|
{0x01234567, 0x89ABCDEF, 0x01234567},
|
||||||
|
{0xEBC5DD46, 0xBE0FEE71, 0xC6BF7193},
|
||||||
|
},
|
||||||
|
|
||||||
|
// 128 bit
|
||||||
|
{
|
||||||
|
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||||
|
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||||
|
{0xE6C8D5FF, 0x070FB6E4, 0x98A534F7, 0xAC03E399},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||||
|
{0x00010203, 0x04050607, 0x08090A0B, 0x0C0D0E0F},
|
||||||
|
{0xAF5CFB0E, 0xAE73552B, 0x1D968A9F, 0x5CB94509},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
{0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF},
|
||||||
|
{0x00010203, 0x04050607, 0x08090A0B, 0x0C0D0E0F},
|
||||||
|
{0x3EA0E16C, 0x9969535A, 0xE4796D50, 0xF217EEEA},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
{0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF},
|
||||||
|
{0x01234567, 0x89ABCDEF, 0x01234567, 0x89ABCDEF},
|
||||||
|
{0x2B4AB1A4, 0x0E487B6D, 0x9A3AACC7, 0xE4132216},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
util::TAP::logger tap;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < elems (TESTS); ++i) {
|
||||||
|
const auto &t = TESTS[i];
|
||||||
|
|
||||||
|
CHECK_EQ (t.dec.size (), t.enc.size ());
|
||||||
|
|
||||||
|
util::crypto::XXTEA gen (t.key);
|
||||||
|
|
||||||
|
std::vector<uint32_t> enc (t.dec);
|
||||||
|
gen.encrypt (enc.data (), enc.size ());
|
||||||
|
|
||||||
|
std::vector<uint32_t> dec (enc);
|
||||||
|
gen.decrypt (dec.data (), dec.size ());
|
||||||
|
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
os << "XXTEA_enc " << i;
|
||||||
|
tap.expect (enc == t.enc, os.str ());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
os << "XXTEA_dec " << i;
|
||||||
|
tap.expect (dec == t.dec, os.str ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tap.status ();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user