Say you encrypted something. If you used one of the standard algorithms, the only possible ways to decrypt it illegally is to either guess/brute-force or enforce the sender to reveal the pass (i.e. the Rubber-hose attack!) Now, this enables you to transmit that ciphertext in way that it opens up a dummy message by giving up a dummy password (in the rubber-hose case), or runs an executable (in the brute-force case).


Truecrypt had some very interesting features. Plausible deniability was, for example, one of them. However using that feature required you to use the software suite. Regular encryption methods like AES also don't provide anything similar.

What it does

Say you want to encrypt a file (e.g. image or a clip etc.) or a text message. Using this software, you'd also encrypt another file or text message and then using a bijective map, generate another ciphertext that opens up the first encrypted content if you feed the the first one's password or opens up the second encrypted dummy content if you feed it its password. This process can go ad infinitum. You merge an encrypted image with the merge of an encrypted clip and an encrypted pdf etc. You could also pair an encrypted executable as the dummy ciphertex. If one enters the dummy password, that executable would be unlocked.

How I built it

Without loss of generality assume we want to encrypt a plaintext(s). We use standard encryption algorithms like AES (here we used AES-128 CBC mode) to encrypt that text. We encrypt another dummy text as well. Then, we assume the ciphertext is a number in base 256. We change the basis to something larger than 10 but small enough for us to assign alphabets. Here we hexlified those ciphertexts. Now we change them to base 10.

We assume one of the ciphertext is a numerator of a fraction and another ciphertext is the denominator of that fraction. Since both ciphertexts would be integers, the resulting fraction is rational. Since rationals are countably infinite, there exists a bijective map from rationals to natural numbers.

We use such a map, called "Cantor's pairing function". The output of that function, is just a single natural number. We change the base back to 256 and consider it as the ciphertext which is to be transmitted.

To reverse the process, one would evaluate the inverse of Cantor's function by feeding the newly created ciphertext to it. The output is two ciphertexts. If one uses the first password, the second ciphertext won't get deciphered and vice versa.

Challenges I ran into

The double precision floating point backend of Python's Long type which is used for handling of arbitrary large integers will be inaccurate for the outputs of functions whose codomain are the floats for sufficiently large inputs. To do that, we've defined the (de)pairing function in Mathematica and connected the two together.

Accomplishments that I'm proud of

  1. It works
  2. Having plausible deniability is cool - though I'd probably never use it!
  3. Everything -except AES primitives- have been implemented from scratch.
  4. The process is just transformations on the standard results of AES algorithm which makes it both to be as secure as the vanilla one (because one would be touching the ciphertext which by definition shouldn't have any identifiable information regarding its plaintext) and to be independent of the encryption algorithm (because, again, it's transformations on the ciphertext).

What I learned

refer to the "challenges" above.

What's next for Cantorize

Polish it. Publish it as open source.

Built With

Share this project: