What I basically need is a way to encrypt and decrypt symmetrically an ID which is a string. Both version of the ID will live and work in different domain and I need a way to switch domain without hold in memory a mapping table. My requirements are:

  • both kind of IDs must be human readble (alphanumeric).
  • plain IDs have fixed length
  • encrypted IDs must have fixed length (not necessarily the same of plain IDs)

abc123 ==== encrypt ====> as78ads89dfs ==== decrypt ====> abc123 23kop2 ==== encrypt ====> jfdsdfsg8dsf ==== decrypt ====> 23kop2 ...

is there any way to obtain this with some combination of encryption and encoding?

thank you all

  • $\begingroup$ About any normal symmetric cipher will do this for you, although you may need to rebase the result after encryption as a modern cipher will output any byte values, not just digits. This requirement seems missing from your question (and hence the answer from SEJPM). $\endgroup$ – Maarten Bodewes Dec 1 '17 at 23:33

Let $E_k$ denote any length-preserving authenticated encryption scheme, such as AES-GCM. These will usually add a fixed overhead of 12+16=28 bytes.

Now I shall assume that you know how to generate and manage keys for the above cipher and that you know how to generate nonces for the cipher.

Let $m$ be the maximal length your plaintext will ever have, in bytes. Define $m'=m+1$, this the length of the messages after encoding and the amount of data which will be fed into $E_k$.

The encoding itself is very easy: Take an $n$-byte message, append a 0x01 byte and $m-n$ 0x00 bytes. For decoding you start from the end of the message, go over all the 0x00 bytes until you hit the 0x01 byte. You throw away anything starting at (and including) the 0x01 byte.

So the overall flow would go like

0xBEEF     ==> encode ==> 0xBEEF010000 ==> AE-encrypt ==> nonce ||ciphertext ||tag  ==> AE-decrypt ==> 0xBEEF010000 ==> decode ==> 0xBEEF
0xDEADBEEF ==> encode ==> 0xDEADBEEF01 ==> AE-encrypt ==> nonce'||ciphertext'||tag' ==> AE-decrypt ==> 0xDEADBEEF01 ==> decode ==> 0xDEADBEEF
| improve this answer | |
  • $\begingroup$ thank you SEJPM. I edited the question to better specify my requirements $\endgroup$ – masciugo Dec 4 '17 at 13:34
  • $\begingroup$ @masciugo the answer stays the same, you'd just have to apply hex / base64 encoding after the encryption step and hex / base64 decoding before the decryption step. $\endgroup$ – SEJPM Dec 4 '17 at 13:55
  • $\begingroup$ ok. I tried with the two mode CBC and GCM. I like GCM because produces an encrypted ID which is shorter than CBC but I don't really like that encrypted IDs for sequential plain IDs are too similar to each other! $\endgroup$ – masciugo Dec 4 '17 at 15:31
  • $\begingroup$ @masciugo .... this is because you are using GCM completely insecurely by re-using the IV across encryptions. The IV needs to be unique for each encryption for GCM to work properly (and even more so for the unauthenticated = bad CBC mode even though it hides your mistakes better). $\endgroup$ – SEJPM Dec 4 '17 at 15:35
  • 1
    $\begingroup$ @masciugo yes, you need to store the IV - that the nonce from the expression nonce ||ciphertext ||tag in the answer. Or for the GCM mode the IV can be implicit (like recordId), for CBC it must be random $\endgroup$ – gusto2 Dec 4 '17 at 16:21

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.