Gids voor Google Tink

1. Inleiding

Tegenwoordig gebruiken veel ontwikkelaars cryptografische technieken om gebruikersgegevens te beschermen.

Bij cryptografie kunnen kleine implementatiefouten ernstige gevolgen hebben, en begrijpen hoe cryptografie correct geïmplementeerd moet worden, is een complexe en tijdrovende taak.

In deze tutorial gaan we Tink beschrijven - een meertalige, platformonafhankelijke cryptografische bibliotheek die ons kan helpen bij het implementeren van veilige, cryptografische code.

2. Afhankelijkheden

We kunnen Maven of Gradle gebruiken om Tink te importeren.

Voor onze tutorial voegen we gewoon Tink's Maven-afhankelijkheid toe:

 com.google.crypto.tink tink 1.2.2 

Hoewel we in plaats daarvan Gradle hadden kunnen gebruiken:

afhankelijkheden {compileer 'com.google.crypto.tink: tink: latest'}

3. Initialisatie

Voordat we een van de Tink-API's gebruiken, moeten we ze initialiseren.

Als we alle implementaties van alle primitieven in Tink moeten gebruiken, kunnen we de TinkConfig.register () methode:

TinkConfig.register ();

Als we bijvoorbeeld alleen AEAD-primitief nodig hebben, kunnen we AeadConfig.register () methode:

AeadConfig.register ();

Voor elke implementatie is ook een aanpasbare initialisatie beschikbaar.

4. Tink Primitives

De belangrijkste objecten die de bibliotheek gebruikt, worden primitieven genoemd die, afhankelijk van het type, verschillende cryptografische functies bevatten.

Een primitief kan meerdere implementaties hebben:

PrimitiefImplementaties
AEADAES-EAX, AES-GCM, AES-CTR-HMAC, KMS-envelop, CHACHA20-POLY1305
Streaming AEADAES-GCM-HKDF-STREAMING, AES-CTR-HMAC-STREAMING
Deterministische AEADAEAD: AES-SIV
MACHMAC-SHA2
Digitale handtekeningECDSA over NIST-curven, ED25519
Hybride versleutelingECIES met AEAD en HKDF, (NaCl CryptoBox)

We kunnen een primitief verkrijgen door de methode aan te roepen getPrimitive () van de overeenkomstige fabrieksklasse die het doorgeeft a KeysetHandle:

Aead aead = AeadFactory.getPrimitive (keysetHandle); 

4.1. KeysetHandle

In volgorde om cryptografische functionaliteit te bieden, heeft elke primitief een sleutelstructuur nodig dat alle belangrijke materialen en parameters bevat.

Tink biedt een object - Sleutelset Handvat - die een sleutelset omhult met enkele aanvullende parameters en metadata.

Dus voordat we een primitief instantiëren, moeten we een KeysetHandle voorwerp:

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

En nadat we een sleutel hebben gegenereerd, willen we deze misschien behouden:

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

Vervolgens kunnen we het vervolgens laden:

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

5. Versleuteling

Tink biedt meerdere manieren om het AEAD-algoritme toe te passen. Laten we kijken.

5.1. AEAD

AEAD biedt geverifieerde versleuteling met bijbehorende gegevens, wat betekent dat we kunnen platte tekst versleutelen en, optioneel, bijbehorende gegevens verstrekken die moeten worden geverifieerd maar niet versleuteld.

Merk op dat dit algoritme de authenticiteit en integriteit van de bijbehorende gegevens garandeert, maar niet de geheimhouding ervan.

Om gegevens te versleutelen met een van de AEAD-implementaties, zoals we eerder zagen, moeten we de bibliotheek initialiseren en een keyset

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

Zodra we dat hebben gedaan, kunnen we de primitief ophalen en de gewenste gegevens versleutelen:

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

Vervolgens kunnen we het cijfertekst de ... gebruiken decoderen () methode:

String decrypted = nieuwe String (aead.decrypt (ciphertext, geassocieerdData.getBytes ()));

5.2. Streaming AEAD

Evenzo wanneer de te versleutelen gegevens te groot zijn om in een enkele stap te worden verwerkt, kunnen we de streaming AEAD-primitief gebruiken:

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

In feite hadden we nodig WriteableByteChannel om dit te behalen.

Dus om het cipherTextFile, we zouden een ReadableByteChannel:

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

6. Hybride versleuteling

Naast symmetrische versleuteling implementeert Tink een aantal primitieven voor hybride versleuteling.

Met Hybrid Encryption kunnen we de efficiëntie van symmetrische sleutels en het gemak van asymmetrische sleutels verkrijgen.

Simpel gezegd, we zullen een symmetrische sleutel gebruiken om de platte tekst te versleutelen en een openbare sleutel om alleen de symmetrische sleutel te versleutelen.

Merk op dat het alleen geheimhouding biedt, niet de identiteitsauthenticiteit van de afzender.

Dus laten we eens kijken hoe we het kunnen gebruiken HybridEncrypt en 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 (cijfertekst, contextInfo.getBytes ());

De contextInfo zijn impliciete openbare gegevens uit de context die kunnen zijn nul of leeg of gebruikt als "geassocieerde data" -invoer voor de AEAD-encryptie of als "CtxInfo" -invoer voor HKDF.

De cijfertekst maakt het mogelijk om de integriteit van contextInfo maar niet de geheimhouding of authenticiteit.

7. Berichtauthenticatiecode

Tink ondersteunt ook Message Authentication Codes of MAC's.

Een MAC is een blok van enkele bytes dat we kunnen gebruiken om een ​​bericht te authenticeren.

Laten we eens kijken hoe we een MAC kunnen maken en vervolgens de authenticiteit ervan kunnen verifiëren:

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 het geval dat de gegevens niet authentiek zijn, moet de methode verifiërenMac () gooit een GeneralSecurityException.

8. Digitale handtekening

Naast coderings-API's ondersteunt Tink digitale handtekeningen.

Om digitale handtekening te implementeren, gebruikt de bibliotheek de PublicKeySign primitief voor het ondertekenen van gegevens, en PublickeyVerifieer voor verificatie:

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

Net als bij de vorige versleutelingsmethode, wanneer de handtekening ongeldig is, krijgen we een GeneralSecurityException.

9. Conclusie

In dit artikel hebben we de Google Tink-bibliotheek geïntroduceerd met behulp van de Java-implementatie.

We hebben gezien hoe u gegevens kunt versleutelen en ontsleutelen en hoe u de integriteit en authenticiteit ervan kunt beschermen. Bovendien hebben we gezien hoe u gegevens kunt ondertekenen met behulp van API's voor digitale handtekeningen.

Zoals altijd is de voorbeeldcode beschikbaar op GitHub.