2

Is there a simple decryption algorithm that is idempotent? Something like this:

decrypt(encrypt(x)) ===  x  === decrypt(decrypt(decrypt(encrypt(x))))
  • I don't think you can have something bijective and idempotent other than the identity. – Nico Schertler May 15 '19 at 01:54
  • 1
    Couldn't you just detect if something is decrypted, and then return the identity if it already was? – Maarten Bodewes May 15 '19 at 01:55
  • 1
    But then decrypt(encrypt(x)) could not be an arbitrary x – Ray Toal May 15 '19 at 01:56
  • @MaartenBodewes couldn't the decyrpt algorithm do that so I don't have to? –  May 15 '19 at 01:58
  • @RayToal Uh, yeah, but say that `x` is an arbitrary value of `n` bits and that `c = encrypt(x)` is an arbitrary value of `n` bits as well. Then above is not going to work, right? Note that stream ciphers do have the property that `encrypt === decrypt` so then any even number of encrypts and decrypts will return the plaintext. – Maarten Bodewes May 15 '19 at 02:10
  • No. (This space intentionally left blank) – n. m. could be an AI May 15 '19 at 03:06
  • 1
    @OlegzandrDenman I fear you may have limited your answers to the purely theoretical by defining your problem so strictly - is this a practical problem you are trying to solve? – Luke Joshua Park May 15 '19 at 03:35
  • 1
    I agree with @LukeJoshuaPark. For all practical uses, this problem is trivial. Add an header to the encrypted data. Once you make it a non-useful format (i.e. remove the header), then you define it into impossibility, but also make it a bad crypto format for most uses. – Rob Napier May 15 '19 at 03:53

3 Answers3

4

Suppose decrypt is a function f and encrypt is a function g. Hence, we have f(g(x)) = x and f(f(f(g(x)))) = x. Hence, we have f(f(x)) = x, and then f(f(x)) = f(g(x)) = x. If the result of the decryption function will be a bijective functio, we can conclude that f(x) = g(x), and then g(g(x)) = x. Also, if we suppose g(x) is bijective, it means f is inverse of g. Therefore, g(x) = x!

Also, if we don't have the bijective assumption for the function g (which is not too far!), from g(g(x)) = x, we find that for all input x the function maps the value of g(x) to itself. Hence, g(x) = x by the definition.

OmG
  • 18,337
  • 10
  • 57
  • 90
  • That's a no then, I suppose :) – Maarten Bodewes May 15 '19 at 02:14
  • 1
    Excellent summary! – Luke Joshua Park May 15 '19 at 02:31
  • 1
    I don't know about this - a simple decryption algorithm could "tack-on" an "a" at the front, then if the decryption algorithm so an "a" at the beginning it would just return the input. Just need some piece of information added. –  May 15 '19 at 02:52
  • 2
    If the decryption algorithm tacks on an "a" at the front, then decrypt(encrypt(x)) cannot be x, because you tacked the "a" on at the front. The OP said they wanted decrypt(encrypt(x)) to be x. You can't do that if you tack extra stuff on. If the OP loosened the restriction, then maybe you can add extra information that said a value was already decrypted, but that would have to be outside of the original message and not part of it. – Ray Toal May 15 '19 at 03:10
  • true - I agree with that –  May 15 '19 at 08:08
2

Here's another take (but accept OmG's answer).

  1. A decryption function must be injective, because otherwise it is useless.

  2. You want the decryption function to be idempotent.

  3. The only idempotent injective function is the identity function. Proof: Let f be idempotent and injective. Then by the definition of idempotent, f(f(x)) = f(x). Now because f is injective, f(x) maps to f(x), for all x, so hey, that's the identity function. Q.E.D.

  4. The identity function is an affirmative answer to your question "Is there a simple decryption algorithm that is idempotent?"

  5. HOWEVER, the identity function is not a real decryption function, because it would imply the ciphertext and the message must be the same, so in practice that is completely useless, in which case, the best answer to your question is "no."

Ray Toal
  • 86,166
  • 18
  • 182
  • 232
0

If decryption has to be idempotent and it actually has to do something, then it must be possible to distinguish (unencrypted) plaintext from (encrypted) ciphertext.

Often this is easy, because you can have the encrypt() function mark the ciphertext with something that just can't occur in plaintext. If the plaintext is text, for example, but the ciphertext can contain any binary data, then you can just include an invalid character at the start of every ciphertext.

If there is no structure that can occur in ciphertext, but can't occur in plaintext, though, then you can still do the job by marking the ciphertext with something that won't occur in plaintext. A reasonable way would be to digitally sign the ciphertext with the same key you use for encryption.

Then your idempotent decryption is just like:

idempotentDecrypt(ciphertext,key) {
    if (is_signed(ciphertext, key)) {
        return rawDecrypt(removeSignature(ciphertext),key)
    } else {
        return ciphertext;
    }
}

Of course there is a chance that some unencrypted plaintext could turn out to be validly signed just by chance, but that chance is vanishingly small and if your signature algorithm is good then you don't really have to worry about it.

Note that your encryption method also has to be idempotent -- it must leave already-encrypted ciphertext alone -- or it must refuse to encrypt things that are already encrypted.

Matt Timmermans
  • 53,709
  • 3
  • 46
  • 87
  • i mean I don't think the encryption algo *must* be idempotent, it might jumble it up into something else as long as it decrypts to the original in one step –  May 17 '19 at 05:25