Until now, I was using jasypt to encrypt a string before storing it on disk on app closing, and later when opening the app for decrypt the string after retrieving it from disk.
It was super easy with jasypt, this was the code:
private static final String JASYPT_PWD = "mypassword";
public static String encryptString(String string) {
StrongTextEncryptor textEncryptor = new StrongTextEncryptor();
textEncryptor.setPassword(JASYPT_PWD);
return textEncryptor.encrypt(string);
}
public static String decryptString(String string) {
StrongTextEncryptor textEncryptor = new StrongTextEncryptor();
textEncryptor.setPassword(JASYPT_PWD);
return textEncryptor.decrypt(string);
}
It worked perfectly, but now, jasypt is deprecated and I'm trying to migrate to the Google Tink library, the problem is that Google Tink seems to be much more complex for just encrypt and decrypt a string as easily as with jasypt.
I can't find in the Tink repo readme the simple way to encrypt and decrypt a string, just can find more complex operations which in fact I can't understand because my knowledge in encryption is totally empty. Because of that I was using a very easy library like jasypt.
This is the Tink repo: https://github.com/Google/tink
Is there an easy way, similar to my jasypt code, to encrypt and decrypt a string with Tink?
Tink is an open source cryptographic library that provides a secure, simple and agile API to perform common cryptographic tasks such as message authentication, digital signatures, hybrid encryption and symmetric encryption.
Tink uses Keysets to enable key rotation. Formally, a keyset is a non-empty list 1 of keys in which one key is designated primary (the key which is used to e.g. sign and encrypt new plaintexts).
Note: The post refers to Tink version 1.2.2. The posted code is partially incompatible with later versions.
The StrongTextEncryptor
-class in your jasypt
-example-code uses the PBEWithMD5AndTripleDES
-algorithm. This algorithm uses the symmetric-key block cipher Triple DES
and derives the key from the password using the MD5
hash function. The latter is called password-based encryption and this isn't supported in Tink
(at least as at 08/2018), see How to create symmetric encryption key with Google Tink?. Thus, it's impossible in Tink
to encrypt by means of a password and the concept used so far in the jasypt
-code couldn't be implemented. If password-based encryption is to be used in any case that is a deal-breaker for Tink
.
Another approach is to directly use a key. Tink
has the AesGcmJce
-class which uses AES-GCM
for encryption. Here the key must have a length of either 128 Bit or 256 bit:
String plainText = "This is a plain text which needs to be encrypted!";
String aad = "These are additional authenticated data (optional)";
String key = "ThisIsThe32ByteKeyForEncryption!"; // 256 bit
// Encryption
AesGcmJce agjEncryption = new AesGcmJce(key.getBytes());
byte[] encrypted = agjEncryption.encrypt(plainText.getBytes(), aad.getBytes());
// Decryption
AesGcmJce agjDecryption = new AesGcmJce(key.getBytes());
byte[] decrypted = agjDecryption.decrypt(encrypted, aad.getBytes());
The use is simple and furthermore the used cipher (AES-GCM
) is secure. However, the Tink
-developers themselves don't recommend this approach because the AesGcmJce
-class belongs to the com.google.crypto.tink.subtle
-package which may change at any time without further notice, (see also here, section Important Warnings). Therefore, also this approach isn't optimal.
Well, how does Tink
typically use symmetric encryption? This is shown in the following snippet from:
String plainText = "This is a plain text which needs to be encrypted!";
String aad = "These are additional authenticated data (optional)";
AeadConfig.register();
KeysetHandle keysetHandle = KeysetHandle.generateNew(AeadKeyTemplates.AES256_GCM);
Aead aead = AeadFactory.getPrimitive(keysetHandle);
// Encryption
byte[] ciphertext = aead.encrypt(plainText.getBytes(), aad.getBytes());
// Decryption
byte[] decrypted = aead.decrypt(ciphertext, aad.getBytes());
The generateNew
-method generates a new key. However, the creation isn't based on a password or a byte-sequence and because of this, a key generated for the encryption can't be easily reconstructed for decryption. Therefore, the key used for encryption has to be persisted to a storage system, e.g. the file system, so it can be used later for decryption. Tink
allows the storing of cleartext keys (which is of course not recommended). A more secure approach is the encryption of keys with master keys stored in a remote key management system (this is in more detail explained Tink
's JAVA-HOWTO, sections Storing Keysets and Loading Existing Keysets).
Tink
's key management concept (with the aim of avoiding accidental leakage of sensitive key material) makes it also somehow cumbersome (this may change in later versions). That's why I said in my comment that I'm not sure if Tink
fits your ideas concerning simplicity.
Disclaimer: I'm Tink's lead developer.
If you're working on an Android app, you can check out AndroidKeysetManager
. There's a hello world example that you can copy from.
In general whenever you want to encrypt something, the first question you should ask yourself is where you're going to store keys. It doesn't make a lot of senses to store keys in the same place (and with the same ACL) where you store your encrypted data. Keys should be stored in a different location (or with different ACL).
Tink's Key Management API is a bit more complex because we want to steer users to storing keys in the right location.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With