1

Naturally XOR can be used twice to get back the original value. What if the original value is part of the mask?

Encoding:

e[i] = c[i] ^ (c[i] + c[i-1])

Assuming: starting value c[-1] = 0, ^ means bitwise XOR

In imperative C form:

void encode(byte *p, int len)
{
    byte prev = 0;
    for (auto i = 0; i < len; i++)
    {
        auto byt = p[i];
        p[i] = byt ^ (prev + byt);
        prev = byt;
    }
}

How do I create a decode step that reverses this from e => c?

I've simplified/clarified (read: changed) the question given what I've learned from your answers! Using similar steps to DanL, starting with the original equation:

e[i] = c[i] ^ (c[i] + c[i-1])

e[i] ^ c[i] = c[i] ^ (c[i] + c[i-1]) ^ c[i]
e[i] ^ c[i] = c[i] + c[i-1]
c[i] = e[i] ^ c[i] - c[i-1]
c[i] ^ c[i] = (e[i] ^ c[i] - c[i-1]) ^ c[i]
0 = e[i] ^ c[i] ^ c[i] - c[i-1] ^ c[i]
0 = e[i] - c[i-1] ^ c[i]
c[i-1] ^ c[i] = e[i]
c[i-1] ^ c[i] ^ c[i-1] = e[i] ^ c[i-1]
c[i] = e[i] ^ c[i-1]

???

Now, looking at the original encode - the first byte will always be zero (= c[i] ^ (c[i] + 0)). So yes, there must be a loss of one byte over the set.

user207421
  • 305,947
  • 44
  • 307
  • 483
Fil
  • 1,766
  • 1
  • 15
  • 15
  • Easy. By definition. c = e ^ (p + c) – LawfulEvil Jun 11 '15 at 17:06
  • Uh, yeah. What about with only c on the left? :) – Fil Jun 11 '15 at 17:06
  • Is it true that: a ^ (b + c) = (a ^ b) + (a ^ c); or similar? – Fil Jun 11 '15 at 17:09
  • 1
    You obviously can't, `e = 0, p = 0` is consistent with any `c` – harold Jun 11 '15 at 17:09
  • Yes, what if there is a constraint that !(e == 0 && p == 0) – Fil Jun 11 '15 at 17:10
  • 1
    `e = 1, p = 1` is consistent with any even `c`, so still no luck. By the way, xor does not distribute over addition. – harold Jun 11 '15 at 17:10
  • 1
    Your equation is not a tautology. 1 = 1^(0&0). (c is both 1 and 0) Of course, if this is programming, the 'c' on the right is the previous value of c so the whole thing might be fine. Maybe if you gave us the context. – LawfulEvil Jun 11 '15 at 17:13
  • p is the previous c - I wasn't thinking of imperative form in this equation, but it would work (you could think of c as being the previous). I'm trying to reverse a C function that uses the above equation to 'encode' some data. – Fil Jun 11 '15 at 17:16
  • 1
    Could you post that (whole) function? – harold Jun 11 '15 at 17:16
  • 1
    You need to distinguish items in the loop from the previous values using subscripts or such. – LawfulEvil Jun 11 '15 at 17:17
  • Code posted - I'm looking for a unmix() function :) – Fil Jun 11 '15 at 17:22
  • 1
    Ignoring the revised question I believe any c in p is valid (`c & ~p == 0`) unless `e^p != p>>1` in which case it is unsatisfiable. Err.. Possibly. – doynax Jun 11 '15 at 17:33
  • 1
    I don't believe there is an umix function. mixed[0] is always 0 as mixed[0] = unmixed[0] ^ (0 + unmixed[0]) [as prev is 0 initially]. This means the function mix effectively maps a len byte array onto a len-1 byte array (as we always know the first byte is 0). – DanL Jun 11 '15 at 17:56

1 Answers1

1

In each iteration of the loop you are effectively calculating

c_i = e ^ ( p + c_(i-1) )

If you wish to reverse the loop then given a c_i you need to calculate c_(i-1)

However as you said xoring twice gets you back to the original value and xor is a commutative operation so if you xor the above equation by e we then get

c_i ^ e = e ^ ( p + c_(i-1) ) ^ e

which simplifies to

c_i ^ e = p + c_(i-1)

then take away p from both sides to give you

(c_i ^ e) - p = c_(i-1)

Therefore in your "reversal" loop

you want the code

c = (c ^ e) - p

Edit: After seeing the revised question with code in context I don't believe this is possible as I believe the mix function is effectively mapping a len byte array onto a len-1 byte array.

I believe this because of the following argument:

Let the unmixed array be called unmixed and the mixed array after applying the mix function be called mixed

mixed[0] = unmixed[0] ^ (0 + unmixed[0])  //Remember prev = 0 initially

therefore mixed[0] = unmixed[0] ^ unmixed[0] = 0

so the first byte of the mixed array will always be 0.

The mix function doesn't increase or decrease the size of the array so we end up with a len byte array with the first element being 0.

We have therefore effectively mapped the space of len byte arrays onto len-1 byte arrays.

If this was perfectly reversible, we would be able to compress a n byte array to a n-1 byte array and then compress that n-1 byte array to a n - 2 byte array and so on.

If we use a one byte array as an example then we see mix just produces an array with a single element of 0, how do you know which of the 256 possible unmixed arrays it was before hand?

DanL
  • 1,974
  • 14
  • 13
  • In fact, any zero bits in the original array cause the subsequent byte's equivalent bit to be lost. Quite lossy :) – Fil Jun 12 '15 at 14:43