Skip to content

Instantly share code, notes, and snippets.

@JoogsWasTaken
Created June 22, 2020 17:39
Show Gist options
  • Save JoogsWasTaken/3dbb5254ddb51a5ec6372c65cd700ab2 to your computer and use it in GitHub Desktop.
Save JoogsWasTaken/3dbb5254ddb51a5ec6372c65cd700ab2 to your computer and use it in GitHub Desktop.
Implementation of the FEAL-4 round function
#include <iostream>
#include <cstdint>
#include <array>
#include <string>
#include <sstream>
#include <iomanip>
#define UINT8_BITLEN 8
#define UINT32_BITLEN 32
constexpr char hex_alphabet[16] = { '0', '1', '2', '3', '4', '5', '6',
'7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
// Converts a uint32 into a string containing its hexadecimal
// representation.
std::string to_hex(uint32_t val)
{
std::stringstream stream;
stream << std::setfill('0') << std::setw(8) << std::hex << std::uppercase << val;
return stream.str();
}
// Performs a cyclic left shift on the given uint8 by the amount
// of places specified by count.
uint8_t clsh(uint8_t val, int count)
{
// No shifting is needed if count is zero.
if (count == 0)
{
return val;
}
// Shifts are applied mod 8.
count %= UINT8_BITLEN;
// CLSH = CRSH + 8.
if (count < 0)
{
count += UINT8_BITLEN;
}
int count_inv = UINT8_BITLEN - count;
// Mask the bits that would be overflowing if a normal LSH would be performed.
uint8_t shift_mask = ((1 << count) - 1) << count_inv;
uint8_t overflow_bits = (val & shift_mask) >> count_inv;
// Perform the actual shift.
val <<= count;
// Add the overflow bits back to the original.
val |= overflow_bits;
return val;
}
// Implements the G function of the FEAL-4 cipher.
// G = (a + b + g) (mod 256).
uint8_t g_func(uint8_t a, uint8_t b, uint8_t g)
{
return clsh(a + b + g, 2);
}
// Implements the FEAL-4 round function.
uint32_t round_func(uint32_t x)
{
// Split up input into four 8 bit bytes.
uint8_t x0 = (x >> 24) & 0xff,
x1 = (x >> 16) & 0xff,
x2 = (x >> 8) & 0xff,
x3 = x & 0xff;
// Compute the four 8 bit output bytes.
uint8_t y1 = g_func(x0 ^ x1, x2 ^ x3, 1);
uint8_t y0 = g_func(x0, y1, 0);
uint8_t y2 = g_func(y1, x2 ^ x3, 0);
uint8_t y3 = g_func(y2, x3, 1);
// Merge them all together into one 32 bit output.
uint32_t y = 0;
// Let y0 be the eight LSBs of the 32 bit output.
// Shift to the left so it'll eventually end up at
// the MSB positions.
y |= y0;
y <<= 8;
// Same with y1 and y2.
y |= y1;
y <<= 8;
y |= y2;
y <<= 8;
return y | y3;
}
// Prompts for a hex string that is then fed into a uint32.
uint32_t prompt_uint32_input(std::string prompt)
{
uint32_t i;
bool done = false;
for (std::string line;
std::cout << prompt && std::getline(std::cin, line); )
{
std::istringstream iss(line);
// Trim leading whitespaces, convert from hex to numbers.
// Then check for EOF at end of string.
if (iss >> std::ws >> std::hex >> i && iss.get() == EOF)
{
done = true;
break;
}
std::cerr << "Invalid input '" << line << "'." << std::endl;
}
if (done)
{
return i;
}
std::cerr << "Input preemptively aborted." << std::endl;
return 0;
}
int main(int argc, char** argv)
{
uint32_t a, b;
a = prompt_uint32_input("Input A: ");
b = prompt_uint32_input("Input B: ");
std::cout << std::endl;
std::cout << " A = " << to_hex(a) << std::endl;
std::cout << " B = " << to_hex(a) << std::endl;
std::cout << " A ^ B = " << to_hex(a ^ b) << std::endl;
uint32_t x, y;
x = round_func(a);
y = round_func(b);
std::cout << std::endl;
std::cout << " F(A) = " << to_hex(x) << std::endl;
std::cout << " F(B) = " << to_hex(y) << std::endl;
std::cout << "F(A) ^ F(B) = " << to_hex(x ^ y) << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment