megacolorboy

Abdush Shakoor's Weblog

Writings, experiments & ideas.

Convert IIS web.config to Apache .htaccess using Javascript

Last week, I built a small tool that converts IIS web.config to Apache .htaccess using Javascript

Last week, I was migrating my company's website from our in-house IIS Virtual Private Server to a Dedicated Apache Server in order to improve the website's overall performance and handle more traffic efficiently. For those of you who have hosted a website using Microsoft's IIS Manager, you'll know that it makes use of an XML document named web.config file, whereas in an Apache Server, it's an .htaccess file, which is also used to store rules to write clean and friendly URLs.

Converting from .htaccess to web.config is easy as it's a matter of importing the rules directly on IIS Manager's URL Rewrite module but doing the other way around was also possible but only if you did it manually and I really don't want to waste time on such mundane tasks.

How did I convert it?

A little bit of Regular Expressions, a dash of Javascript and an understanding on how Apache's mod_rewrite works, I decided to build a tool that converts web.config to .htaccess format.

How to use this converter:

  • Paste your web.config XML code on the textfield
  • Hit "Convert" to convert to .htaccess format
  • Please use a valid XML format before converting your code

Code snippet:

//web.config to .htaccess converter
function webConfigToHtaccess()
{

    // Take input from textarea
    // and parse it into XML

    var xml = $("#webconfig-xml").val(), 
    xmlDoc = $.parseXML(xml), 
    $xml = $(xmlDoc);


    // - Inside each "rule", look for the "action" child node
    // - If it contains multiple parameters, follow the 
    // regular expression pattern: /{R:(d{1})}/
    // - Replace that pattern with a dollar sign and it's parameter
    // - Append "RewriteRule" along with the url and it's rules

    $xml.find('rule').each(function(){
        var str = $(this).find("rule>action").attr('url');
        var regex = /{R:(d{1})}/;
        while(regex.test(str))
        {
            str = str.replace(regex, '$' + RegExp.$1);
        }

        $("#htaccess-code").append("RewriteRule " + $(this).find("rule>match").attr('url')
            + " " + str + "<br>"
        );
    });
}

Although, I can't really say that it's perfect because I had to make some changes but hey, it's just minor changes and yes, it did save me a lot of time!

Hope you found this article useful!

Convert SVG from Image to Code using Javascript

Two weeks ago, I wrote a small script to convert SVG from Image to Code using Javascript that allowed me to play around with it's attributes and properties.

Have you ever downloaded minimal and beautiful looking SVG icons and added them into your HTML code as an <img> instead of <svg> tag? The answer is: "yes, you're right!".

Okay, how about another question?

What would you do if you want to change all of those SVG icons to black, red or blue? Your answer would be: "Well, I would edit the colors of all the vector images in Adobe Illustrator and then refresh my page to see the changes.", if that's your answer, then what would you do if you have to do it for multiple icons in multiple pages in a short amount of time?

Two weeks ago, I faced this same scenario and I found a quick solution to it and I will be sharing it in this article on how to convert SVG from image to code using Javascript and how it allowed me to play around with attributes and properties.

Why convert from Image to Code?

Well, as a developer, it allows me to interact with every part of the SVG such as changing the colors, adjusting the height and width, animate it and so on. In this article, I will show you an example on how I could do a simple color change on an SVG image that I had downloaded from flaticon.

Figure 1. Original SVG Space Icon

How to convert from Image to Code?

Simple, just convert the SVG image into an XML format using XMLSerializer() then give it a class name like "custom-svg-icon" and execute the code! Below, I have provided a code snippet, I hope the comments will help you out!

Code snippet:

    $(function(){
     //Change the class name, if it has to be applied for more SVG elements
     jQuery('img.custom-svg-icon').each(function(){
     var $img = jQuery(this); // The image
     var imgID = $img.attr('id'); // ID attribute
     var imgClass = $img.attr('class'); // Class Name
     var imgURL = $img.attr('src'); // URL of the SVG image

     jQuery.get(imgURL, function(data) {
     //The data param contains the XML data of the SVG image
     //alert(new XMLSerializer().serializeToString(data));

     // Get the SVG tag, ignore the rest
     var $svg = jQuery(data).find('svg');

     // Give the image's ID to the SVG
     if(typeof imgID !== 'undefined') 
     {
     $svg = $svg.attr('id', imgID);
     }

     // Give the image's class to the SVG
     if(typeof imgClass !== 'undefined') 
     {
     $svg = $svg.attr('class', imgClass+' replaced-svg');
     }

     // Remove any invalid XML tags as per http://validator.w3.org
     $svg = $svg.removeAttr('xmlns:a');

     // Check if the viewport is set, else we gonna set it if we can.
     if(!$svg.attr('viewBox') && $svg.attr('height') && $svg.attr('width')) 
     {
     $svg.attr('viewBox', '0 0 ' + $svg.attr('height') + ' ' + $svg.attr('width'))
     }

     // Replace image with new SVG
     $img.replaceWith($svg);

     }, 'xml'); //Returns as XML
     });
    });

Give it some custom CSS to change the color and width of the SVG image:

    svg path, svg rect
    {
        fill: #ff5a5f;
    }

    .custom-svg-icon
    {
        width: 170px;
        height: 170px;
    }

Right-click on the image, hit "Inspect Element" and view the converted image below but this time, you'll see it as an SVG element:

Figure 2. Converted SVG Space Icon

However, there are a few downsides to this as SVG code is hard to maintain, pretty messy and sometimes quite complex especially if it contains a lot of paths, circles and rectangles but in a scenario that is similar to what I have faced, I think it's pretty useful, otherwise, just stick to adding your SVG images using the <img> tag.

Hope you have found this article useful!

Credit

Icons made by Eucalyp from www.flaticon.com is licensed by CC 3.0 BY

I decided to learn Python

I decided to get back on solving algorithmic and programming puzzles by adding a new programming language to my tech arsenal, Python.

Hello Folks!

Happy New Year! I know I'm late at this point but hey, it's better late than never!

As the year had begun, I got busy with work and I barely found any time to post anything new but that doesn't mean I didn't do anything new.

At the end of December, I decided to get back on solving algorithmic and programming puzzles again (The last time I did was back on 2016) and for starters, I decided to solve Project Euler problems by adding a new programming language to my tech arsenal, Python.

Why solve it using Python?

Previously, I'd solved around 57 problems using C++ and it got paused for a while after I got into internships and work life. But now that I have found the time for it, I thought that this would be the perfect opportunity for me to learn Python. It has a really good community, good documentation and the code looks so clean, simple and readable without those curly brackets!

What is Project Euler?

It's a website that hosts a series of challenging algorithmic and mathematical programming puzzles in which you will have to produce solutions that'd clock in under a minute with decent computer specifications.

By solving these puzzles, you will be experiencing an inductive chain learning i.e. when you solve one problem, you'll be exposed to a completely new concept that allows you to delve into unfamiliar areas of mathematics and programming.

As I'm writing this article, I'm taking it slow and I have solved around 21 problems in 3 weekends. I will be posting a walkthrough for each problem but for now, I will talk about one of my favorite problems: Maximum Path Sum.

Maximum Path Sum

Problem definition of Problem 18:

By starting at the top of the Binary Tree below and moving to adjacent numbers on the row below, the maximum total from top to bottom is 23.

3
7 4
2 4 6
8 5 9 3

That is, 3 + 7 + 4 + 9 = 23. Now, find the maximum total from top to bottom of the Binary Tree below:

75
95 64
17 47 82
18 35 87 10
20 04 82 47 65
19 01 23 75 03 34
88 02 77 73 07 63 67
99 65 04 28 06 16 70 92
41 41 26 56 83 40 80 70 33
41 48 72 33 47 32 37 16 94 29
53 71 44 65 25 43 91 52 97 51 14
70 11 33 28 77 73 17 78 39 68 17 57
91 71 52 38 17 14 91 43 58 50 27 29 48
63 66 04 68 89 53 67 30 73 16 69 87 40 31
04 62 98 27 23 09 70 98 73 93 38 53 60 04 23

Since there are fifteen rows, you can solve this puzzle using Brute Force by trying every route possible but if you're going to use that same technique for Problem 67 that has a Binary Tree containing one hundred rows, it will not be efficient. So this problem forces you to avoid brute force and instead wants you to come up with a clever solution!

Solution

As I had mentioned above, a brute force technique is going to be very inefficient, instead I did a bottom-up approach:

Implementation of the method(s):

# Sum of numbers
def sumOfNumbers(n):
    return (n*(n+1))/2

# Return the maximum path sum in a Binary Tree
# Bottom Up Approach
def maxPathSum(list):
    # the last number of the list
    last = len(list)

    # number of rows in the Binary Tree
    nrow = 1

    # count the number of rows in the Binary Tree
    # use the sum of numbers method to count the number of rows
    while sumOfNumbers(nrow) < last:
        # print (sumOfNumbers(nrow))
        nrow += 1

    last -= 1

    for i in range(nrow, 0, -1):
        # print list[last - i]

        # iterate through each number in each row
        for j in range(2, i+1):
            # pick a number from the row above the current row
            # and pick the 2 numbers from the current row
            # Find the max between the two numbers and add it
            list[last - i] = list[last - i] + max(list[last - 1], list[last])

            # shift to the next number in the row above
            last -= 1

        # shift to the next number in the row above
        last -= 1

    # return the max sum
    return list[0]

Final code:

# Project Euler: Problem 18 and 67 - Maximum Path Sum I and II

#!usr/bin/python
import time, math, pe_lib

num_str = ""

# read text file
f = open("triangle2.txt", "r")
for line in f:
    num_str += line
f.close()

# convert the string numbers to integers in the list
list = map(int, num_str.replace('n', ' ').split(' '))

start = time.time()
print pe_lib.maxPathSum(list)
print "Finished: %f seconds" % (time.time() - start)

The maximum path sum for Problem 67 is 7273 and it compiled in 0.003990 seconds.

Note: This solution and the library named pe_lib.py was built using the Python programming language. The source code for this solution can be found on Github.

Stay tuned for more!

The Cryptopals Crypto Challenges: Set 1 - Detect AES in ECB Mode

Find the string that has been encrypted with AES-128 cipher with an ECB mode in a file of ciphertexts.

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

For this challenge, you are given a file, which contains a bunch of ciphertexts that has been encrypted using AES-128 Cipher but only one of them has an ECB (Electronic Codebook) mode. Find the string the string that has the ECB mode.

In the previous post, I had explained that ECB is a cipher mode that is used to repeat the key until it covers the entire plaintext i.e. the same 16 byte plaintext will have the same 16 byte ciphertext.

Well, the solution is pretty much trivial, so here's the solution:

Implementation of the method(s):

//Detect ECB Mode in AES Cipher
bool CryptoLib::detect_ecb_mode(string str, int keyLength)
{
    //Divide into equal amount of blocks
    int blocks = str.size() / keyLength;

    /*
        Theory: the problem with ECB as I had mentioned
        in the previous post, it uses the exact number of bytes of the ciphertext
        to encrypt the plaintext repeatedly.

        In that case, just do the reverse.

        Divide it into equal amount of blocks, in this case, we
        know the key is "YELLOW SUBMARINE", which is 16 bytes.

        Then, all you have to do is take two substrings of a string and compare,
        if they have the same string, we found it!
    */
    for(int i=0; i<blocks; i++)
    {
        //Take a substring of x number of bytes
        string strA = str.substr(i*keyLength, keyLength);

        for(int j=i+1; j<blocks; j++)
        {
            //Take another substring of x number of bytes
            string strB = str.substr(j*keyLength, keyLength);
            if(strA == strB)
            {
                //Found
                return true;
            }
        }
    }
    return false;
}

Final code:

//The Cryptopals Crypto Challenges - Set 1 Challenge 8
#include "crypto.h"

int main()
{
    CryptoLib crypt;

    string str;

    ifstream infile;
    infile.open("8.txt");

    int count = 0;
    while(!infile.eof())
    {
        getline(infile, str);

        //Check if this string has ECB mode
        if(crypt.detect_ecb_mode(str, 16) == true)
        {
            cout << "FOUND AT LINE " << count << " => " << str << endl;
            break;
        }
        count++;
    }
}

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.

Well, this challenge marks the end of Set 1 from The Cryptopals Crypto Challenges. However, I do intend to continue solving all these crypto challenges, let's see how it goes!

Until next time, then!

The Cryptopals Crypto Challenges: Set 1 - AES in ECB Mode

Decrypt a Base64 encoded file that is encrypted with an AES-128 Cipher in ECB mode.

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

For this challenge, you are given a file, which contains a ciphertext that has been encrypted using AES-128 Cipher with ECB (Electronic Codebook) mode and then encoded using Base64. Decrypt it.

In order to decrypt it, you are given a key:

YELLOW SUBMARINE

What is AES?

Advanced Encryption Standard a.k.a Rjindael, which was developed by two belgian cryptographers, Vincent Rijmen and Joan Daemen. Rjindael is a family of ciphers with various block and key sizes.

AES-128 is commonly used but there are also larger key sizes such as 192 and 256 bits. Similar to XOR cipher, it uses the same key to encrypt and decrypt the message. Till date, there isn't any publication that states if whether AES is broken but even if you were to break it, it will take atleast a billion years with a supercomputer, which could beyond the age of the universe.

What is ECB Mode?

What if your plaintext is longer than (in this case, 128 bits) the keysize? This is where ECB comes into the picture. ECB (Electronic Codebook) is a cipher mode that is used to repeat the key until it covers the entire plaintext (similar to Repeating-Key XOR Cipher) and then each block is independently encrypted using the AES algorithm to produce the desired ciphertext.

This challenge is not that hard, in fact, it's completely trivial and more like an introduction of AES Cipher. There are so many ways to solve this problem but I chose to solve this problem using OpenSSL and other commandline tools such as xxd (used to print the hexdump of a file) on my UNIX terminal.

Here's the solution:

openssl enc -aes-128-ecb -d -a -in secret.txt -K $(echo "YELLOW SUBMARINE" | xxd -p) -iv 1 | head

This is the decrypted message:

I'm back and I'm ringin' the bell
A rockin' on the mike while the fly girls yell
In ecstasy in the back of me
Well that's my DJ Deshay cuttin' all them Z's
Hittin' hard and the girlies goin' crazy
Vanilla's on the mike, man I'm not lazy.

I'm lettin' my drug kick in
It controls my mouth and I begin
To just let it flow, let my concepts go

Initially, I was planning to write an implementation of AES for fun, but then I decided to make it a side project that I can work on as there are a lot of things about AES that I'd like to talk about in the future.

Stay tuned for the next challenge!

Hamming Distance Algorithm in C++

An article about the Hamming Distance algorithm that will be used in the next challenge.

This is a short article about the Hamming Distance algorithm, which will be used in The Cryptopals Crypto Challenges: Set 1 - Break Repeating-Key XOR challenge.

In Challenge 6, the first step states that you have to write a function to compute the edit distance/Hamming distance between two strings:

this is a test

And

wokka wokka!!!

When this function is executed, the expected result must be 37. If you we're able to make this function work, you can proceed with the next steps in the challenge.

What is Hamming Distance?

Applied in domains like Cryptography, Information theory and Coding theory, Hamming distance is just the number of differing bits between two strings of equal length. Named after the American Mathematician, Richard Hamming, this algorithm mainly used for Error Detection and Error Correction (and yes, this also makes use of Bitwise Operators).

Using the example above, let's see how this works, in theory:

ASCII Format: this is a test
Binary Format: 011101[0][0] 01101[0][0][0] 011010[0]1 011[1][0]011 0[0]10000[0] 0[1]10[1]00[1] 01110[0]11 0[0]10[0][0][0][0] 0110[0]0[0]1 0[0]10[0]0[0][0] 011[1]0[1]0[0] 0[1]100[1]01 0[1]1[1]00[1]1 0[1]1[1]0[1]0[0]

ASCII Format: wokka wokka!!!
Binary Format: 011101[1][1] 01101[1][1][1] 011010[1]1 011[0][1]011 0[1]10000[1] 0[0]10[0]00[0] 01110[1]11 0[1]10[1][1][1][1] 0110[1]0[1]1 0[1]10[1]0[1][1] 011[0]0[0]0[1] 0[0]100[0]01 0[0]1[0]00[0]1 0[0]1[0]0[0]0[1]

As per the given example, when you count the number of differing bits (the bits marked in brackets) between the two strings, the result is 37.

With help of Google and Wikipedia, I was able to build an implementation of this algorithm using the C++ programming language:

//Hamming Distance
int CryptoLib::hamming_distance(string str1, string str2)
{
    int count=0;
    for(int i=0; i<str1.size(); i++)
    {
        int partial = (str1[i] & 0xFF) ^ (str2[i] & 0xFF);
        while(partial)
        {
            count += partial & 1;
            partial = partial >>1;
        }
    }
    return count;
}

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.

Hope you found this article useful!

Adios Amigo!

The Cryptopals Crypto Challenges: Set 1 - Break Repeating-Key XOR

Write a method that decodes a message which is encrypted using the Repeating-Key XOR cipher.

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

For this challenge, you are given a file, which contains a ciphertext that has been encrypted using Repeating-Key XOR and then encoded using Base64. Decrypt it.

According to the problem description on the website:

It is officially on, now.

This challenge isn't conceptually hard, but it involves actual error-prone coding. The other challenges in this set are there to bring you up to speed. This one is there to qualify you. If you can do this one, you're probably just fine up to Set 6.

Well, conceptually, this may not be the hardest but practically, it is the first hardest challenge in this set and it really did take me a while to understand how to decrypt the ciphertext through trial-and-error despite the instructions given on the website. In this challenge, it's more like connecting all the puzzles and looking at the big picture, in this case, all of the previous code that I had written, is to break the Repeating-Key XOR cipher.

How to break it?

The challenge had given some steps to follow. Here's how:

  1. Let KEYSIZE be the guessed length of the key; try values from 2 to (say) 40
  2. Write a function to compute the edit distance/Hamming distance between two strings. To know more about it, click here
  3. For each KEYSIZE, take the first KEYSIZE worth of bytes, and the second KEYSIZE worth of bytes, and find the edit distance between them. Normalize this result by dividing by KEYSIZE
  4. The KEYSIZE with the smallest normalized edit distance is probably the key. You could proceed perhaps with the smallest 2-3 KEYSIZE values. Or take 4 KEYSIZE blocks instead of 2 and average the distances
  5. Now that you probably know the KEYSIZE: break the ciphertext into blocks of KEYSIZE length
  6. Now transpose the blocks: make a block that is the first byte of every block, and a block that is the second byte of every block, and so on
  7. Solve each block as if it was single-character XOR. You already have code to do this
  8. For each block, the single-byte XOR key that produces the best looking histogram is the repeating-key XOR key byte for that block. Put them together and you have the key

Let's dive in to the code (I hope the comments, help you out!):

Implementation of the method(s):

//Single Byte XOR V2 - a better version
string CryptoLib::singleByteXOR_V2(string str, char key)
{
    //Don't forget to add a NULL character to the string, it broke when I didn't add it previously.
    string newStr(str.size(),''); 

    for(int i=0; i<str.size(); ++i){
        newStr[i] = str[i] ^ key;
    }
    return newStr;
}

//Return the Single Byte XOR key via Bruteforce
char CryptoLib::singleByteXOR_Bruteforce_key(string cipherBlock)
{
    char key = 0;
    int maxCount=0;
    string decodedMessage;

    //Brute force all 256 possibilities
    for(int i=0; i<=256; i++)
    {
        char ch = (char) i;

        //Perform Single Byte XOR -- modified version
        string attempt = singleByteXOR_V2(cipherBlock, ch);

        // cout << "Message: " << attempt << endl;

        int count = 0;
        /*
            Look for characters that are alphabetic and the space character,
            if it finds, increment the counter
        */
        for(int j=0; j<attempt.size(); j++)
        {
            if((attempt[j] >= 65 && attempt[j] <= 122) || attempt[j] == ' ')
            {
                count++;
            }
        }

        //The one with the highest count, has the predicted key
        if(count > maxCount)
        {
            maxCount = count;
            key = ch;
            // decrypted = attempt;
        }
    }

    // cout << "KEY: " << key << endl;
    // cout << "MESSAGE: " << decrypted << endl;

    return key;
}

//Guess Key length of the cipher
int CryptoLib::guess_key_length(string cipherText)
{
    int KEYSIZE = -1;
    double leastNormalized = INT_MAX;

    //Guess a keysize from 2 to 40
    for(int i=2; i<=40; i++)
    {
        double normalize = 0.0f;

        //Number of bytes per key size
        int bytes = cipherText.size()/i;

        for(int j=0; j<bytes; j++)
        {
            string blockA = cipherText.substr((j*i), i);
            string blockB = cipherText.substr(((j+1)*i), i);

            //Calculate Hamming Distance between 2 strings
            int edit_distance = hamming_distance(blockA, blockB);

            normalize += ((double)edit_distance)/((double)blockA.size());
        }

        //Now, take an average 
        normalize /= bytes;

        //The key size that has the least edit distance is the key size required
        if(normalize > 0 && normalize < leastNormalized)
        {
            leastNormalized = normalize;
            KEYSIZE = i;
        }
    }

    //Return the key size
    return KEYSIZE;
}

Final code:

//The Cryptopals Crypto Challenges - Set 1 Challenge 6
#include "crypto.h"

int main()
{
    CryptoLib crypt;
    string message;
    string binary;
    string key;

    //if this returns 37, then the function is working correct!
    // cout << crypt.hamming_distance("this is a test", "wokka wokka!!!") << endl;

    //Read the file content
    ifstream infile;

    //Converted the B64 text to Hexadecimals through an online converter
    //as it wasn't accurate with b64 decoder that I'd built
    infile.open("message.txt");
    getline(infile, message, '');
    infile.close();

    //Convert the hexadecimal string to ASCII
    message = crypt.con_hex_2_ascii(message);

    //Guess the length of the key
    int keyLength = crypt.guess_key_length(message);

    //Transpose the message based on keysize length
    int blocks = message.size() / keyLength;

    for(int i=0; i<keyLength; ++i)
    {
        string block;
        char indexKey='';

        /*
            Transpose the message into blocks 
            based on keysize and concatenate it 
            into one string
        */
        for(int j=0; j<blocks; j++){
            block += message.substr((j*keyLength) + i,1);
        }

        //Concatenate the selected characters, which will become the predicted key
        key += crypt.singleByteXOR_Bruteforce_key(block);
    }

    cout << "KEY: " << key << endl;
    cout << "DECODED: " << crypt.con_hex_2_ascii(crypt.repeatingKeyXOR(message, key)) << 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.

When the following code is executed, the most probable KEYSIZE is 29 and after transposing the message and decrypting the blocks, you get a key of that length:

Terminator X: Bring the noise

Lastly, use the Repeating-Key XOR method to decrypt the message with the cracked key (which looks like lyrics to some music track!):

A rockin' on the mike while the fly girls yell
Well that's my DJ Deshay cuttin' all them Z's
Vanilla's on the mike, man I'm not lazy. ?I'm lettin' my drug kick in
To just let it flow, let my concepts go
And if you don't give a damn, then
So get off 'cause I control the stage
I'm in my own phase
And I can dance better than any kid n' play ?
Stage 2 -- Yea the one ya' wanna listen to
So I can funk it up and make it sound good
For good luck, I like my rhymes atrocious
I'm an effect and that you can bet
There's no denyin', You can try to hang 
Over and over, practice makes perfect
Soon -- Oh my God, homebody, you probably eat
Intoxicating so you stagger like a wino
Vanilla Ice is sellin' and you people are buyin'
Movin' and groovin' trying to sing along
Now you're amazed by the VIP posse. ?
Steppin' so hard like a German Nazi
There's no trippin' on mine, I'm just gettin' down
You trapped me once and I thought that
So step down and lend me your ear 
Your body's gettin' hot, so, so I can smell it
'Cause the lyrics belong to ICE, You can call me Dad 
Let the witch doctor, Ice, do the dance to cure 
You wanna battle me -- Anytime, anywhere ?
You thought that I was weak, Boy, you're dead wrong 
play that funky music Go white boy, go white boy, go
Play that funky music white boy you say it, say it 
Play that funky music, white boy Come on, Come on, Come on

As mentioned above, this was really challenging and fun, at the same time. Although, Most people (academically) know "how-to" break a Repeating-Key XOR (Vignere Cipher) but being able to break it, is another thing.

Hope you liked reading this article!

But, hang in there, surprisingly, this code will be useful later on for many problems.

The Cryptopals Crypto Challenges: Set 1 - Implement Repeating-Key XOR

Write a method that encrypts messages using the Repeating-Key XOR method with a given key.

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

For this challenge, you have to implement a Repeating-Key XOR method to encrypt the following message:

Burning 'em, if you ain't quick and nimble
I go crazy when I hear a cymbal

With a given key:

ICE

The final message should look like this:

0b3637272a2b2e63622c2e69692a23693a2a3c6324202d623d63343c2a26226324272765272
a282b2f20430a652e2c652a3124333a653e2b2027630c692b20283165286326302e27282f

If you've already understood the concept of XOR and had no issues implementing both Fixed XOR Cipher and Single-Byte XOR Cipher, then this should be a piece of cake for you when it comes to implementing Repeating-Key XOR Cipher.

How does this work?

With Repeating-Key XOR, you'll sequentially apply each byte of the key (which is "ICE", in this case); the first byte of plaintext will be XOR'd against "I", the next "C", the next "E", then "I" again for the 4th byte, and so on.

You can use this method to encrypt anything you want. Emails, Passwords, Secret messages and so on. You'll definitely get a feel for it because things will get interesting after this challenge.

Let's dive in to the code:

Implementation of the method(s):

//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();
}

//Repeating Key XOR implementation
string CryptoLib::repeatingKeyXOR(string str, string key)
{
    string newStr = "";
    int count = 0;

    /*
        1. Perform XOR against each character of the message 
        against each character of the key. 
        So if the key was "ICE" and the message is "abcdefg",
        it would be "a" against "I", then "b" against "C" and "c" against "E"
        but once it reaches the key's limit, you start again from the beginning
        of the key, which should be like: "d" against "I", "e" against "C" and so on.
    */
    for(int i=0; i<str.size(); i++)
    {
        unsigned char a = key[count];
        unsigned char b = str[i];
        unsigned char c = b ^ a;

        newStr += c;

        if(count == key.size()-1)
        {
            count = 0;
        }
        else
        {
            count++;
        }
    }

    //2. Convert the ASCII message to Hexadecimal
    string final = "0";
    final += con_ascii_2_hex(newStr);
    return final;
}

Final code:

//Cryptopals Set 1 Challenge 5
#include "crypto.h"

int main()
{
    CryptoLib crypt;

    //Test cases provided
    string str = "Burning 'em, if you ain't quick and nimble I go crazy when I hear a cymbal";
    string key = "ICE";

    cout << "ENCODED: " << crypt.repeatingKeyXOR(str, key) << 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!