Permuting...

Jul 06, 2011 13:00

So. I'm working on some code for a friend. Gotta implement a permutation cipher. It takes a chunk of text (data) and scrambles the low-level bits. Sort of like when you scramble the alphabet to make a simple substitution cipher for those cryptograms in the newspaper, except at the data representation level internal to the computer instead of at the level that humans read.

Sh*t!!!! Jalapeno pepper juice in the eye! It buuuuuurrrrrnnnnzzzzzz!!! WHAAAAAAAA!!!

That was in the kitchen earlier.

Ha ha.

Anyway. Permutation cipher. We're operating on bytes. A byte is 8 bits. A bit is a 1 or a 0, those mythical beasts that are the basest of "particles" in a computer. For the sake of simplicity, a byte = 1 letter. And there are 256 possible letters that we could create, aside from your letters, numbers, and fancy punctuation marks. Faaaaaancy. You're sitting on the edge of your seat. I can tell.

So. We take the block, which is ONE or more bytes, and we randomly distribute the bits. Normal bit order:

1, 2, 3, 4, 5, 6, 7, 8

Bit order after randomly distribution:

7, 4, 6, 3, 8, 5, 1, 2

So your bits come in "01101011" and go out "10011101". You'll have to pardon my lack of diagrams. I'm not in the mood to create a perfect ASCII chart with arrows and fancy lines.

When your block is bigger, like 24 bits, the shuffling can be even more exciting, taking bits from one letter and shoving them in another and vice versa. Terribly enthralling. I know.

This is the terrible bit of code I wrote to do this:

std::string PermutationCipher::PermuteBits(const std::string& block) const
{
  std::stringstream bitBlockStream;
  for (std::string::const_iterator itr = block.begin(); itr != block.end(); ++itr) {
    std::bitset::digits> bits(*itr);
    bitBlockStream << bits.to_string();
  }

const std::string bitBlock = bitBlockStream.str();

std::string permutedBits;
  for(PermuteKey::const_iterator kitr = mKey.begin(); kitr != mKey.end(); ++kitr) {
    permutedBits.push_back(bitBlock.at(*kitr));
  }

std::string encryptedBlock;
  for(int index = 0; index < permutedBits.size(); index+=8) {
    std::bitset::digits> byte(permutedBits.substr(index, 8));
    encryptedBlock.push_back(byte.to_ulong());
  }

return encryptedBlock;

}

Jesus CRIPES. That's a terrible algorithm. I think this does the same thing. A lot shorter, too:

std::string PermutationCipher::PermuteBits(const std::string& block) const
{
  MessageContainer result;
  result.resize(block.size());
  for (PermuteKey::const_iterator kitr = mKey.begin(); kitr!=mKey.end(); ++kitr) {
    const int byte = (*kitr)/8;
    const int bit = 1<<(*kitr%8);
    const int val = (block.at(byte) & bit);

if (val != 0) {
      const int index = std::distance(mKey.begin(), kitr)/8;
      const int setVal = 1<<(std::distance(mKey.begin(), kitr)%8);
      result[index] |= setVal;
    }
  }

return result;
}

Aaaaaaaaaahhhhhhh. Magic numbers. But it was fun to play with std::bitset. I'm done.
Previous post Next post
Up