Integer encryption preserving equality

I have read too many different options for encryption that I now feel quite lost. I need a simple, secure (don't we all) scheme for encrypting integers (32-bit) with the following requirements:

• Ciphertext is also an integer (32-bit) or a long (64-bit)
• For integers x1=x2 then ciphertexts E(x1)=E(x2)
• For integers x1<>x2 then ciphertexts E(x1)<>E(x2)
• If I know E(x1) it will be very hard to decrypt x1 without the (private) key

Is there such a simple scheme?

• How about AES or any block cipher in any deterministic mode (SIV with constant or empty nonce, ECB) Apr 29, 2015 at 14:27
• What you're looking for a Format Preserving encryption (where your "format" is a 32 bit or 64 bit integer). You had a tag for homeomorphic encryption -- that's something else. Apr 29, 2015 at 14:28
• @ThomasM.DuBuisson I know that for AES x1=x2 then ciphertexts E(x1)=E(x2). Does the reverse apply => x1<>x2 then ciphertexts E(x1)<>E(x2)? b) AES would make 128bit and not 32-64 bit. c) If I add different SALT to different numbers, would those 2 conditions still apply? Apr 29, 2015 at 14:30
• @Alexandros Certainly if the plaintexts don't match then any deterministic operatoin, including a block cipher, will result in equal values. No matter the size of the integral (32, 64, whatever), you could zero extend the value or use SIV. And yes, this is an ad-hoc construction I'm talking through - poncho has suggested the correct field for well constructed and peer reviewed material. Apr 29, 2015 at 14:38
• What Thomas meant to say is if the plaintexts don't match, then the ciphertexts won't either. If the ciphertexts did match, then you wouldn't be able to uniquely decrypt (even with the key). Apr 29, 2015 at 14:47

Some of your conditions are already met by the definition of an encryption scheme:

• Encryption has to be reversible, so that a ciphertext can be the encryption of (at most) one plaintext.
• Your last point is basically just a ciphertext only attack. That is usually the weakest considered attack, and for todays security definitions not enough. So any scheme which is considered secure, it also includes this.

The only non-trivial part is your first point, because it is not that easy to find an encryption scheme, which has ciphertexts of 32 or 64 bit length. Of course you could use 3DES (64 bit), but that should not be recommended any more today. But there are other options:

• Stream ciphers don't expand the ciphertext. When choosing a stream cipher, use a current one, and consider to use keystream btis beginning after some threshold. RC4 is popular but has quite a few security problems.
• Using a block cipher in OFB, CTR (or KFB) mode of operation functions very similar to stream ciphers, and you can just drop the bits you don't need.
• Format preserving encryption is a method which enables you to have that 32 bit to 32 bit relationship. But there are a lot of constructions, and quite a few build upon the other mentioned methods.
• Stream ciphers don't expand the ciphertext, but you have to store the nonce so that you can decrypt, which means a stream cipher can't be format-preserving. Apr 30, 2015 at 17:42
• @tylo. Thanks. Without wanting to take advantage of your kindness, which of the methods supported by Java docs.oracle.com/javase/8/docs/technotes/guides/security/…, would you choose? I must probably exclude RC2, RC4, AES, RSA, all DES variants and that leaves what? RC5 with CFB32 or OFB32 or CFB64 or OFB64. Or I am missing something here? May 2, 2015 at 12:48
• Probably I would just use AES in OFB mode. When encrypting and decrypting, just pad it with zeros and throw away that part of the result afterwards.
– tylo
May 4, 2015 at 10:29

The main problems using stream ciphers for this type of encryption are 1) you should not use the same key stream more than once and 2) linear operations such as cipher-text = plain-text XOR key-stream enables indirect plain-text modification simply by cipher-text changes (toggling a bit of cipher-text toggles the same bit of plain-text). For a better approach, have a look at https://github.com/msotoodeh/integer-encoder. It supports 32 and 64 bit integer encryption.