Upload files to "v1"
This commit is contained in:
261
v1/threefish.d
Normal file
261
v1/threefish.d
Normal file
@@ -0,0 +1,261 @@
|
||||
module angel.utils.cryptography.threefish;
|
||||
|
||||
import std.random : Random, unpredictableSeed, uniform;
|
||||
|
||||
// memcpy
|
||||
extern(C) nothrow @nogc void* memcpy(void* dst, const void* src, size_t n);
|
||||
|
||||
class Threefish512
|
||||
{
|
||||
private {
|
||||
// Размер блока шифра
|
||||
enum blockSize = 64;
|
||||
// Количество 64-битных слов в ключе (и в блоке)
|
||||
enum Nw = 8;
|
||||
// Количество раундов
|
||||
enum Nr = 72;
|
||||
// Количество раундов (за вычетом последнего)
|
||||
enum Ns = Nr / 4;
|
||||
// Функция перестановки
|
||||
uint[8] p = [2, 1, 4, 7, 6, 5, 0, 3];
|
||||
uint[8] p_1 = [6, 1, 0, 7, 2, 5, 4, 3];
|
||||
|
||||
// Функция смешивания и перестановки
|
||||
uint[4][8] r = [
|
||||
[46, 36, 19, 37],
|
||||
[33, 27, 14, 42],
|
||||
[17, 49, 36, 39],
|
||||
[44, 9 , 54, 56],
|
||||
[39, 30, 34, 24],
|
||||
[13, 50, 10, 17],
|
||||
[25, 29, 39, 43],
|
||||
[8 , 35, 56, 22]
|
||||
];
|
||||
|
||||
// Твик-значение (свободный параметр алгоритма)
|
||||
ulong[3] t;
|
||||
// Раундовые ключи
|
||||
ulong[8][Ns + 1] subKeys;
|
||||
|
||||
auto _mix(ref ulong[2] x, ulong r, ref ulong[2] y)
|
||||
{
|
||||
y[0] = x[0] + x[1];
|
||||
y[1] = (x[1] << r) | (x[1] >> (64 - r));
|
||||
y[1] ^= y[0];
|
||||
}
|
||||
|
||||
auto _demix(ref ulong[2] y, ulong r, ref ulong[2] x)
|
||||
{
|
||||
y[1] ^= y[0];
|
||||
x[1] = (y[1] << (64 - r)) | (y[1] >> r);
|
||||
x[0] = y[0] - x[1];
|
||||
}
|
||||
|
||||
alias _mod8 = (ulong a) => a & 7UL;
|
||||
}
|
||||
|
||||
/// Шифрование блока
|
||||
/// plain - указатель на блок для шифрования, c - массив-приемник результата
|
||||
void crypt(ulong* plainData, ulong* c) @system
|
||||
{
|
||||
ulong[8] f;
|
||||
ulong[8] e;
|
||||
ulong[2] y;
|
||||
ulong[2] x;
|
||||
ulong[8] v;
|
||||
uint i;
|
||||
|
||||
memcpy (&v[0], plainData, 64);
|
||||
|
||||
for (uint round = 0; round < Nr; round++)
|
||||
{
|
||||
if (round % 4 == 0)
|
||||
{
|
||||
uint s = round >> 2;
|
||||
|
||||
for (i = 0; i < Nw; i++)
|
||||
{
|
||||
e[i] = v[i] + subKeys[s][i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < Nw; i++)
|
||||
{
|
||||
e[i] = v[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < Nw / 2; i++)
|
||||
{
|
||||
x[0] = e[i * 2];
|
||||
x[1] = e[i * 2 + 1];
|
||||
|
||||
_mix(x, r[cast(uint) _mod8(round)][i], y);
|
||||
|
||||
f[i * 2] = y[0];
|
||||
f[i * 2 + 1] = y[1];
|
||||
}
|
||||
|
||||
for (i = 0; i < Nw; i++)
|
||||
{
|
||||
v[i] = f[p[i]];
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < Nw; i++)
|
||||
{
|
||||
c[i] = v[i] + subKeys[Ns][i];
|
||||
}
|
||||
}
|
||||
|
||||
/// Шифрование блока (безопасная версия)
|
||||
/// plain - массив с данными блока
|
||||
auto crypt(ulong[8] plainData)
|
||||
{
|
||||
ulong[8] c = 0;
|
||||
crypt(plainData.ptr, c.ptr);
|
||||
return c;
|
||||
}
|
||||
|
||||
/// Дешифрование блока
|
||||
/// plain - указатель на блок для дешифрования, c - массив-приемник результата
|
||||
void decrypt(ulong* plainData, ulong* c) @system
|
||||
{
|
||||
ulong[8] f;
|
||||
ulong[8] e;
|
||||
ulong[2] y;
|
||||
ulong[2] x;
|
||||
ulong[8] v;
|
||||
uint i;
|
||||
|
||||
memcpy(&v[0], plainData, 64);
|
||||
|
||||
for (uint round = Nr; round > 0; round--)
|
||||
{
|
||||
if (round % 4 == 0)
|
||||
{
|
||||
uint s = round >> 2;
|
||||
for (i = 0; i < Nw; i++)
|
||||
{
|
||||
f[i] = v[i] - subKeys[s][i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < Nw; i++)
|
||||
{
|
||||
f[i] = v[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < Nw; i++)
|
||||
{
|
||||
e[i] = f[p_1[i]];
|
||||
}
|
||||
|
||||
for (i = 0; i < Nw / 2; i++)
|
||||
{
|
||||
y[0] = e[i * 2];
|
||||
y[1] = e[i * 2 + 1];
|
||||
|
||||
_demix(y, r[cast(uint) _mod8(round - 1)][i], x);
|
||||
|
||||
v[i * 2] = x[0];
|
||||
v[i * 2 + 1] = x[1];
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < Nw; i++)
|
||||
{
|
||||
c[i] = v[i] - subKeys[0][i];
|
||||
}
|
||||
}
|
||||
|
||||
/// Дешифрование блока (безопасная версия)
|
||||
/// plain - массив с данными блока
|
||||
auto decrypt(ulong[8] plain)
|
||||
{
|
||||
ulong[8] c = 0;
|
||||
decrypt(plain.ptr, c.ptr);
|
||||
return c;
|
||||
}
|
||||
|
||||
/// Подготовка раундовых ключей
|
||||
/// keyData - указатель на массив с ключом, tweakData - указатель на массив с твик-значением
|
||||
void setup(ulong* keyData, ulong* tweakData) @system
|
||||
{
|
||||
uint i;
|
||||
ulong[8] K;
|
||||
ulong[2] T;
|
||||
ulong[9] key;
|
||||
|
||||
// C240 constant
|
||||
ulong kNw = 0x1BD11BDAA9FC1A22;
|
||||
|
||||
memcpy(&K[0], &keyData[0], 64);
|
||||
memcpy(&T[0], &tweakData[0], 16);
|
||||
|
||||
for (i = 0; i < Nw; i++)
|
||||
{
|
||||
kNw ^= K[i];
|
||||
key[i] = K[i];
|
||||
}
|
||||
|
||||
key[8] = kNw;
|
||||
|
||||
t[0] = T[0];
|
||||
t[1] = T[1];
|
||||
t[2] = T[0] ^ T[1];
|
||||
|
||||
for (uint round = 0; round <= Ns; round++)
|
||||
{
|
||||
for (i = 0; i < Nw; i++)
|
||||
{
|
||||
subKeys[round][i] = key[(round + i) % (Nw + 1)];
|
||||
|
||||
if (i == Nw - 3)
|
||||
{
|
||||
subKeys[round][i] += t[round % 3];
|
||||
}
|
||||
else if (i == Nw - 2)
|
||||
{
|
||||
subKeys[round][i] += t[(round + 1) % 3];
|
||||
}
|
||||
else if (i == Nw - 1)
|
||||
{
|
||||
subKeys[round][i] += round;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Подготовка раундовых ключей (безопасная версия)
|
||||
/// keyData - указатель на массив с ключом, tweakData - указатель на массив с твик-значением
|
||||
void setup(ulong[8] keyData, ulong[2] tweakData)
|
||||
{
|
||||
setup(keyData.ptr, tweakData.ptr);
|
||||
}
|
||||
|
||||
public static ulong[8] generateKey()
|
||||
{
|
||||
ulong[8] key;
|
||||
auto rng = Random(unpredictableSeed);
|
||||
foreach (i; 0 .. 8)
|
||||
{
|
||||
key[i] = uniform!ulong(rng);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
public static ulong[2] generateTweak()
|
||||
{
|
||||
ulong[2] tweak;
|
||||
auto rng = Random(unpredictableSeed);
|
||||
foreach (i; 0 .. 2)
|
||||
{
|
||||
tweak[i] = uniform!ulong(rng);
|
||||
}
|
||||
return tweak;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user