Upload files to "v1"

This commit is contained in:
2025-12-22 15:15:42 +00:00
parent d5de70103a
commit cd100b6904
44 changed files with 4420 additions and 0 deletions

261
v1/threefish.d Normal file
View 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;
}
}