2021-12-05 15:47:31 +01:00
# include <iostream>
# include <sstream>
# include <array>
2021-12-05 15:58:56 +01:00
# include <bitset>
2021-12-05 15:47:31 +01:00
2021-12-05 16:38:42 +01:00
# define BLOCK_SIZE 128
2021-12-05 15:58:56 +01:00
# define FEISTELBLOCK_SIZE (BLOCK_SIZE / 2)
2021-12-05 18:27:29 +01:00
# define N_ROUNDS 128
2021-12-05 15:47:31 +01:00
2021-12-05 15:58:56 +01:00
typedef std : : bitset < BLOCK_SIZE > Block ;
typedef std : : bitset < FEISTELBLOCK_SIZE > Feistelblock ;
2021-12-05 17:09:01 +01:00
typedef std : : array < Feistelblock , N_ROUNDS > Keyset ;
2021-12-05 15:58:56 +01:00
2021-12-05 16:38:42 +01:00
// Will convert a string to a data block
Block StringToBits ( const std : : string & s ) ;
2021-12-05 15:47:31 +01:00
2021-12-05 16:38:42 +01:00
// Will convert a data block to a string
std : : string BitsToString ( const Block & bits ) ;
2021-12-05 16:15:11 +01:00
// Split a data block into two feistel blocks (into L and R)
std : : pair < Feistelblock , Feistelblock > FeistelSplit ( const Block & block ) ;
// Combine two feistel blocks (L and R) into a regular data block
Block FeistelCombine ( const Feistelblock & l , const Feistelblock & r ) ;
2021-12-05 17:09:01 +01:00
// Will generate a keyset from a seed-key
Keyset GenerateRoundkeys ( const Feistelblock & seedKey ) ;
2021-12-05 16:15:11 +01:00
// Feistel-cipher
2021-12-05 17:09:01 +01:00
Block Feistel ( const Block & data , const Keyset & keys , bool reverseKeyOrder = false ) ;
2021-12-05 16:15:11 +01:00
2021-12-05 18:27:29 +01:00
// Substitutes four bits by static random others
std : : string SBox ( const std : : string & in ) ;
2021-12-05 16:15:11 +01:00
// Arbitrary cipher function
Feistelblock F ( Feistelblock m , const Feistelblock & key ) ;
2021-12-05 15:47:31 +01:00
2021-12-05 17:50:17 +01:00
template < std : : size_t T >
std : : bitset < T > Shiftl ( const std : : bitset < T > & bits , std : : size_t amount ) ;
template < std : : size_t T >
std : : bitset < T > Shiftr ( const std : : bitset < T > & bits , std : : size_t amount ) ;
2021-12-05 18:27:29 +01:00
std : : string DebugPrint ( const std : : string & asciiMessage ) ;
2021-12-05 17:50:17 +01:00
int Mod ( int numerator , int denominator )
{
return ( denominator + ( numerator % denominator ) ) % denominator ;
}
2021-12-05 15:47:31 +01:00
int main ( )
{
2021-12-05 18:27:29 +01:00
const std : : string cipher1 = DebugPrint ( " Hello, World :3 " ) ;
std : : cout < < std : : endl ;
const std : : string cipher2 = DebugPrint ( " Hello, world :3 " ) ;
std : : size_t numDiff = 0 ;
for ( std : : size_t i = 0 ; i < cipher1 . size ( ) ; i + + )
if ( cipher1 [ i ] ! = cipher2 [ i ] )
numDiff + + ;
std : : cout < < std : : endl ;
std : : cout < < " Total difference in C1 and C2: " < < numDiff < < std : : endl ;
return 0 ;
}
2021-12-05 16:38:42 +01:00
2021-12-05 18:27:29 +01:00
std : : string DebugPrint ( const std : : string & asciiMessage )
{
2021-12-05 16:38:42 +01:00
Block message = StringToBits ( asciiMessage ) ;
2021-12-05 16:15:11 +01:00
2021-12-05 17:09:01 +01:00
const Feistelblock seedKey ( StringToBits ( " Ich bin ein PASSWORT-SCHLÜSSEL! " ) . to_string ( ) ) ; // StringToBits returns a bitset that's too large. We have to trim it to fit the smaller FeistelBlock bitset.
2021-12-05 18:27:29 +01:00
Keyset roundkeys = GenerateRoundkeys ( seedKey ) ;
2021-12-05 17:09:01 +01:00
//std::cout << "Keys: " << std::endl;
//for (std::size_t i = 0; i < roundkeys.size(); i++)
// std::cout << roundkeys[i] << std::endl;
//std::cout << "---" << std::endl;
2021-12-05 17:50:17 +01:00
//return 0;
2021-12-05 15:47:31 +01:00
2021-12-05 16:38:42 +01:00
std : : cout < < " Message ascii: " < < asciiMessage < < std : : endl ;
std : : cout < < " Message: " < < message < < std : : endl ;
2021-12-05 15:47:31 +01:00
2021-12-05 17:09:01 +01:00
Block ciphertext = Feistel ( message , roundkeys ) ;
2021-12-05 16:38:42 +01:00
std : : cout < < " Ciphertext: " < < ciphertext < < std : : endl ;
2021-12-05 15:47:31 +01:00
2021-12-05 17:09:01 +01:00
Block decrypted = Feistel ( ciphertext , roundkeys , true ) ;
2021-12-05 16:38:42 +01:00
std : : cout < < " Decrypted: " < < decrypted < < std : : endl ;
const std : : string asciiDecrypted = BitsToString ( decrypted ) ;
std : : cout < < " Decrypted ascii: " < < asciiDecrypted < < std : : endl ;
2021-12-05 15:47:31 +01:00
2021-12-05 18:27:29 +01:00
return ciphertext . to_string ( ) ;
2021-12-05 15:47:31 +01:00
}
2021-12-05 17:09:01 +01:00
Block Feistel ( const Block & data , const Keyset & keys , bool reverseKeyOrder )
2021-12-05 15:47:31 +01:00
{
2021-12-05 16:15:11 +01:00
const auto splitData = FeistelSplit ( data ) ;
Feistelblock l = splitData . first ;
Feistelblock r = splitData . second ;
2021-12-05 15:58:56 +01:00
Feistelblock tmp ;
2021-12-05 15:47:31 +01:00
for ( std : : size_t i = 0 ; i < N_ROUNDS ; i + + )
{
// Calculate key index
std : : size_t keyIndex ;
if ( reverseKeyOrder )
keyIndex = N_ROUNDS - i - 1 ;
else
keyIndex = i ;
// Do a feistel round
tmp = r ;
2021-12-05 15:58:56 +01:00
r = l ^ F ( r , keys [ keyIndex ] ) ;
2021-12-05 15:47:31 +01:00
l = tmp ;
}
2021-12-05 16:15:11 +01:00
return FeistelCombine ( r , l ) ;
2021-12-05 15:47:31 +01:00
}
2021-12-05 15:58:56 +01:00
Feistelblock F ( Feistelblock m , const Feistelblock & key )
2021-12-05 15:47:31 +01:00
{
// Made-up F function
2021-12-05 18:27:29 +01:00
// Shift to left by 1
m = Shiftl ( m , 1 ) ;
2021-12-05 15:47:31 +01:00
// Xor with key
2021-12-05 18:27:29 +01:00
m ^ = key ;
// Non-linearly apply subsitution boxes
std : : stringstream ss ;
const std : : string m_str = m . to_string ( ) ;
for ( std : : size_t i = 0 ; i < m_str . size ( ) ; i + = 4 )
{
ss < < SBox ( m_str . substr ( i , 4 ) ) ;
}
m = Feistelblock ( ss . str ( ) ) ;
return m ;
}
std : : string SBox ( const std : : string & in )
{
if ( in = = " 0000 " ) return " 1100 " ;
else if ( in = = " 0001 " ) return " 1000 " ;
else if ( in = = " 0010 " ) return " 0001 " ;
else if ( in = = " 0011 " ) return " 0111 " ;
else if ( in = = " 0100 " ) return " 1011 " ;
else if ( in = = " 0101 " ) return " 0011 " ;
else if ( in = = " 0110 " ) return " 1101 " ;
else if ( in = = " 0111 " ) return " 1111 " ;
else if ( in = = " 1000 " ) return " 0000 " ;
else if ( in = = " 1001 " ) return " 1010 " ;
else if ( in = = " 1010 " ) return " 0100 " ;
else if ( in = = " 1011 " ) return " 1001 " ;
else if ( in = = " 1100 " ) return " 0010 " ;
else if ( in = = " 1101 " ) return " 1110 " ;
else if ( in = = " 1110 " ) return " 0101 " ;
else /*if (in == "1111")*/ return " 0110 " ;
2021-12-05 15:47:31 +01:00
}
2021-12-05 16:15:11 +01:00
2021-12-05 16:38:42 +01:00
Block StringToBits ( const std : : string & s )
{
std : : stringstream ss ;
for ( std : : size_t i = 0 ; i < s . size ( ) ; i + + )
ss < < std : : bitset < 8 > ( s [ i ] ) ;
// Pad rest with zeores
for ( std : : size_t i = s . size ( ) * 8 ; i < BLOCK_SIZE ; i + + )
ss < < ' 0 ' ;
return Block ( ss . str ( ) ) ;
}
std : : string BitsToString ( const Block & bits )
{
std : : stringstream ss ;
const std : : string bitstring = bits . to_string ( ) ;
for ( std : : size_t i = 0 ; i < BLOCK_SIZE ; i + = 8 )
{
2021-12-05 18:27:29 +01:00
ss < < ( char ) std : : bitset < 8 > ( bitstring . substr ( i , 8 ) ) . to_ulong ( ) ;
2021-12-05 16:38:42 +01:00
}
return ss . str ( ) ;
}
2021-12-05 16:15:11 +01:00
std : : pair < Feistelblock , Feistelblock > FeistelSplit ( const Block & block )
{
const std : : string bits = block . to_string ( ) ;
Feistelblock l ( bits . substr ( 0 , bits . size ( ) / 2 ) ) ;
Feistelblock r ( bits . substr ( bits . size ( ) / 2 ) ) ;
return std : : make_pair ( l , r ) ;
}
Block FeistelCombine ( const Feistelblock & l , const Feistelblock & r )
{
return Block ( l . to_string ( ) + r . to_string ( ) ) ;
}
2021-12-05 17:09:01 +01:00
Keyset GenerateRoundkeys ( const Feistelblock & seedKey )
{
Keyset keys ;
2021-12-05 17:50:17 +01:00
2021-12-05 17:09:01 +01:00
keys [ 0 ] = seedKey ;
2021-12-05 17:50:17 +01:00
keys [ 1 ] = ( Shiftl ( seedKey , 32 ) ^ keys [ 0 ] ) ;
for ( std : : size_t i = 2 ; i < keys . size ( ) ; i + + )
2021-12-05 17:09:01 +01:00
{
2021-12-05 17:50:17 +01:00
keys [ i ] = Shiftl ( keys [ i - 1 ] , i + 32 ) ^ keys [ i - 2 ] ;
2021-12-05 17:09:01 +01:00
}
return keys ;
}
2021-12-05 17:50:17 +01:00
template < std : : size_t T >
std : : bitset < T > Shiftl ( const std : : bitset < T > & bits , std : : size_t amount )
{
std : : stringstream ss ;
const std : : string bitss = bits . to_string ( ) ;
for ( std : : size_t i = 0 ; i < bitss . size ( ) ; i + + )
ss < < bitss [ Mod ( ( i + amount ) , bitss . size ( ) ) ] ;
return std : : bitset < T > ( ss . str ( ) ) ;
}
template < std : : size_t T >
std : : bitset < T > Shiftr ( const std : : bitset < T > & bits , std : : size_t amount )
{
std : : stringstream ss ;
const std : : string bitss = bits . to_string ( ) ;
for ( std : : size_t i = 0 ; i < bitss . size ( ) ; i + + )
ss < < bitss [ Mod ( ( i - amount ) , bitss . size ( ) ) ] ;
return std : : bitset < T > ( ss . str ( ) ) ;
}