Skip to content

Instantly share code, notes, and snippets.

@arhadthedev
Created April 24, 2016 06:41
Show Gist options
  • Save arhadthedev/6a8ec1cd62fb90c0b0237d55bb464207 to your computer and use it in GitHub Desktop.
Save arhadthedev/6a8ec1cd62fb90c0b0237d55bb464207 to your computer and use it in GitHub Desktop.
Реализация алгоритма ГОСТ-28147-89 для ЛР №2 по ИБ
#include <cassert>
#include <cstring>
#include <climits>
#include <cstdint>
static uint8_t substitutions[8][16] =
{
{4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3},
{14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9},
{5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11},
{7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3},
{6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2},
{4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14},
{13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12},
{1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12}
};
// http://stackoverflow.com/questions/776508 with template-related modifications
template<class T>
static T rotl(T n, T c)
{
const T mask = (CHAR_BIT * sizeof(n) - 1);
assert((c <= mask) && "rotate by type width or more");
c &= mask; // avoid undef behaviour with NDEBUG. 0 overhead for most types / compilers
return (n << c) | (n >> ((-c) & mask));
}
uint64_t do_round(uint64_t in, uint32_t roundKey)
{
const uint32_t MSBs = in >> 32;
const uint32_t LSBs = in & 0xffffffff;
const uint32_t sBoxIn = (LSBs + roundKey) & UINT_MAX;
const uint32_t sBoxOut
= (substitutions[0][(sBoxIn >> 28) & 0xf] << 28)
| (substitutions[1][(sBoxIn >> 24) & 0xf] << 24)
| (substitutions[2][(sBoxIn >> 20) & 0xf] << 20)
| (substitutions[3][(sBoxIn >> 16) & 0xf] << 16)
| (substitutions[4][(sBoxIn >> 12) & 0xf] << 12)
| (substitutions[5][(sBoxIn >> 8 ) & 0xf] << 8 )
| (substitutions[6][(sBoxIn >> 4 ) & 0xf] << 4 )
| (substitutions[7][(sBoxIn ) & 0xf] );
const uint32_t OutMSBs = LSBs;
const uint32_t OutLSBs = rotl<uint32_t>(sBoxOut, 11) ^ MSBs;
return (static_cast<uint64_t>(OutMSBs) << 32) | OutLSBs;
}
uint64_t GOST_28147_89(uint64_t message, uint32_t (&key)[8])
{
uint64_t buffer = message;
for(size_t round1 = 0; round1 < 3; ++round1)
{
for(size_t round2 = 0; round2 < 8; ++round2)
buffer = do_round(buffer, key[round2]);
}
for(size_t round2 = 0; round2 < 8; ++round2)
buffer = do_round(buffer, key[7 - round2]);
return buffer;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment