Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "feistel.h"
- namespace feistel
- {
- 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<std::vector<uint8_t>> roundKeys(4);
- 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());
- }
- size_t szAddBlock = 32;
- if (plainText.size() % 4 != 0)
- {
- szAddBlock = plainText.size() % 4;
- std::vector<uint8_t> bufBlock(plainText.end() - szAddBlock, plainText.end());
- while (bufBlock.size() != 4)
- {
- bufBlock.push_back(static_cast<uint8_t>(0));
- }
- std::vector<uint8_t> encryptedBlock = FeistelNetwork(bufBlock, roundKeys);
- MakeWhitening(enteredKey, encryptedBlock);
- cipherText.insert(cipherText.end(), encryptedBlock.begin(), encryptedBlock.end());
- szAddBlock *= 8;
- }
- std::vector<uint8_t> addBlock(4);
- addBlock[0] = szAddBlock >> 24;
- addBlock[1] = (szAddBlock >> 16) & 0xFF;
- addBlock[2] = (szAddBlock >> 8) & 0xFF;
- addBlock[3] = szAddBlock & 0xFF;
- std::vector<uint8_t> encryptedBlock = FeistelNetwork(addBlock, roundKeys);
- MakeWhitening(enteredKey, encryptedBlock);
- cipherText.insert(cipherText.end(), encryptedBlock.begin(), encryptedBlock.end());
- }
- } ///< namespace feistel
Add Comment
Please, Sign In to add comment