-
Notifications
You must be signed in to change notification settings - Fork 2
Cryptography
It is often difficult for a beginner to encrypt some data, especially do that well and properly. Many people often fail at different points for one reason or another. kantanj provides a really simple API to work with cryptography in Java.
Cryptography-related stuff is located inside package me.darksidecode.kantanj.crypto
and usually requires no additional libraries. For both encryption and decryption, interface Encryptor
is used, which provides two methods: encrypt
and decrypt
, which both accept and return an array of bytes (byte[]
). The encrypt
method is used to encrypt a given array of bytes and returns the encrypted data. The decrypt
method does right the opposite, accepting encrypted data and returning the original array of bytes.
In kantanj, I decided not to focus on AES-128 too much, and only provided a small, simple, and often insecure, implementation. It should not be used in serious production projects.
In order to encrypt a given byte array (byte[] plain
) with AES-128, knowing the key (exactly 16 bytes, must be secret) (byte[] key
) and the init vector (exactly 16 bytes, does not have to be secret, but should not be reused — you should generate new IV each time you encrypt something) (byte[] iv
), use the following code (requires no additional libraries or natives):
/* Sender Side */
byte[] key = ...
byte[] iv = ... // generate something random for encryption and transfer it with the encrypted data for proper decryption
String plaintext = "Hello, world!";
byte[] plain = plaintext.getBytes(StandardCharsets.UTF_8);
Encryptor enc = new AES128Encryptor(key, iv);
byte[] encryptedData = enc.encrypt(plain);
// send `encryptedData` and `iv` to recipient
To decrypt, use the decrypt
method:
/* Recipient Side */
byte[] key = ... // secret key known both to sender and recipient
byte[] encryptedData = ... // received data
byte[] iv = ... // received init vector
Encryptor enc = new AES128Encryptor(key, iv);
byte[] plain = enc.decrypt(encryptedData);
String plainText = new String(plain, StandardCharsets.UTF_8); // "Hello, world!"
IMPORTANT NOTE: you have to install Java Cryptography Extension (JCE) in order to take advantage of AES-256 encryption for Java 8 — you can download it here. This is not needed for newer versions of Java.
Much more attention was paid to AES-256 encryption, which is the most secure encryption standard at the moment. In order to encrypt a given byte array (byte[] plain
) with AES-256, knowing the key (non-empty character array, must be secret) (char[] key
) and salt (exactly 8 bytes, does not have to be secret, may be reused) (byte[] salt
), use the following code (requires JCE, see the above note for details):
/* Sender Side */
char[] key = ...
byte[] salt = ... // generate 8 random bytes using a strong SecureRandom instance
String plaintext = "Hello, world!";
byte[] plain = plaintext.getBytes(StandardCharsets.UTF_8);
Encryptor enc = new AES256Encryptor(key, salt);
byte[] encryptedData = enc.encrypt(plain);
// unlike AES128Encryptor, AES256Encryptor returns both the encrypted data and the IV all merged in a single byte[] array
// send `encryptedData` to recipient
To decrypt, use the decrypt
method:
/* Recipient Side */
char[] key = ... // secret key known both to sender and recipient
byte[] encryptedData = ... // received data, also contains IV
byte[] salt = ... // salt known both to sender and recipient, does not have to be secret
Encryptor enc = new AES256Encryptor(key, salt);
byte[] plain = enc.decrypt(encryptedData);
String plainText = new String(plain, StandardCharsets.UTF_8); // "Hello, world!"
Both in order to generate AES-128 init vector and AES-256 salt, you should only rely on SecureRandom, since its results are way more complex to predict. Never use plain Random for cryptograhpy purposes!
Here is a brief example how you can generate a random 8-bytes-long salt:
SecureRandom srnd = SecureRandom.getInstanceStrong();
byte[] salt = new byte[8];
srnd.nextBytes(salt); // done, now `salt` is filled with eight securely randomized bytes
NOTE: if the last line of the above code (
nextBytes
) takes too long (or infinite time) to run, this means that you are running out of entropy, or, in other words, your system/machine does not provide enough random data. This can usually be easily resolved, just Google a little bit.