Fast, simple to use symmetric cipher for integer encryption in Java
Asked Answered
C

3

5

What is in Java a cipher function for integer encryption having these properties?:

  • Fast
  • Symmetric-key algorithm
  • Simple to use (i.e. a couple of lines of code to use it and no external library to include)
  • It is possible to specify the output length (e.g. 20 characters)

I need to use it only to encrypt/decrypt integers.

Concert answered 26/4, 2015 at 16:8 Comment(4)
The identity function works for that, it's fast, it's symmetric, it's super simple to use, and it's possible to specify the output length by passing input of a given length.Phoenix
@BenjaminGruenbaum I need to encrypt my integers, how is it possible using the identity function?Concert
You can never specify the output length. It's inferred from the plaintext.Wolfie
@ArtjomB. Ok.. So, let me remove that requirement.. What about the other three?Concert
W
9

The requirement for no external library reduces the list to DES, 3DES and AES. DES and 3DES have a block size of 64 bits whereas AES has a block size of 128 bits. There are different aspects, one can examine this for.

Ciphertext size

DES and 3DES are best used for integers that are at most 56-bit wide (non-full long), because the result will be a single block of 8 byte, because of padding. If you encrypt a full long value, then an additional padding block will be added.

AES will always produce a 16 byte ciphertext for any int of long value.

Speed

According to this analysis AES (Rijndael-128) is more than twice as fast as DES/3DES with a bigger key size (more secure). AES can be even much faster than DES or 3DES when the CPU supports AES-NI. All current CPUs support this. This is my current result for taken from the openssl speed command.

AES achieves 127MB/s for 16 byte payloads whereas 3DES only achieves 27MB/s. Here's the data to poke around.

Security

Don't use DES for anything serious, because it only has a 56-bit key (64-bit with parity). Brute forcing cost is 256. 3DES is also not that good, because Brute forcing cost is 2112. Brute forcing cost for AES is 2128, 2192, 2256 depending on the used key size.

Code

Probably use AES:

private final String CIPHER_NAME = "AES/ECB/PKCS5Padding";
private final String ALGORITHM_NAME = "AES"; // keySizes 128, 192, 256
// private final String CIPHER_NAME = "DES/ECB/PKCS5Padding";
// private final String ALGORITHM_NAME = "DES"; // keySize 56
// private final String CIPHER_NAME = "DESede/ECB/PKCS5Padding";
// private final String ALGORITHM_NAME = "DESede"; // keySize 168

byte[] encrypt(SecretKey key, long num) {
    BigInteger bignum = BigInteger.valueOf(num);
    Cipher cipher = Cipher.getInstance(CIPHER_NAME);
    cipher.init(Cipher.ENCRYPT_MODE, key);
    return cipher.doFinal(bignum.toByteArray());
}

long decrypt(SecretKey key, byte[] ct) {
    Cipher cipher = Cipher.getInstance(CIPHER_NAME);
    cipher.init(Cipher.DECRYPT_MODE, key);
    byte[] pt = cipher.doFinal(ct);
    BigInteger bignum = new BigInteger(pt);
    return bignum.longValue();
}

SecretKey keyGen(String algorithm, int keySize) {
    KeyGenerator keygen = KeyGenerator.getInstance(algorithm);
    keygen.init(keySize);
    return keygen.generateKey();
}

Mode of operation

Here I use ECB mode. It is generally not a good idea to use it. It has a problem that encrypting the same plaintext with the same key results in the same ciphertext. This may not be a property that is acceptable. If it is not acceptable, then you need to use for example CBC mode with a new random IV. With will blow up the ciphertext by an additional block.

Wolfie answered 26/4, 2015 at 17:35 Comment(6)
I assume that integer actually means 32-bit int.Wolfie
I'm using Java Long type.. but your answer is still valid, I see encrypt/decrypt functions taking long as parameter.. isn't it?Concert
Anyway it's working for me!.. I used the keySize = 128 bit and a fixed SecretKey.Concert
the "this analysis" link seems to say the opposite of what you claim... they concluded that AES was the slowest.Outrageous
@Outrageous I only claimed that AES is considerably faster than 3DES which you can see from the numbers in tables 1 through 3. Keep in mind that 3DES only provides 112 bit security because of the possibility of a meet-in-the-middle attack. AES-128 provides at least 126 bit of security with the current research and is faster at the same time. AES can be regarded even much faster if we assume AES-NI instruction set of the current processor generation.Wolfie
@Outrageous I've added a performance comparison between AES and 3DES. I also don't consider DES or Blowfish as secure, because DES only has 56 bit security and Blowfish was obsoleted by its author.Wolfie
W
5

If you don't need a secure solution, but just fast one, consider the XOR cipher:

int key = ...
....
int b = a ^ key;
int c = b ^ key;
assert (c == a);
Wideeyed answered 1/8, 2015 at 21:58 Comment(2)
In the particular case of this question, XOR cipher may also be the most secure solution possible (since the cipher length is identical to the message length - both of them being ints - it is literally impossible to decrypt the message without knowing the key). This is only true though if the encrypted messages/integers are independent of each other and don't have well-known properties (like e.g. one particular message being very frequent).Rubino
XOR can be the most secure option, if the key is randomly generated, is larger than the message and is used only once during its lifetime. If you use the key multiple times you get a many-time pad where it is possible to deduce the original values.Wolfie
L
1

You should never implement a cipher yourself if you want any security. There's just too much what can get wrong.

But you can write your numbers into a byte[] and use a cipher provided with Java like described in this answer.

Lucubration answered 26/4, 2015 at 17:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.