Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "feistel.h"
- #include <random>
- #include <ios>
- namespace feistel
- {
- constexpr size_t RANDKEY32 = 1;
- constexpr size_t RANDBLOCK32 = 2;
- const std::vector<int8_t> spPermutation{ 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 };
- std::vector<std::vector<uint8_t>> CreateRoundKeys(const std::vector<uint8_t>& key)
- {
- const size_t halfWay = key.size() / 2;
- std::vector<uint8_t> theta1(key.begin(), key.begin() + halfWay);
- std::vector<uint8_t> theta2(key.begin() + halfWay, key.end());
- return std::vector<std::vector<uint8_t>>{theta1, theta2, theta1, theta2};
- }
- std::vector<uint8_t> SPNetwork(const std::vector<uint8_t> x2,
- const std::vector<uint8_t> roundKey)
- {
- std::vector<uint8_t> spResult(2);
- // XOR
- for (size_t i = 0; i < 2; ++i)
- {
- spResult[i] = x2[i] ^ roundKey[i];
- }
- // S - block
- uint8_t buffer = 0x0;
- uint8_t s1Result, s2Result, s3Result, s4Result;
- s1Result = spPermutation[spResult[0] >> 4];
- s2Result = spPermutation[spResult[0] & 0xF];
- s3Result = spPermutation[spResult[1] >> 4];
- s4Result = spPermutation[spResult[1] & 0xF];
- buffer = s1Result;
- buffer <<= 4;
- buffer += s2Result;
- spResult[0] = buffer;
- buffer = s3Result;
- buffer <<= 4;
- buffer += s4Result;
- spResult[1] = buffer;
- // P - block
- uint16_t pResult = 0x0;
- uint16_t largeBuf = spResult[0];
- largeBuf <<= 8;
- largeBuf += spResult[1];
- for (int bit = 32768, j = 0; bit >= 1; bit /= 2, j++)
- {
- if ((bit & largeBuf) == bit)
- {
- int idx = (13 * j + 1) % 16;
- pResult |= 32768 >> idx;
- }
- }
- spResult[0] = pResult >> 8;
- spResult[1] = pResult & 0xFF;
- return spResult;
- }
- void MakeWhitening(const std::vector<uint8_t> enteredKey, std::vector<uint8_t>& encryptedBlock)
- {
- std::vector<uint8_t> whiteKey;
- const size_t halfWay = enteredKey.size() / 2;
- std::vector<uint8_t> theta1(enteredKey.begin(), enteredKey.begin() + halfWay);
- std::vector<uint8_t> theta2(enteredKey.begin() + halfWay, enteredKey.end());
- whiteKey.push_back(theta1[0] ^ theta2[0]);
- whiteKey.push_back(theta1[1] ^ theta2[1]);
- whiteKey.push_back(whiteKey[0]);
- whiteKey.push_back(whiteKey[1]);
- for (size_t i = 0; i < encryptedBlock.size(); ++i)
- {
- encryptedBlock[i] ^= whiteKey[i];
- }
- }
- std::vector<uint8_t> FeistelXOR(const std::vector<uint8_t> x1, const std::vector<uint8_t> x2,
- const std::vector<uint8_t> roundKey)
- {
- std::vector<uint8_t> spResult = SPNetwork(x2, roundKey);
- std::vector<uint8_t> xorResult(2);
- for (size_t i = 0; i < 2; ++i)
- {
- xorResult[i] = spResult[i] ^ x1[i];
- }
- return xorResult;
- }
- std::vector<uint8_t> FeistelNetwork(const std::vector<uint8_t> block,
- const std::vector<std::vector<uint8_t>>& roundKeys)
- {
- const size_t halfWay = block.size() / 2;
- size_t roundCounter = 0;
- std::vector<uint8_t> encryptedBlock;
- std::vector<uint8_t> x1(block.begin(), block.begin() + halfWay);
- std::vector<uint8_t> x2(block.begin() + halfWay, block.end());
- // X2 || (X1 ^ f(X2))
- for (auto &roundKey: roundKeys)
- {
- // Шаблон раунда
- encryptedBlock.insert(encryptedBlock.begin(), x2.begin(), x2.end());
- std::vector<uint8_t> xorResult = FeistelXOR(x1, x2, roundKey);
- encryptedBlock.insert(encryptedBlock.end(), xorResult.begin(), xorResult.end());
- if (roundCounter == 3)
- {
- return encryptedBlock;
- }
- // Меняем x1 и x2
- x1.clear(); x2.clear();
- x1.insert(x1.begin(), encryptedBlock.begin(), encryptedBlock.end() - halfWay);
- x2.insert(x2.begin(), encryptedBlock.begin() + halfWay, encryptedBlock.end());
- encryptedBlock.clear();
- ++roundCounter;
- }
- return encryptedBlock;
- }
- void EncryptFunction(const std::vector<uint8_t> plainText, std::vector<uint8_t>& cipherText, const std::vector<uint8_t>& enteredKey)
- {
- //std::vector<uint8_t> enteredKey = GetKey();
- std::vector<std::vector<uint8_t>> roundKeys(4);
- cipherText.clear();
- roundKeys = CreateRoundKeys(enteredKey);
- for (size_t i = 0; i <= plainText.size() - 4 - (plainText.size()) % 4; i += 4)
- {
- std::vector<uint8_t> bufBlock = { plainText[i], plainText[i + 1],
- plainText[i + 2], plainText[i + 3] };
- std::vector<uint8_t> encryptedBlock = FeistelNetwork(bufBlock, roundKeys);
- MakeWhitening(enteredKey, encryptedBlock);
- cipherText.insert(cipherText.end(), encryptedBlock.begin(), encryptedBlock.end());
- }
- }
- #pragma warning(disable: 4715)
- std::vector<uint8_t> Gen32(size_t randOp)
- {
- const uint32_t low = 0;
- const uint32_t high = UINT32_MAX - 1;
- std::random_device rand_dev;
- std::mt19937 generator(rand_dev());
- std::uniform_int_distribution<uint32_t> distr(low, high);
- if (randOp == RANDKEY32)
- {
- while (1)
- {
- uint32_t bufNum = distr(generator);
- // Weak
- if ((bufNum >> 16) == (bufNum & 0XFFFF))
- {
- return std::vector<uint8_t>{ static_cast<uint8_t>(bufNum >> 24), static_cast<uint8_t>((bufNum >> 16) & 0xFF),
- static_cast<uint8_t>((bufNum >> 8) & 0XFF), static_cast<uint8_t>(bufNum & 0xFF) };
- }
- }
- }
- else if ( randOp == RANDBLOCK32 )
- {
- uint32_t bufNum = distr(generator);
- return std::vector<uint8_t>{ static_cast<uint8_t>(bufNum >> 24), static_cast<uint8_t>((bufNum >> 16) & 0xFF),
- static_cast<uint8_t>((bufNum >> 8) & 0XFF), static_cast<uint8_t>(bufNum & 0xFF) };
- }
- }
- void GroupCryptoAnalysis(time_t& timeStart, time_t& timeEnd)
- {
- time(&timeStart);
- std::cout << "theta1 \ttheta2\t\tT\t x0\t\txT" << std::endl;
- for (size_t i = 0; i < 10; ++i)
- {
- std::vector<uint8_t> v_theta1 = Gen32( RANDKEY32 );
- std::vector<uint8_t> v_theta2 = Gen32( RANDKEY32 );
- std::vector<uint8_t> x0 = Gen32( RANDBLOCK32 );
- std::vector<uint8_t> xT = x0;
- for (uint32_t T = 0; T < UINT32_MAX; ++T)
- {
- EncryptFunction(xT, xT, v_theta1);
- EncryptFunction(xT, xT, v_theta2);
- if (xT == x0)
- {
- uint32_t th1 = 0; uint32_t th2 = 0; uint32_t ux0 = 0; uint32_t uxT = 0;
- for (size_t i = 0; i < 4; ++i)
- {
- th1 += v_theta1[i];
- th2 += v_theta2[i];
- ux0 += x0[i];
- uxT += xT[i];
- th1 <<= 8;
- th2 <<= 8;
- ux0 <<= 8;
- uxT <<= 8;
- }
- std::cout << std::hex << "0x" << th1 << " \t0x" << std::hex << th2 << "\t0x" <<
- std::hex << T << "\t 0x" << std::hex << ux0 << "\t0x" << std::hex << uxT << std::endl;
- break;
- }
- }
- }
- time(&timeEnd);
- }
- } ///< namespace feistel
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement