Skip to content

Instantly share code, notes, and snippets.

@thevar1able
Created January 15, 2016 12:32
Show Gist options
  • Select an option

  • Save thevar1able/20b31ddb32db0dd9408f to your computer and use it in GitHub Desktop.

Select an option

Save thevar1able/20b31ddb32db0dd9408f to your computer and use it in GitHub Desktop.
simple gost28147-89 implementation
#include <algorithm>
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
#include <bitset>
using namespace std;
std::vector<char> readFile(char* filename) {
ifstream ifs(filename, ios::binary|ios::ate);
ifstream::pos_type pos = ifs.tellg();
std::vector<char> result(pos);
ifs.seekg(0, ios::beg);
ifs.read(&result[0], pos);
return result;
}
inline uint64_t vectorToBits(std::vector<char> data) {
return ((uint64_t)data[0] << 56 & 0xff00000000000000) |
((uint64_t)data[1] << 48 & 0x00ff000000000000) |
((uint64_t)data[2] << 40 & 0x0000ff0000000000) |
((uint64_t)data[3] << 32 & 0x000000ff00000000) |
((uint64_t)data[4] << 24 & 0x00000000ff000000) |
((uint64_t)data[5] << 16 & 0x0000000000ff0000) |
((uint64_t)data[6] << 8 & 0x000000000000ff00) |
((uint64_t)data[7] << 0 & 0x00000000000000ff);
}
inline std::vector<char> bitsToVector(uint64_t data) {
std::vector<char> sym;
sym.push_back((char)(data >> 56));
sym.push_back((char)(data >> 48));
sym.push_back((char)(data >> 40));
sym.push_back((char)(data >> 32));
sym.push_back((char)(data >> 24));
sym.push_back((char)(data >> 16));
sym.push_back((char)(data >> 8));
sym.push_back((char)(data >> 0));
return sym;
}
uint64_t gostBasicStep(uint64_t input, uint32_t key) {
union uData {
uint64_t largeData;
uint32_t dataBlock[2];
};
union uS {
uint32_t s32;
uint8_t s8[4];
};
uint8_t Tab_Z[8][16] = {
0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,
0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,
0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,
0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,
0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,
0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,
0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,
0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF
};
union uData data;
data.largeData = input;
union uS S;
S.s32 = (data.dataBlock[1] + key);
for (uint8_t i = 0; i < 4; i += 2) {
uint8_t t;
t = Tab_Z[i][(S.s8[4 - i/2] >> 4) & 0xf0];
t <<= 4;
t = t | Tab_Z[i + 1][S.s8[4 - i/2] & 0x0f];
S.s8[4 - i/2] = t;
}
S.s32 = (S.s32 << 11) | (S.s32 >> (32 - 11));
S.s32 = S.s32 ^ data.dataBlock[0];
data.dataBlock[0] = data.dataBlock[1];
data.dataBlock[1] = S.s32;
return data.largeData;
}
uint64_t encryptCycle(uint64_t input) {
union uData {
uint64_t largeData;
uint32_t dataBlock[2];
};
union uData data;
data.largeData = input;
uint32_t key[8] =
{
0x0123,
0x4567,
0x89AB,
0xCDEF,
0x0123,
0x4567,
0x89AB,
0xCDEF
};
for (int i = 1; i < 4; ++i) {
for (int j = 0; j < 8; ++j) {
data.largeData = gostBasicStep(data.largeData, key[j]);
}
}
for (int i = 7; i >= 0; i--) {
data.largeData = gostBasicStep(data.largeData, key[i]);
}
swap(data.dataBlock[0], data.dataBlock[1]);
return data.largeData;
}
uint64_t decryptCycle(uint64_t input) {
union uData {
uint64_t largeData;
uint32_t dataBlock[2];
};
union uData data;
data.largeData = input;
uint32_t key[8] =
{
0x0123,
0x4567,
0x89AB,
0xCDEF,
0x0123,
0x4567,
0x89AB,
0xCDEF
};
for (int i = 0; i < 8; ++i) {
data.largeData = gostBasicStep(data.largeData, key[i]);
}
for (int i = 1; i < 4; ++i) {
for (int j = 7; j >= 0; j--) {
data.largeData = gostBasicStep(data.largeData, key[j]);
}
}
swap(data.dataBlock[0], data.dataBlock[1]);
return data.largeData;
}
//
//uint64_t prng(uint64_t prev) {
// union omega {
// uint64_t large;
// uint32_t small[2];
// };
//
// union omega o;
// o.large = prev;
//
// o.small[0] = o.small[0] + 0x01010104 - 1 + 1; //?
// o.small[1] = o.small[1] + 0x01010101;
//
// return o.large;
//}
std::vector<char> encryptData(std::vector<char> data, uint64_t sync) {
std::vector<char> encrypted;
for (int i = 0; i < data.size(); i += 8) {
uint64_t t = vectorToBits(std::vector<char>(data.begin() + i, data.begin() + i + 8));
t = encryptCycle(t);
sync = encryptCycle(sync);
t = t ^ sync;
std::vector<char> sym = bitsToVector(t);
encrypted.insert(encrypted.end(), begin(sym), end(sym));
}
return encrypted;
}
std::vector<char> decryptData(std::vector<char> data, uint64_t sync) {
std::vector<char> decrypted;
for (int i = 0; i < data.size(); i += 8) {
uint64_t t = vectorToBits(std::vector<char>(data.begin() + i, data.begin() + i + 8));
sync = encryptCycle(sync);
t = t ^ sync;
t = decryptCycle(t);
std::vector<char> sym = bitsToVector(t);
decrypted.insert(decrypted.end(), begin(sym), end(sym));
}
return decrypted;
}
int main(int argc, char* argv[]) {
if(argc != 2) {
return 1;
}
std::vector<char> filebuffer = readFile(argv[1]);
for(auto x : filebuffer) {
std::cout<<x;
}
std::cout<<std::endl;
int padding = 8 - (filebuffer.size() % 8);
for (int i = 0; i < padding; ++i) {
filebuffer.push_back(0);
}
uint64_t sync = 0x1a014ff3ca4da1bf;
filebuffer = encryptData(filebuffer, sync);
for(auto x : filebuffer) {
std::cout<<x;
}
std::cout<<std::endl;
filebuffer = decryptData(filebuffer, sync);
for(auto x : filebuffer) {
std::cout<<x;
}
std::cout<<std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment