3
$\begingroup$

What is the best practice to accomplish this? For example, let's have an initial value abc123456 and a seed secret_hash. I want to change the initial value once about every hour to a new value and be able to decrypt any future value back to the original one.

Should I use an external known value, for instance time, in order to encrypt and decrypt, or there is an algorithm that will generate a decrypt-able infinite stream of values just from the seed and the initial value?

$\endgroup$
6
  • $\begingroup$ It is not clear to me what you want to do? I think what you want is for example if your initial value is abc123456 and then after n hours the encrypted value is zh1wq9z81 you want to be able to trace back all the changes that happen to abc123456 and results after n hours in zh1wq9z81? Is that what you want? What type of encryption you use symmetric or asymmetric? $\endgroup$ – Ubaidah Dec 26 '15 at 5:43
  • 3
    $\begingroup$ This is an atypical request. Could you describe what problem you are trying to solve? $\endgroup$ – Neil Smithline Dec 26 '15 at 5:45
  • $\begingroup$ I'd rather use symmetric encryption, if possible in this scenario. I want to trace the current encrypted value which has changed N times back to the original value. The intermittent values are not important. $\endgroup$ – logic Dec 26 '15 at 16:31
  • $\begingroup$ I second Neil's question. $\endgroup$ – StackzOfZtuff Dec 26 '15 at 19:18
  • 1
    $\begingroup$ Assuming you can keep $K$ secret, you could use $E_K(E_K(...E_K(IV)))$ if your IV is appropriately sized and you keep the count of encryptions. $\endgroup$ – SEJPM Dec 26 '15 at 21:25
2
$\begingroup$

As SEJPM suggests in the comments, you could simply derive each successive value by encrypting the previous value using a block cipher (in "ECB mode", i.e. using the raw block cipher directly), with your "seed" as the key:

$$\begin{aligned} v_0 &= \text{"abc123456"} \\ v_{i+1} &= E_K(v_i) \end{aligned}$$

where $E_K(x)$ denotes the encryption of the block $x$ using a block cipher with the key $K$.


It's possible that the iteration above might get caught in a small loop, although if the block size of the cipher is reasonably large (and 128 or even 64 bits should be more than plenty), the probability of this happening within any reasonable number of iterations is negligible; the expected cycle length for an $n$-bit block cipher is $2^{n-1}+1$.

That said, if you want to guarantee that your values will cycle through all possible cipher block values before they repeat, you can use the following scheme instead:

$$\begin{aligned} v_0 &= \text{"abc123456"} \\ v_{i+1} &= E_K(D_K(v_i)+1) \end{aligned}$$

where $D_K$ denotes block cipher decryption with key $K$, and $+$ denotes $n$-bit modular addition, when $n$ is the block size of the cipher in bits.

Note that, since $D_K(E_K(x)) = x$, this recurrence can also be equivalently written as:

$$\begin{aligned} v_0 &= \text{"abc123456"} \\ c_0 &= D_K(v_0) \\ v_i &= E_K(c_0 + i). \end{aligned}$$

That is, each output value $v_i$ is the encryption of a counter $c_i = c_0 + i$, where the initial counter value $c_0$ is the block cipher decryption of the first output value $v_0$.


Of course, if you don't care about the first output $v_0$ having some certain prescribed value, you can simply set the initial counter value $c_0$ directly to some arbitrary starting value (and, if you never use the same key $K$ twice, you could even just always set $c_0 = 0$):

$$\begin{aligned} c_0 &= \text{whatever} \\ v_i &= E_K(c_0 + i). \end{aligned}$$

This is very similar to the counter (CTR) mode of block cipher operation.

If you do want to generate multiple output sequences with the same key $K$, one option is to set, say, $c_0 = k \times 2^{64}$ (for a 128-bit cipher block size, like AES has), where $k$ is a unique 64-bit number identifying the output sequence. This way, you can have up to $2^{64}$ distinct output streams per key, and can generate up to $2^{64}$ output values for each stream without risking overlap with another stream.

This also lets you, given an arbitrary output block, easily identify both the stream the block belongs to (given by the upper 64 bits of the decrypted counter value) and the position of the block in the stream (given by the lower 64 bits).

(Of course, if you don't need quite that many streams or blocks per stream, you could also use a cipher with a 64-bit block size like Blowfish, and $c_0 = k \times 2^{32}$, to shorten your output values by 50%.)

$\endgroup$
2
  • $\begingroup$ From your answer and reading about modes of operation it seems like CBC and CTR modes are what I need. With CBC I get a different ciphertext every time with the same key and IV. With CTR I need to change the IV on every iteration to get a new ciphertext. However, I tried to implement both in PHP and faced problems: in CBC mode, I can only decrypt the ciphertext from the first iteration successfully. The next ones are not decrypted correctly. In CTR mode I can't understand how to increment the IV and how to get it from the ciphertext during decryption (I though this would be automated). $\endgroup$ – logic Dec 28 '15 at 14:08
  • $\begingroup$ My suggestion above would be to use the block cipher directly to encrypt individual blocks; your crypto library probably exposes that as "ECB mode", which takes no IV / nonce, and treats the plaintext / ciphertext as a series of individual cipher blocks to be encrypted / decrypted separately. (ECB mode is not a general-purpose semantically secure encryption mode by itself, but the raw access it provides to the block cipher is useful e.g. for implementing other modes, or for custom cryptographic schemes like this.) $\endgroup$ – Ilmari Karonen Dec 28 '15 at 15:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.