saleks28

kmzi2_feistel

Jan 29th, 2020
324
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.59 KB | None | 0 0
  1. #include "feistel.h"
  2.  
  3. extern size_t errorTimeCounter;
  4.  
  5. namespace feistel
  6. {
  7.      const std::vector<int8_t> spPermutation{ 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 };
  8.      
  9.      std::vector<uint8_t> GetKey()
  10.      {
  11.           std::string sKey;
  12.           std::vector<uint8_t> vKey;
  13.  
  14.           std::cout << "Enter key: ";
  15.           std::cin >> sKey;
  16.  
  17.           for (char& e : sKey)
  18.           {
  19.                vKey.push_back(static_cast<uint8_t>(e));
  20.           }
  21.  
  22.           return vKey;
  23.      }
  24.  
  25.      std::vector<std::vector<uint8_t>> CreateRoundKeys(const std::vector<uint8_t>& key)
  26.      {
  27.           const size_t halfWay = key.size() / 2;
  28.           std::vector<uint8_t> theta1(key.begin(), key.begin() + halfWay);
  29.           std::vector<uint8_t> theta2(key.begin() + halfWay, key.end());
  30.  
  31.           return std::vector<std::vector<uint8_t>>{theta1, theta2, theta1, theta2};
  32.      }
  33.  
  34.      std::vector<uint8_t> SPNetwork(const std::vector<uint8_t> x2,
  35.           const std::vector<uint8_t> roundKey)
  36.      {
  37.           std::vector<uint8_t> spResult(2);
  38.          
  39.           // XOR
  40.           for (size_t i = 0; i < 2; ++i)
  41.           {
  42.                spResult[i] = x2[i] ^ roundKey[i];
  43.           }
  44.          
  45.           // S - block
  46.           uint8_t buffer = 0x0;
  47.           uint8_t s1Result, s2Result, s3Result, s4Result;
  48.          
  49.           s1Result = spPermutation[spResult[0] >> 4];
  50.           s2Result = spPermutation[spResult[0] & 0xF];
  51.           s3Result = spPermutation[spResult[1] >> 4];
  52.           s4Result = spPermutation[spResult[1] & 0xF];
  53.  
  54.           buffer = s1Result;
  55.           buffer <<= 4;
  56.           buffer += s2Result;
  57.           spResult[0] = buffer;
  58.  
  59.           buffer = s3Result;
  60.           buffer <<= 4;
  61.           buffer += s4Result;
  62.           spResult[1] = buffer;
  63.              
  64.           // P - block
  65.           uint16_t pResult = 0x0;
  66.           uint16_t largeBuf = spResult[0];
  67.           largeBuf <<= 8;
  68.           largeBuf += spResult[1];
  69.          
  70.           for (int bit = 32768, j = 0; bit >= 1; bit /= 2, j++)
  71.           {
  72.                if ((bit & largeBuf) == bit)
  73.                {
  74.                     int idx = (13 * j + 1) % 16;
  75.                     pResult |= 32768 >> idx;
  76.                }
  77.           }
  78.  
  79.           spResult[0] = pResult >> 8;
  80.           spResult[1] = pResult & 0xFF;
  81.  
  82.           return spResult;
  83.      }
  84.  
  85.      void MakeWhitening(const std::vector<uint8_t> enteredKey, std::vector<uint8_t>& encryptedBlock)
  86.      {
  87.           std::vector<uint8_t> whiteKey;
  88.  
  89.           const size_t halfWay = enteredKey.size() / 2;
  90.  
  91.           std::vector<uint8_t> theta1(enteredKey.begin(), enteredKey.begin() + halfWay);
  92.           std::vector<uint8_t> theta2(enteredKey.begin() + halfWay, enteredKey.end());
  93.  
  94.           whiteKey.push_back(theta1[0] ^ theta2[0]);
  95.           whiteKey.push_back(theta1[1] ^ theta2[1]);
  96.           whiteKey.push_back(whiteKey[0]);
  97.           whiteKey.push_back(whiteKey[1]);
  98.  
  99.           for (size_t i = 0; i < encryptedBlock.size(); ++i)
  100.           {
  101.                encryptedBlock[i] ^= whiteKey[i];
  102.           }
  103.      }
  104.  
  105.      std::vector<uint8_t> FeistelXOR(const std::vector<uint8_t> x1, const std::vector<uint8_t> x2,
  106.           const std::vector<uint8_t> roundKey)
  107.      {
  108.           std::vector<uint8_t> spResult = SPNetwork(x2, roundKey);
  109.           std::vector<uint8_t> xorResult(2);
  110.  
  111.           for (size_t i = 0; i < 2; ++i)
  112.           {
  113.                xorResult[i] = spResult[i] ^ x1[i];
  114.           }
  115.  
  116.           return xorResult;
  117.      }
  118.  
  119.      std::vector<uint8_t> FeistelNetwork(const std::vector<uint8_t> block,
  120.           const std::vector<std::vector<uint8_t>>& roundKeys)
  121.      {
  122.           const size_t halfWay = block.size() / 2;
  123.           size_t roundCounter = 0;
  124.           std::vector<uint8_t> encryptedBlock;
  125.  
  126.           std::vector<uint8_t> x1(block.begin(), block.begin() + halfWay);
  127.           std::vector<uint8_t> x2(block.begin() + halfWay, block.end());
  128.  
  129.           // X2 || (X1 ^ f(X2))
  130.           for (auto &roundKey: roundKeys)
  131.           {
  132.                // Шаблон раунда
  133.                encryptedBlock.insert(encryptedBlock.begin(), x2.begin(), x2.end());
  134.                std::vector<uint8_t> xorResult = FeistelXOR(x1, x2, roundKey);
  135.                encryptedBlock.insert(encryptedBlock.end(), xorResult.begin(), xorResult.end());
  136.  
  137.                if (roundCounter == 3 || roundCounter == ::errorTimeCounter)
  138.                {
  139.                     return encryptedBlock;
  140.                }
  141.  
  142.                // Меняем x1 и x2
  143.                x1.clear(); x2.clear();
  144.  
  145.                x1.insert(x1.begin(), encryptedBlock.begin(), encryptedBlock.end() - halfWay);
  146.                x2.insert(x2.begin(), encryptedBlock.begin() + halfWay, encryptedBlock.end());
  147.                encryptedBlock.clear();
  148.                
  149.                ++roundCounter;
  150.           }
  151.          
  152.           return encryptedBlock;
  153.      }
  154.  
  155.  
  156.      void EncryptFunction(const std::vector<uint8_t>& plainText, std::vector<uint8_t>& cipherText)
  157.      {
  158.           std::vector<uint8_t> enteredKey = GetKey();
  159.           std::vector<std::vector<uint8_t>> roundKeys(4);
  160.          
  161.           roundKeys = CreateRoundKeys(enteredKey);
  162.  
  163.           for (size_t i = 0; i <= plainText.size() - 4 - (plainText.size()) % 4; i += 4)
  164.           {
  165.                std::vector<uint8_t> bufBlock = { plainText[i], plainText[i + 1],
  166.                     plainText[i + 2], plainText[i + 3] };
  167.  
  168.                std::vector<uint8_t> encryptedBlock = FeistelNetwork(bufBlock, roundKeys);
  169.  
  170.                MakeWhitening(enteredKey, encryptedBlock);
  171.  
  172.                cipherText.insert(cipherText.end(), encryptedBlock.begin(), encryptedBlock.end());
  173.           }
  174.  
  175.           size_t szAddBlock = 32;
  176.  
  177.           if (plainText.size() % 4 != 0)
  178.           {
  179.                szAddBlock = plainText.size() % 4;
  180.                std::vector<uint8_t> bufBlock(plainText.end() - szAddBlock, plainText.end());
  181.  
  182.                while (bufBlock.size() != 4)
  183.                {
  184.                     bufBlock.push_back(static_cast<uint8_t>(0));
  185.                }
  186.                std::vector<uint8_t> encryptedBlock = FeistelNetwork(bufBlock, roundKeys);
  187.  
  188.                MakeWhitening(enteredKey, encryptedBlock);
  189.  
  190.                cipherText.insert(cipherText.end(), encryptedBlock.begin(), encryptedBlock.end());
  191.  
  192.                szAddBlock *= 8;
  193.           }
  194.  
  195.           std::vector<uint8_t> addBlock(4);
  196.           addBlock[0] = szAddBlock >> 24;
  197.           addBlock[1] = (szAddBlock >> 16) & 0xFF;
  198.           addBlock[2] = (szAddBlock >> 8) & 0xFF;
  199.           addBlock[3] = szAddBlock & 0xFF;
  200.  
  201.           std::vector<uint8_t> encryptedBlock = FeistelNetwork(addBlock, roundKeys);
  202.  
  203.           MakeWhitening(enteredKey, encryptedBlock);
  204.  
  205.           cipherText.insert(cipherText.end(), encryptedBlock.begin(), encryptedBlock.end());
  206.  
  207.      }
  208.  
  209.      void DecryptFunction(std::vector<uint8_t>& plainText, const std::vector<uint8_t>& cipherText)
  210.      {
  211.           std::vector<uint8_t> enteredKey = GetKey();
  212.           std::vector<std::vector<uint8_t>> roundKeys(4);
  213.  
  214.           roundKeys = CreateRoundKeys(enteredKey);
  215.           std::reverse(roundKeys.begin(), roundKeys.end());
  216.  
  217.           //Decryption
  218.           for (size_t i = 0; i <= cipherText.size() - 4; i+=4)
  219.           {
  220.                std::vector<uint8_t> encryptedBlock = { cipherText[i], cipherText[i + 1],
  221.                     cipherText[i + 2], cipherText[i + 3] };
  222.  
  223.                MakeWhitening(enteredKey, encryptedBlock);
  224.                
  225.                std::swap(encryptedBlock[0], encryptedBlock[2]);
  226.                std::swap(encryptedBlock[1], encryptedBlock[3]);
  227.  
  228.                encryptedBlock = FeistelNetwork(encryptedBlock, roundKeys);
  229.  
  230.                std::swap(encryptedBlock[0], encryptedBlock[2]);
  231.                std::swap(encryptedBlock[1], encryptedBlock[3]);
  232.  
  233.                if (i == cipherText.size() - 4)
  234.                {
  235.                     size_t szAddBlock = 0;
  236.                     for (size_t j = 0; j < 4; ++j)
  237.                     {
  238.                          szAddBlock += encryptedBlock[j];
  239.                          szAddBlock <<= 8;
  240.                     }
  241.                     szAddBlock /= 8;
  242.  
  243.                     if (szAddBlock == 4)
  244.                          return;
  245.  
  246.                     for (size_t j = 0; j < szAddBlock; ++j)
  247.                     {
  248.                          plainText.pop_back();
  249.                     }
  250.                     return;
  251.                }
  252.                plainText.insert(plainText.end(), encryptedBlock.begin(), encryptedBlock.end());
  253.           }
  254.  
  255.      }
  256.  
  257.  
  258.  
  259. } ///< namespace feistel
Add Comment
Please, Sign In to add comment