Created
January 15, 2016 12:32
-
-
Save thevar1able/20b31ddb32db0dd9408f to your computer and use it in GitHub Desktop.
simple gost28147-89 implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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