Add C++ implementation of Trivium.
This commit is contained in:
parent
a6721cae33
commit
c6c3ef396a
|
@ -5,7 +5,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: ref_xoroshiro ref_mt19937
|
all: ref_xoroshiro ref_mt19937 ref_trivium
|
||||||
|
|
||||||
ref_xoroshiro: ref_xoroshiro.c
|
ref_xoroshiro: ref_xoroshiro.c
|
||||||
$(CC) -std=c11 -Wall -O2 -o $@ $<
|
$(CC) -std=c11 -Wall -O2 -o $@ $<
|
||||||
|
@ -13,7 +13,10 @@ ref_xoroshiro: ref_xoroshiro.c
|
||||||
ref_mt19937: ref_mt19937.cpp
|
ref_mt19937: ref_mt19937.cpp
|
||||||
$(CXX) -std=c++11 -Wall -O2 -o $@ $<
|
$(CXX) -std=c++11 -Wall -O2 -o $@ $<
|
||||||
|
|
||||||
|
ref_trivium: ref_trivium.cpp
|
||||||
|
$(CXX) -std=c++11 -Wall -O2 -o $@ $<
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
$(RM) ref_xoroshiro ref_mt19937
|
$(RM) ref_xoroshiro ref_mt19937 ref_trivium
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
/*
|
||||||
|
* Reference implementation of "Trivium" in C++11.
|
||||||
|
*
|
||||||
|
* Written in 2016 by Joris van Rantwijk <joris@jorisvr.nl>
|
||||||
|
*
|
||||||
|
* To the extent possible under law, the author has dedicated all copyright
|
||||||
|
* and related and neighboring rights to this software to the public domain
|
||||||
|
* worldwide. This software is distributed without any warranty.
|
||||||
|
*
|
||||||
|
* See <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||||
|
*
|
||||||
|
* NOTE: This is a very naive and slow implementation of Trivium,
|
||||||
|
* not suitable for practical use.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <bitset>
|
||||||
|
|
||||||
|
struct trivium_state {
|
||||||
|
std::bitset<93> s1;
|
||||||
|
std::bitset<84> s2;
|
||||||
|
std::bitset<111> s3;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate one random bit and update state.
|
||||||
|
*
|
||||||
|
* Returns: one random bit, value 0 or 1.
|
||||||
|
*/
|
||||||
|
unsigned int trivium_step(struct trivium_state *state)
|
||||||
|
{
|
||||||
|
unsigned int t1 = state->s1[65] ^ state->s1[92];
|
||||||
|
unsigned int t2 = state->s2[68] ^ state->s2[83];
|
||||||
|
unsigned int t3 = state->s3[65] ^ state->s3[110];
|
||||||
|
|
||||||
|
unsigned int z = t1 ^ t2 ^ t3;
|
||||||
|
|
||||||
|
t1 ^= (state->s1[90] & state->s1[91]) ^ state->s2[77];
|
||||||
|
t2 ^= (state->s2[81] & state->s2[82]) ^ state->s3[86];
|
||||||
|
t3 ^= (state->s3[108] & state->s3[109]) ^ state->s1[68];
|
||||||
|
|
||||||
|
state->s1 <<= 1;
|
||||||
|
state->s1[0] = t3;
|
||||||
|
state->s2 <<= 1;
|
||||||
|
state->s2[0] = t1;
|
||||||
|
state->s3 <<= 1;
|
||||||
|
state->s3[0] = t2;
|
||||||
|
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize stream state with given key and IV.
|
||||||
|
*
|
||||||
|
* key: pointer to 10 bytes of key data.
|
||||||
|
* iv: pointer to 10 bytes of IV data.
|
||||||
|
*/
|
||||||
|
void trivium_init(struct trivium_state *state,
|
||||||
|
const unsigned char *key,
|
||||||
|
const unsigned char *iv)
|
||||||
|
{
|
||||||
|
state->s1.reset();
|
||||||
|
state->s2.reset();
|
||||||
|
state->s3.reset();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: The least significant bit of the first byte of the key
|
||||||
|
* is mapped to s_80. The most significant bit of the last
|
||||||
|
* byte of the key is mapped to s_1.
|
||||||
|
*
|
||||||
|
* This is the same as the phase-3, API-compliant version
|
||||||
|
* of Trivium as published on the ECRYPT website (but different
|
||||||
|
* from the original submitted code.)
|
||||||
|
*/
|
||||||
|
for (unsigned int p = 0; p < 10; p++) {
|
||||||
|
for (unsigned int k = 0; k < 8; k++) {
|
||||||
|
state->s1[79-8*p-k] = ((key[p] >> k) & 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: The least significant bit of the first byte of the IV
|
||||||
|
* is mapped to s_173. The most significant bit of the last
|
||||||
|
* byte of the key is mapped to s_94.
|
||||||
|
*/
|
||||||
|
for (unsigned int p = 0; p < 10; p++) {
|
||||||
|
for (unsigned int k = 0; k < 8; k++) {
|
||||||
|
state->s2[79-8*p-k] = ((iv[p] >> k) & 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state->s3[108] = true;
|
||||||
|
state->s3[109] = true;
|
||||||
|
state->s3[110] = true;
|
||||||
|
|
||||||
|
for (int i = 0; i < 4 * 288; i++) {
|
||||||
|
trivium_step(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a small subset of the test vectors from
|
||||||
|
* the ECRYPT stream cipher project.
|
||||||
|
*/
|
||||||
|
static const struct testvec {
|
||||||
|
unsigned char key[10];
|
||||||
|
unsigned char iv[10];
|
||||||
|
} testvecs[5] = {
|
||||||
|
{ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||||
|
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||||
|
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||||
|
{ { 0x00, 0x53, 0xA6, 0xF9, 0x4C, 0x9F, 0xF2, 0x45, 0x98, 0xEB },
|
||||||
|
{ 0x0D, 0x74, 0xDB, 0x42, 0xA9, 0x10, 0x77, 0xDE, 0x45, 0xAC } },
|
||||||
|
{ { 0x05, 0x58, 0xAB, 0xFE, 0x51, 0xA4, 0xF7, 0x4A, 0x9D, 0xF0 },
|
||||||
|
{ 0x16, 0x7D, 0xE4, 0x4B, 0xB2, 0x19, 0x80, 0xE7, 0x4E, 0xB5 } }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
const unsigned int nvec = sizeof(testvecs) / sizeof(testvecs[0]);
|
||||||
|
struct trivium_state state;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < nvec; i++) {
|
||||||
|
|
||||||
|
printf("key =");
|
||||||
|
for (unsigned int p = 0; p < 10; p++)
|
||||||
|
printf(" %02x", testvecs[i].key[p]);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("iv =");
|
||||||
|
for (unsigned int p = 0; p < 10; p++)
|
||||||
|
printf(" %02x", testvecs[i].iv[p]);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
trivium_init(&state, testvecs[i].key, testvecs[i].iv);
|
||||||
|
|
||||||
|
unsigned int np = 0;
|
||||||
|
for (unsigned int p = 0; p < 131072; p++) {
|
||||||
|
|
||||||
|
// Generate 8 random bits.
|
||||||
|
// Map first-generated bit to least significant bit within byte;
|
||||||
|
// last-generated bit to most significant bit.
|
||||||
|
unsigned int t = 0;
|
||||||
|
for (unsigned int k = 0; k < 8; k++) {
|
||||||
|
t = (t >> 1) | (trivium_step(&state) << 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write parts of the output to screen.
|
||||||
|
if (p == 0 || p == 448 || p == 131008) {
|
||||||
|
np = 64;
|
||||||
|
printf("data+%-6d =", p);
|
||||||
|
} else if (np > 0 && np % 16 == 0) {
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
if (np > 0) {
|
||||||
|
printf(" %02x", t);
|
||||||
|
np--;
|
||||||
|
if (np % 16 == 0) {
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue