Tink encryptionGoogle has released Tink and which is a multi-language, cross-platform cryptographic library. With OpenSSL we have complex bindings and which were often focused on specific systems, such as for DLLs in Windows systems. Tink is open-source and focuses on creating simple APIs and which should make the infrastructure more portable [Tink Symmetric key][Tink MAC][Tink ECDSA/Ed25519][Tink Hybrid encryption][Tink Envelope encryption][HKDF][Deterministic Authenticated Encryption]: |
Outline
For Tink — based on BoringSSL and now at Version 1.2.0 — the adoption has been good and is already integrated into AdMob, Google Pay, Google Assistant, and Firebase. It also integrates AEAD (Authenticated encryption AE and authenticated encryption with associated data) methods and which integrates encryption keys, a hash function, and a message authentication code (MAC). Google, too, have analysed many cryptography weaknesses and have created code which addresses many of these problems.
The minimal standards for AEAD include [RFC5116]:
- The plaintext and associated data can have any length (from 0 to 2³² bytes).
- Supports 80-bit authentication.
- CCA2 security (adaptive chosen-ciphertext attack).
Sample code
Tink aims to simplify encryption processing and use the best methods possible for encryption. In the following we encrypt a string (“napier”) with a key of “qwerty123”:
package com.helloworld; import java.util.Base64; import com.google.crypto.tink.aead.AeadConfig; import java.security.GeneralSecurityException; import com.google.crypto.tink.Aead; import com.google.crypto.tink.KeysetHandle; import com.google.crypto.tink.aead.AeadFactory; import com.google.crypto.tink.aead.AeadKeyTemplates; import com.google.crypto.tink.subtle.Hex; import com.google.crypto.tink.CleartextKeysetHandle; import com.google.crypto.tink.JsonKeysetWriter; import java.io.ByteArrayOutputStream; public final class HelloWorld { public static void main(String[] args) throws Exception { AeadConfig.register(); try { String plaintext="napier"; String aad="qwerty123"; int t=1; if (args.length>0) plaintext=args[0]; if (args.length>1) aad=args[1]; if (args.length>2) t=Integer.valueOf(args[2]); System.out.println("Text:\t\t"+plaintext); System.out.println("Password:\t"+aad); KeysetHandle keysetHandle=null; if (t==1) { System.out.println("Enc type:\t128-bit AES GCM"); keysetHandle=KeysetHandle.generateNew(AeadKeyTemplates.AES128_GCM); } else if (t==2) { System.out.println("Enc type:\t128-bit AES EAX"); keysetHandle=KeysetHandle.generateNew(AeadKeyTemplates.AES128_EAX); } else if (t==3) { System.out.println("Enc type:\t128-bit AES CTR HMAC SHA256"); keysetHandle=KeysetHandle.generateNew(AeadKeyTemplates.AES128_CTR_HMAC_SHA256); } else if (t==4) { System.out.println("Enc type:\tCHACHA 20 POLY 1305"); keysetHandle=KeysetHandle.generateNew(AeadKeyTemplates.CHACHA20_POLY1305); } else if (t==5) { System.out.println("Enc type:\t256-bit AES EAX"); keysetHandle=KeysetHandle.generateNew(AeadKeyTemplates.AES256_EAX); } else if (t==6) { System.out.println("Enc type:\t256-bit AES GCM"); keysetHandle=KeysetHandle.generateNew(AeadKeyTemplates.AES256_GCM); } else if (t==7) { System.out.println("Enc type:\t256-bit AES HMAC SHA-256"); keysetHandle=KeysetHandle.generateNew(AeadKeyTemplates.AES256_CTR_HMAC_SHA256); } Aead aead = AeadFactory.getPrimitive(keysetHandle); byte[] ciphertext = aead.encrypt(plaintext.getBytes(), aad.getBytes()); byte[] encoded = Base64.getEncoder().encode(ciphertext); System.out.println("\nCipher:\t"+ new String(encoded)); System.out.println("\nCipher:\t"+ Hex.encode(ciphertext)); byte[] decrypted = aead.decrypt(ciphertext, aad.getBytes()); String s = new String(decrypted); System.out.println("\nDecrypted:\t"+s); System.out.println("\nPrinting out key:"); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); CleartextKeysetHandle.write(keysetHandle, JsonKeysetWriter.withOutputStream(outputStream)); System.out.println( new String(outputStream.toByteArray())); } catch (GeneralSecurityException e) { System.out.println(e); System.exit(1); } } }
A sample run proves the process:
Text: hello Password: qwerty Enc type: 128-bit AES GCM Cipher: AVrtH/qbbuUSv22n2f8D3g3wr3Y24yeBqRybkPBg9Cxxap3Dd34= Cipher: 41567274482F7162627555537632326E32663844336733777233593234796542715279626B50426739437878617033446433343D Decrypted: hello Printing out key: { "primaryKeyId": 1525489658, "key": [{ "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.AesGcmKey", "keyMaterialType": "SYMMETRIC", "value": "GhAmZA23Todsp2JPRj7u813O" }, "outputPrefixType": "TINK", "keyId": 1525489658, "status": "ENABLED" }] }
In this case we use 128-bit AES with GCM (Galois/counter mode). We can see that the key is "GhAmZA23Todsp2JPRj7u813O". Another sample:
Text: hello Password: qwerty Enc type: 128-bit AES CTR HMAC SHA256 Cipher: AX2ZvBzsVcf3kWWWaWtTupFaeviCSEmFGRuWsLnNTAXdGsZEg5e+mEUN Cipher: 4158325A76427A73566366336B57575761577454757046616576694353456D4647527557734C6E4E5441586447735A456735652B6D45554E Decrypted: hello Printing out key: { "primaryKeyId": 2107227164, "key": [{ "keyData": { "typeUrl": "type.googleapis.com/google.crypto.tink.AesCtrHmacAeadKey", "keyMaterialType": "SYMMETRIC", "value": "EhYSAggQGhAfPlJHjrHhxcnneDbZai27GigSBAgDEBAaIKyjnQCyJkWPQB0fhs0wwVjy1NE5bR6IUBqd5W695V9f" }, "outputPrefixType": "TINK", "keyId": 2107227164, "status": "ENABLED" }] }
Our AEAD object is created with:
KeysetHandle keysetHandle = KeysetHandle.generateNew(AeadKeyTemplates.AES128_GCM); Aead aead = AeadFactory.getPrimitive(keysetHandle);
and then the encrypt() and decrypt() methods are used to create the cipher stream and then decipher it.
Google aims to focus the industry on strong encryption methods using AEAD and with integrated authentication: AES-EAX (encrypt-then-authenticate-then-translate), AES-GCM, AES-CTR-HMAC (Counter reset), KMS Envelope. For streaming encryption these methods are converted into: AES-GCM-HKDF-STREAMING, and AES-CTR-HMAC-STREAMING .
This AeadKeyTemplates object has the following properties:
- AES128_CTR_HMAC_SHA25. 16 byte AES key size. IV size: 16 bytes. HMAC key size: 32 bytes.HMAC tag size: 16 bytes. HMAC hash function: SHA256
- AES128_EAX. Key size: 16 bytes. IV size: 16 bytes.
- AES128_GCM Key size: 16 bytes.
- AES256_CTR_HMAC_SHA256. AES key size: 32 bytes. AES IV size: 16 bytes . HMAC key size: 32 bytes. HMAC tag size: 32 bytes. HMAC hash function: SHA256
- AES256_EAX. Key size: 32 bytes. IV size: 16 bytes
- AES256_GCM. Key size: 32 bytes.
- CHACHA20_POLY1305.
Presentation
The following is a presentation related to Google Tink [slides]: