This is the second challenge of Set 1 in The Cryptopals Crypto Challenges website. Previously, I spoke about these challenges and provided a walkthrough for the first challenge, if you haven't read them, here are the links:

For this challenge, you must write a method that takes two strings of fixed equal length and produce their XOR combination:

When you feed the following Hexadecimal string:

1c0111001f010100061a024b53535009181c

And perform an XOR operation against another Hexadecimal string:

686974207468652062756c6c277320657965

The method should return the following result:

746865206b696420646f6e277420706c6179

Like the first challenge, this is sort of a warmup and a simple challenge to tackle. Just to give you a heads up, every challenge that you solve in this set would all make sense, in the end, as the challenges will get tougher and much more interesting.

How do I solve this?

As I mentioned above, this problem is simple and pretty straightforward. In my previous post, I talked about Bitwise Manipulations and it's operators, I will be using the XOR (\^) operator, if you want to know more about it, check out my previous post. Also, I will reuse some of the functions that I had used in the first challenge. So let's dive in to the code:

Methods that are being reused:

//Hashmap that contain hex key and binary values
map<char, string> CryptoLib::gen_hex_table()
{
    map<char, string> map;

    map['0'] = "0000";
    map['1'] = "0001";
    map['2'] = "0010";
    map['3'] = "0011";
    map['4'] = "0100";
    map['5'] = "0101";
    map['6'] = "0110";
    map['7'] = "0111";
    map['8'] = "1000";
    map['9'] = "1001";
    map['a'] = "1010";
    map['b'] = "1011";
    map['c'] = "1100";
    map['d'] = "1101";
    map['e'] = "1110";
    map['f'] = "1111";

    return map;
}

//Convert hex to string
string CryptoLib::con_hex_2_bin(string hexStr)
{
    map<char,string> m = gen_hex_table();

    string newStr = "";
    for(int i=0; i<hexStr.size(); i++)
    {
        if(isdigit(hexStr[i]))
        {
            newStr += m.find(hexStr[i])->second;
        }
        else
        {
            newStr += m.find(hexStr[i])->second;
        }
        // newStr += m.find(hexStr[i])->second;
    }
    return newStr;
}

//Convert binary to decimal
vector<int> CryptoLib::con_bin_2_dec(string str, double power)
{
    vector<int> v;
    string newStr = "";
    istringstream iss(str);
    string x;

    while(iss >> x)
    {
        double p = power;
        double decimal = 0.0;

        for(int i=0; i<x.size(); i++)
        {
            if(x[i] == '1')
            {
                decimal += pow(2.0, p);
            }
            p--;
        }
        v.push_back((int)decimal);
    }
    return v;
}

//Add spaces between strings
string CryptoLib::add_spaces(string str, int spaces)
{
    string newStr = "";
    int count = 0;

    for(int i=0; i<str.size(); i++)
    {

        // newStr += str[i];
        if(count == spaces)
        {
            newStr += " ";
            i--;
            count = 0;
        }
        else
        {
            newStr += str[i];
            count++;
        }
    }

    return newStr;
}

//Convert ASCII to HEX
string CryptoLib::con_ascii_2_hex(string str)
{
    stringstream ss;
    for(int i=0; i<str.size(); i++)
    {
        ss << std::hex << (int)str[i];
    }
    return ss.str();
}

Implementation of the method:

//Fixed XOR implementation
string CryptoLib::fixedXOR(string str1, string str2)
{
    //Check if the length of both the strings are equal
    if(str1.size() != str2.size())
    {
        return "The strings are not of equal length.";
    }
    else
    {
        string newStr = "";

        //Step 1. convert hex to binary of 8 bits
        str1 = add_spaces(con_hex_2_bin(str1), 8);
        str2 = add_spaces(con_hex_2_bin(str2), 8);

        //Step 2. convert binary to decimal
        vector<int> v1 = con_bin_2_dec(str1, 7.0);
        vector<int> v2 = con_bin_2_dec(str2, 7.0);

        //Step 3. XOR the decimals of v1 with decimals of v2
        for(int i=0; i<v1.size(); i++)
        {
            //Get the char of the first string
            unsigned char a = v1[i];

            //Get the char of the second string
            unsigned char b = v2[i];

            //Perform XOR operation against each other
            unsigned char c = a ^ b;

            //Concatenate the string
            newStr += c;
        }

        //ASCII result: the kid don't play.

        //Final result - Convert the ASCII string to Hexadecimal
        return con_ascii_2_hex(newStr); 
    }
}

Final code:

//CryptoPals Set 1 Challenge 2
#include "crypto.h"

int main()
{
    CryptoLib crypt;

    //The test cases provided
    string str1 = "1c0111001f010100061a024b53535009181c";
    string str2 = "686974207468652062756c6c277320657965";

    cout << crypt.fixedXOR(str1, str2) << endl;
    return 0;
}

Note: This solution and the library named crypto.h was built using the C++ programming language. The source code for this solution can be found on Github.

Stay tuned for the next challenge!