full-stack overflow

14 Sep 2017

Detecting The Single-Byte XOR Cipher

Cryptopals Set 1 Challenge 4 // code repo // working demo

The challenge? Given a text file of over 300 60-character hex strings, find which one has been encrypted using single-byte XOR.

This one’s really short. We lean heavily on the code already generated for challenge 3 tutorial HERE. All we need to do is load in the strings from the text file, apply the key guessing procedure to each one, and find the string with the highest score from the process. This will be the most likely string that was encoded in this manner. Though not certain: just consider removing the highest scoring “answer”: you’ll always have a high score, but that in itself is not meaningful.

Easy enough!

We store the texts as a string by enclosing the block in backticks, denoting a template literal. This is a sweet ES6 feature allowing for multiline strings (`), and then we split the block based on the newline (\n) character, giving us an array with each element as one of the potential encoded strings. Then, we loop over this array of strings and pass it into guessTheKey.

The return method of guessTheKey is changed slightly to return an array containing both the high score and the highest scoring string [lastHighScore,highestScoringText,scoreIdx]. Each time we call guessTheKey, we’ll score the highestScoringText and highScore so that at the end, we can recover the actual text. scoreIdx maps to the single byte hex key used for encryption.

We can find the max score in an array using the ES6 spread operator: Math.max(...scores). When we find the maximum score, we can use it to index on all the texts that we tested to find the highest-scoring text.

function goThroughTheFiles(txts) {
  // takes an array of texts
  let scores = [];
  let texts = [];
  for (var i = 0; i < txts.length; i++) {
    let res = guessTheKey(txts[i]);
    scores.push(res[0]);
    texts.push(res[1]);
  }
  console.log(
    "gttf scores:",
    scores,
    Math.max(...scores),
    texts[scores.indexOf(Math.max(...scores))]
  );
}

We get the result of Now that the party is jumping and a score of 215.223 using our character scoring rubric. Vanilla Ice is strong in this one.