Guide til Google Tink
1. Introduktion
I dag bruger mange udviklere kryptografiske teknikker til at beskytte brugerdata.
I kryptografi kan små implementeringsfejl have alvorlige konsekvenser, og det er en kompleks og tidskrævende opgave at forstå, hvordan man implementerer kryptografi korrekt.
I denne vejledning beskriver vi Tink - et kryptografisk bibliotek på tværs af platforme, der kan hjælpe os med at implementere sikker, kryptografisk kode.
2. Afhængigheder
Vi kan bruge Maven eller Gradle til at importere Tink.
Til vores vejledning tilføjer vi bare Tinks Maven-afhængighed:
com.google.crypto.tink tink 1.2.2
Selvom vi kunne have brugt Gradle i stedet:
afhængigheder {kompilér 'com.google.crypto.tink: tink: seneste'}
3. Initialisering
Før vi bruger nogen af Tink API'er, skal vi initialisere dem.
Hvis vi har brug for alle implementeringer af alle primitiver i Tink, kan vi bruge TinkConfig.register () metode:
TinkConfig.register ();
Mens vi f.eks. Kun har brug for AEAD-primitiv, kan vi bruge det AeadConfig.register () metode:
AeadConfig.register ();
En tilpasset initialisering leveres også til hver implementering.
4. Tink-primitiver
De vigtigste objekter, som biblioteket bruger, kaldes primitiver, der afhængigt af typen indeholder forskellige kryptografiske funktioner.
En primitiv kan have flere implementeringer:
Primitiv | Implementeringer |
---|---|
FREM | AES-EAX, AES-GCM, AES-CTR-HMAC, KMS-konvolut, CHACHA20-POLY1305 |
Streaming AEAD | AES-GCM-HKDF-STREAMING, AES-CTR-HMAC-STREAMING |
Deterministisk AEAD | FREM: AES-SIV |
MAC | HMAC-SHA2 |
Digital signatur | ECDSA over NIST-kurver, ED25519 |
Hybrid kryptering | ECIES med AEAD og HKDF, (NaCl CryptoBox) |
Vi kan opnå en primitiv ved at kalde metoden getPrimitive () af den tilsvarende fabriksklasse, der passerer den a KeysetHandle:
Aead aead = AeadFactory.getPrimitive (keysetHandle);
4.1. KeysetHandle
I orden for at give kryptografisk funktionalitet har hver primitiv brug for en nøglestruktur der indeholder alt nøglemateriale og parametre.
Tink giver et objekt - KeysetHandle - som ombryder et nøglesæt med nogle yderligere parametre og metadata.
Så inden vi opretter en primitiv, er vi nødt til at oprette en KeysetHandle objekt:
KeysetHandle keysetHandle = KeysetHandle.generateNew (AeadKeyTemplates.AES256_GCM);
Og efter at have genereret en nøgle, vil vi måske fortsætte den:
String keysetFilename = "keyset.json"; CleartextKeysetHandle.write (keysetHandle, JsonKeysetWriter.withFile (ny fil (keysetFilename)));
Derefter kan vi efterfølgende indlæse det:
String keysetFilename = "keyset.json"; KeysetHandle keysetHandle = CleartextKeysetHandle.read (JsonKeysetReader.withFile (ny fil (keysetFilename)));
5. Kryptering
Tink giver flere måder at anvende AEAD-algoritmen på. Lad os se.
5.1. FREM
AEAD leverer godkendt kryptering med tilknyttede data, hvilket betyder det vi kan kryptere almindelig tekst og eventuelt levere tilknyttede data, der skal godkendes, men ikke krypteres.
Bemærk, at denne algoritme sikrer ægtheden og integriteten af de tilknyttede data, men ikke dens hemmeligholdelse.
For at kryptere data med en af AEAD-implementeringerne, som vi tidligere har set, er vi nødt til at initialisere biblioteket og oprette en nøglesætHåndtag:
AeadConfig.register (); KeysetHandle keysetHandle = KeysetHandle.generateNew (AeadKeyTemplates.AES256_GCM);
Når vi har gjort det, kan vi hente det primitive og kryptere de ønskede data:
String plaintext = "baeldung"; String associatedData = "Tink"; Aead aead = AeadFactory.getPrimitive (keysetHandle); byte [] ciphertext = aead.encrypt (plaintext.getBytes (), associeretData.getBytes ());
Dernæst kan vi dekryptere ciphertext bruger dekryptere () metode:
Streng dekrypteret = ny streng (aead.decrypt (ciphertext, associatedData.getBytes ()));
5.2. Streaming AEAD
Tilsvarende når dataene, der skal krypteres, er for store til at blive behandlet i et enkelt trin, kan vi bruge streaming AEAD primitive:
AeadConfig.register (); KeysetHandle keysetHandle = KeysetHandle.generateNew (StreamingAeadKeyTemplates.AES128_CTR_HMAC_SHA256_4KB); StreamingAead streamingAead = StreamingAeadFactory.getPrimitive (keysetHandle); FileChannel cipherTextDestination = ny FileOutputStream ("cipherTextFile"). GetChannel (); WritableByteChannel encryptingChannel = streamingAead.newEncryptingChannel (cipherTextDestination, associatedData.getBytes ()); ByteBuffer buffer = ByteBuffer.allocate (CHUNK_SIZE); InputStream in = ny FileInputStream ("plainTextFile"); mens (in.available ()> 0) {in.read (buffer.array ()); encryptingChannel.write (buffer); } encryptingChannel.close (); i. luk ();
Dybest set havde vi brug for WriteableByteChannel for at opnå dette.
Så for at dekryptere cipherTextFile, vi ønsker at bruge en ReadableByteChannel:
FileChannel cipherTextSource = ny FileInputStream ("cipherTextFile"). GetChannel (); ReadableByteChannel decryptingChannel = streamingAead.newDecryptingChannel (cipherTextSource, associatedData.getBytes ()); OutputStream out = ny FileOutputStream ("plainTextFile"); int cnt = 1; gør {buffer.clear (); cnt = dekrypteringChannel.read (buffer); out.write (buffer.array ()); } mens (cnt> 0); dekrypteringChannel.close (); out.close ();
6. Hybrid kryptering
Ud over symmetrisk kryptering implementerer Tink et par primitiver til hybrid kryptering.
Med hybrid kryptering kan vi få effektiviteten af symmetriske nøgler og bekvemmeligheden ved asymmetriske nøgler.
Kort sagt, vi bruger en symmetrisk nøgle til at kryptere almindelig tekst og en offentlig nøgle til kun at kryptere den symmetriske nøgle.
Bemærk, at det kun giver hemmeligholdelse, ikke afsenderens identitetsægthed.
Så lad os se, hvordan du bruger HybridEncrypt og 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 ());
Det contextInfo er implicitte offentlige data fra den sammenhæng, der kan være nul eller tom eller bruges som "tilknyttet data" -indgang til AEAD-kryptering eller som "CtxInfo" -indgang til HKDF.
Det ciphertext muliggør kontrol af integriteten af contextInfo men ikke dens hemmeligholdelse eller ægthed.
7. Meddelelsesgodkendelseskode
Tink understøtter også meddelelsesgodkendelseskoder eller MAC'er.
En MAC er en blok på et par byte, som vi kan bruge til at godkende en besked.
Lad os se, hvordan vi kan oprette en MAC og derefter kontrollere dens ægthed:
TinkConfig.register (); KeysetHandle keysetHandle = KeysetHandle.generateNew (MacKeyTemplates.HMAC_SHA256_128BITTAG); Strengdata = "baeldung"; Mac mac = MacFactory.getPrimitive (keysetHandle); byte [] tag = mac.computeMac (data.getBytes ()); mac.verifyMac (tag, data.getBytes ());
I tilfælde af at dataene ikke er autentiske, er metoden verificereMac () kaster en GeneralSecurityException.
8. Digital signatur
Ud over krypterings-API'er understøtter Tink digitale signaturer.
For at implementere digital signatur bruger biblioteket PublicKeySign primitiv til signering af data, og PublickeyVerify til verifikation:
TinkConfig.register (); KeysetHandle privateKeysetHandle = KeysetHandle.generateNew (SignatureKeyTemplates.ECDSA_P256); KeysetHandle publicKeysetHandle = privateKeysetHandle.getPublicKeysetHandle (); Strengdata = "baeldung"; PublicKeySign signer = PublicKeySignFactory.getPrimitive (privateKeysetHandle); PublicKeyVerify verifier = PublicKeyVerifyFactory.getPrimitive (publicKeysetHandle); byte [] signatur = signer.sign (data.getBytes ()); verifier.verify (signatur, data.getBytes ());
Svarende til den tidligere krypteringsmetode, når signaturen er ugyldig, får vi en GeneralSecurityException.
9. Konklusion
I denne artikel introducerede vi Google Tink-biblioteket ved hjælp af dets Java-implementering.
Vi har set, hvordan man bruger til at kryptere og dekryptere data, og hvordan man beskytter dets integritet og ægthed. Desuden har vi set, hvordan man underskriver data ved hjælp af digitale signatur-API'er.
Som altid er prøvekoden tilgængelig på GitHub.