Panduan untuk Google Tink

1. Perkenalan

Saat ini, banyak pengembang menggunakan teknik kriptografi untuk melindungi data pengguna.

Dalam kriptografi, kesalahan implementasi kecil dapat menimbulkan konsekuensi serius, dan memahami bagaimana mengimplementasikan kriptografi dengan benar adalah tugas yang kompleks dan memakan waktu.

Dalam tutorial ini, kami akan menjelaskan Tink - pustaka kriptografi lintas platform multi-bahasa yang dapat membantu kami menerapkan kode kriptografi yang aman.

2. Dependensi

Kita bisa menggunakan Maven atau Gradle untuk mengimpor Tink.

Untuk tutorial kami, kami hanya akan menambahkan dependensi Maven Tink:

 com.google.crypto.tink tink 1.2.2 

Meskipun kita bisa menggunakan Gradle sebagai gantinya:

dependencies { compile 'com.google.crypto.tink:tink:latest' }

3. Inisialisasi

Sebelum menggunakan Tink API apa pun, kita perlu menginisialisasinya.

Jika kita perlu menggunakan semua implementasi dari semua primitif di Tink, kita bisa menggunakan metode TinkConfig.register () :

TinkConfig.register();

Misalnya, jika kita hanya membutuhkan primitif AEAD, kita dapat menggunakan metode AeadConfig.register () :

AeadConfig.register();

Inisialisasi yang dapat disesuaikan juga disediakan untuk setiap implementasi.

4. Tink Primitif

Objek utama yang digunakan perpustakaan disebut primitif yang, bergantung pada tipenya, berisi fungsionalitas kriptografi yang berbeda.

Primitif dapat memiliki beberapa implementasi:

Primitif Implementasi
AEAD AES-EAX, AES-GCM, AES-CTR-HMAC, Amplop KMS, CHACHA20-POLY1305
Streaming AEAD AES-GCM-HKDF-STREAMING, AES-CTR-HMAC-STREAMING
AEAD deterministik AEAD: AES-SIV
MAC HMAC-SHA2
Tanda tangan digital ECDSA melalui kurva NIST, ED25519
Enkripsi Hibrid ECIES dengan AEAD dan HKDF, (NaCl CryptoBox)

Kita bisa mendapatkan primitif dengan memanggil metode getPrimitive () dari kelas pabrik yang sesuai dengan meneruskan KeysetHandle :

Aead aead = AeadFactory.getPrimitive(keysetHandle); 

4.1. KeysetHandle

Untuk menyediakan fungsionalitas kriptografi, setiap primitif membutuhkan struktur kunci yang berisi semua material dan parameter kunci.

Tink menyediakan objek - KeysetHandle - yang membungkus kumpulan kunci dengan beberapa parameter dan metadata tambahan.

Jadi, sebelum membuat instance primitif, kita perlu membuat objek KeysetHandle :

KeysetHandle keysetHandle = KeysetHandle.generateNew(AeadKeyTemplates.AES256_GCM);

Dan setelah membuat kunci, kami mungkin ingin mempertahankannya:

String keysetFilename = "keyset.json"; CleartextKeysetHandle.write(keysetHandle, JsonKeysetWriter.withFile(new File(keysetFilename)));

Kemudian, kami selanjutnya dapat memuatnya:

String keysetFilename = "keyset.json"; KeysetHandle keysetHandle = CleartextKeysetHandle.read(JsonKeysetReader.withFile(new File(keysetFilename)));

5. Enkripsi

Tink menyediakan berbagai cara untuk menerapkan algoritma AEAD. Mari lihat.

5.1. AEAD

AEAD menyediakan Enkripsi yang Diautentikasi dengan Data Terkait yang berarti kami dapat mengenkripsi teks biasa dan, secara opsional, menyediakan data terkait yang harus diautentikasi tetapi tidak dienkripsi .

Perhatikan bahwa algoritme ini memastikan keaslian dan integritas data terkait, tetapi bukan kerahasiaannya.

Untuk mengenkripsi data dengan salah satu implementasi AEAD, seperti yang kita lihat sebelumnya, kita perlu menginisialisasi perpustakaan dan membuat keysetHandle:

AeadConfig.register(); KeysetHandle keysetHandle = KeysetHandle.generateNew( AeadKeyTemplates.AES256_GCM);

Setelah kita selesai melakukannya, kita bisa mendapatkan yang primitif dan mengenkripsi data yang diinginkan:

String plaintext = "baeldung"; String associatedData = "Tink"; Aead aead = AeadFactory.getPrimitive(keysetHandle); byte[] ciphertext = aead.encrypt(plaintext.getBytes(), associatedData.getBytes());

Selanjutnya, kita dapat mendekripsi ciphertext menggunakan metode decrypt () :

String decrypted = new String(aead.decrypt(ciphertext, associatedData.getBytes()));

5.2. Streaming AEAD

Similarly, when the data to be encrypted is too large to be processed in a single step, we can use the streaming AEAD primitive:

AeadConfig.register(); KeysetHandle keysetHandle = KeysetHandle.generateNew( StreamingAeadKeyTemplates.AES128_CTR_HMAC_SHA256_4KB); StreamingAead streamingAead = StreamingAeadFactory.getPrimitive(keysetHandle); FileChannel cipherTextDestination = new FileOutputStream("cipherTextFile").getChannel(); WritableByteChannel encryptingChannel = streamingAead.newEncryptingChannel(cipherTextDestination, associatedData.getBytes()); ByteBuffer buffer = ByteBuffer.allocate(CHUNK_SIZE); InputStream in = new FileInputStream("plainTextFile"); while (in.available() > 0) { in.read(buffer.array()); encryptingChannel.write(buffer); } encryptingChannel.close(); in.close();

Basically, we needed WriteableByteChannel to achieve this.

So, to decrypt the cipherTextFile, we'd want to use a ReadableByteChannel:

FileChannel cipherTextSource = new FileInputStream("cipherTextFile").getChannel(); ReadableByteChannel decryptingChannel = streamingAead.newDecryptingChannel(cipherTextSource, associatedData.getBytes()); OutputStream out = new FileOutputStream("plainTextFile"); int cnt = 1; do { buffer.clear(); cnt = decryptingChannel.read(buffer); out.write(buffer.array()); } while (cnt>0); decryptingChannel.close(); out.close();

6. Hybrid Encryption

In addition to symmetric encryption, Tink implements a couple of primitives for hybrid encryption.

With Hybrid Encryption we can get the efficiency of symmetric keys and the convenience of asymmetric keys.

Simply put, we'll use a symmetric key to encrypt the plaintext and a public key to encrypt the symmetric key only.

Notice that it provides secrecy only, not identity authenticity of the sender.

So, let's see how to use HybridEncrypt and HybridDecrypt:

TinkConfig.register(); KeysetHandle privateKeysetHandle = KeysetHandle.generateNew( HybridKeyTemplates.ECIES_P256_HKDF_HMAC_SHA256_AES128_CTR_HMAC_SHA256); KeysetHandle publicKeysetHandle = privateKeysetHandle.getPublicKeysetHandle(); String plaintext = "baeldung"; String contextInfo = "Tink"; HybridEncrypt hybridEncrypt = HybridEncryptFactory.getPrimitive(publicKeysetHandle); HybridDecrypt hybridDecrypt = HybridDecryptFactory.getPrimitive(privateKeysetHandle); byte[] ciphertext = hybridEncrypt.encrypt(plaintext.getBytes(), contextInfo.getBytes()); byte[] plaintextDecrypted = hybridDecrypt.decrypt(ciphertext, contextInfo.getBytes());

The contextInfo is implicit public data from the context that can be null or empty or used as “associated data” input for the AEAD encryption or as “CtxInfo” input for HKDF.

The ciphertext allows for checking the integrity of contextInfo but not its secrecy or authenticity.

7. Message Authentication Code

Tink also supports Message Authentication Codes or MACs.

A MAC is a block of a few bytes that we can use to authenticate a message.

Let's see how we can create a MAC and then verify its authenticity:

TinkConfig.register(); KeysetHandle keysetHandle = KeysetHandle.generateNew( MacKeyTemplates.HMAC_SHA256_128BITTAG); String data = "baeldung"; Mac mac = MacFactory.getPrimitive(keysetHandle); byte[] tag = mac.computeMac(data.getBytes()); mac.verifyMac(tag, data.getBytes());

In the event that the data isn't authentic, the method verifyMac() throws a GeneralSecurityException.

8. Digital Signature

As well as encryption APIs, Tink supports digital signatures.

To implement digital signature, the library uses the PublicKeySign primitive for the signing of data, and PublickeyVerify for verification:

TinkConfig.register(); KeysetHandle privateKeysetHandle = KeysetHandle.generateNew(SignatureKeyTemplates.ECDSA_P256); KeysetHandle publicKeysetHandle = privateKeysetHandle.getPublicKeysetHandle(); String data = "baeldung"; PublicKeySign signer = PublicKeySignFactory.getPrimitive(privateKeysetHandle); PublicKeyVerify verifier = PublicKeyVerifyFactory.getPrimitive(publicKeysetHandle); byte[] signature = signer.sign(data.getBytes()); verifier.verify(signature, data.getBytes());

Similar to the previous encryption method, when the signature is invalid, we'll get a GeneralSecurityException.

9. Conclusion

In this article, we introduced the Google Tink library using its Java implementation.

We've seen how to use to encrypt and decrypt data and how to protect its integrity and authenticity. Moreover, we've seen how to sign data using digital signature APIs.

Seperti biasa, kode sampel tersedia di GitHub.