xref: /aosp_15_r20/external/tink/docs/GOLANG-HOWTO.md (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1*e7b1675dSTing-Kang Chang# Tink for Go HOW-TO
2*e7b1675dSTing-Kang Chang
3*e7b1675dSTing-Kang ChangThis document contains instructions for common tasks in
4*e7b1675dSTing-Kang Chang[Tink](https://github.com/google/tink). Example code snippets for these tasks
5*e7b1675dSTing-Kang Changand API documentation can be found on
6*e7b1675dSTing-Kang Chang[pkg.go.dev](https://pkg.go.dev/github.com/google/tink/go).
7*e7b1675dSTing-Kang Chang
8*e7b1675dSTing-Kang Chang## Setup instructions
9*e7b1675dSTing-Kang Chang
10*e7b1675dSTing-Kang ChangTo install Tink locally run:
11*e7b1675dSTing-Kang Chang
12*e7b1675dSTing-Kang Chang```sh
13*e7b1675dSTing-Kang Changgo get github.com/google/tink/go/...
14*e7b1675dSTing-Kang Chang```
15*e7b1675dSTing-Kang Chang
16*e7b1675dSTing-Kang Changto run all the tests locally:
17*e7b1675dSTing-Kang Chang
18*e7b1675dSTing-Kang Chang```sh
19*e7b1675dSTing-Kang Changcd $GOPATH/go/src/github.com/google/tink/go
20*e7b1675dSTing-Kang Changgo test ./...
21*e7b1675dSTing-Kang Chang```
22*e7b1675dSTing-Kang Chang
23*e7b1675dSTing-Kang ChangGolang Tink API also supports [Bazel](https://www.bazel.build) builds. To run
24*e7b1675dSTing-Kang Changthe tests using bazel:
25*e7b1675dSTing-Kang Chang
26*e7b1675dSTing-Kang Chang```sh
27*e7b1675dSTing-Kang Changcd $GOPATH/go/src/github.com/google/tink/go
28*e7b1675dSTing-Kang Changbazel build ... && bazel test ...
29*e7b1675dSTing-Kang Chang```
30*e7b1675dSTing-Kang Chang
31*e7b1675dSTing-Kang Chang## Generating new keys and keysets
32*e7b1675dSTing-Kang Chang
33*e7b1675dSTing-Kang ChangTo take advantage of key rotation and other key management features, you usually
34*e7b1675dSTing-Kang Changdo not work with single keys, but with keysets. Keysets are just sets of keys
35*e7b1675dSTing-Kang Changwith some additional parameters and metadata.
36*e7b1675dSTing-Kang Chang
37*e7b1675dSTing-Kang ChangInternally Tink stores keysets as Protocol Buffers, but you can work with
38*e7b1675dSTing-Kang Changkeysets via a wrapper called a keyset handle. You can generate a new keyset and
39*e7b1675dSTing-Kang Changobtain its handle using a KeyTemplate. KeysetHandle objects enforce certain
40*e7b1675dSTing-Kang Changrestrictions that prevent accidental leakage of the sensitive key material.
41*e7b1675dSTing-Kang Chang
42*e7b1675dSTing-Kang Chang```go
43*e7b1675dSTing-Kang Changpackage main
44*e7b1675dSTing-Kang Chang
45*e7b1675dSTing-Kang Changimport (
46*e7b1675dSTing-Kang Chang  "fmt"
47*e7b1675dSTing-Kang Chang  "log"
48*e7b1675dSTing-Kang Chang
49*e7b1675dSTing-Kang Chang  "github.com/google/tink/go/aead"
50*e7b1675dSTing-Kang Chang  "github.com/google/tink/go/keyset"
51*e7b1675dSTing-Kang Chang)
52*e7b1675dSTing-Kang Chang
53*e7b1675dSTing-Kang Changfunc main() {
54*e7b1675dSTing-Kang Chang  // Other key templates can also be used.
55*e7b1675dSTing-Kang Chang  kh, err := keyset.NewHandle(aead.AES128GCMKeyTemplate())
56*e7b1675dSTing-Kang Chang  if err != nil {
57*e7b1675dSTing-Kang Chang    log.Fatal(err)
58*e7b1675dSTing-Kang Chang  }
59*e7b1675dSTing-Kang Chang
60*e7b1675dSTing-Kang Chang  fmt.Println(kh.String())
61*e7b1675dSTing-Kang Chang}
62*e7b1675dSTing-Kang Chang
63*e7b1675dSTing-Kang Chang```
64*e7b1675dSTing-Kang Chang
65*e7b1675dSTing-Kang ChangKey templates are available for MAC, digital signatures, AEAD encryption, DAEAD
66*e7b1675dSTing-Kang Changencryption and hybrid encryption.
67*e7b1675dSTing-Kang Chang
68*e7b1675dSTing-Kang ChangKey Template Type | Key Template
69*e7b1675dSTing-Kang Chang----------------- | ------------------------------------------------
70*e7b1675dSTing-Kang ChangAEAD              | aead.AES128CTRHMACSHA256KeyTemplate()
71*e7b1675dSTing-Kang ChangAEAD              | aead.AES128GCMKeyTemplate()
72*e7b1675dSTing-Kang ChangAEAD              | aead.AES256CTRHMACSHA256KeyTemplate()
73*e7b1675dSTing-Kang ChangAEAD              | aead.AES256GCMKeyTemplate()
74*e7b1675dSTing-Kang ChangAEAD              | aead.ChaCha20Poly1305KeyTemplate()
75*e7b1675dSTing-Kang ChangAEAD              | aead.XChaCha20Poly1305KeyTemplate()
76*e7b1675dSTing-Kang ChangDAEAD             | daead.AESSIVKeyTemplate()
77*e7b1675dSTing-Kang ChangMAC               | mac.HMACSHA256Tag128KeyTemplate()
78*e7b1675dSTing-Kang ChangMAC               | mac.HMACSHA256Tag256KeyTemplate()
79*e7b1675dSTing-Kang ChangMAC               | mac.HMACSHA512Tag256KeyTemplate()
80*e7b1675dSTing-Kang ChangMAC               | mac.HMACSHA512Tag512KeyTemplate()
81*e7b1675dSTing-Kang ChangSignature         | signature.ECDSAP256KeyTemplate()
82*e7b1675dSTing-Kang ChangSignature         | signature.ECDSAP384KeyTemplate()
83*e7b1675dSTing-Kang ChangSignature         | signature.ECDSAP521KeyTemplate()
84*e7b1675dSTing-Kang ChangHybrid            | hybrid.ECIESHKDFAES128GCMKeyTemplate()
85*e7b1675dSTing-Kang ChangHybrid            | hybrid.ECIESHKDFAES128CTRHMACSHA256KeyTemplate()
86*e7b1675dSTing-Kang Chang
87*e7b1675dSTing-Kang ChangTo avoid accidental leakage of sensitive key material, you should avoid mixing
88*e7b1675dSTing-Kang Changkeyset generation and usage in code. To support the separation of these
89*e7b1675dSTing-Kang Changactivities Tink provides a command-line tool, [Tinkey](TINKEY.md), which can be
90*e7b1675dSTing-Kang Changused for common key management tasks.
91*e7b1675dSTing-Kang Chang
92*e7b1675dSTing-Kang Chang## Storing and loading existing keysets
93*e7b1675dSTing-Kang Chang
94*e7b1675dSTing-Kang ChangAfter generating key material, you might want to persist it to a storage system.
95*e7b1675dSTing-Kang ChangTink supports encrypting and persisting the keys to any io.Writer and io.Reader
96*e7b1675dSTing-Kang Changimplementations.
97*e7b1675dSTing-Kang Chang
98*e7b1675dSTing-Kang Chang```go
99*e7b1675dSTing-Kang Changpackage main
100*e7b1675dSTing-Kang Chang
101*e7b1675dSTing-Kang Changimport (
102*e7b1675dSTing-Kang Chang  "fmt"
103*e7b1675dSTing-Kang Chang  "log"
104*e7b1675dSTing-Kang Chang
105*e7b1675dSTing-Kang Chang  "github.com/google/tink/go/aead"
106*e7b1675dSTing-Kang Chang  "github.com/google/tink/go/core/registry"
107*e7b1675dSTing-Kang Chang  "github.com/google/tink/go/integration/gcpkms"
108*e7b1675dSTing-Kang Chang  "github.com/google/tink/go/keyset"
109*e7b1675dSTing-Kang Chang)
110*e7b1675dSTing-Kang Chang
111*e7b1675dSTing-Kang Changconst (
112*e7b1675dSTing-Kang Chang  // Change this. AWS KMS, Google Cloud KMS and HashiCorp Vault are supported out of the box.
113*e7b1675dSTing-Kang Chang   keyURI = "gcp-kms://projects/tink-examples/locations/global/keyRings/foo/cryptoKeys/bar"
114*e7b1675dSTing-Kang Chang  credentialsPath = "credentials.json"
115*e7b1675dSTing-Kang Chang)
116*e7b1675dSTing-Kang Chang
117*e7b1675dSTing-Kang Changfunc main() {
118*e7b1675dSTing-Kang Chang  // Generate a new keyset handle.
119*e7b1675dSTing-Kang Chang  handle1, err := keyset.NewHandle(aead.AES128GCMKeyTemplate())
120*e7b1675dSTing-Kang Chang  if err != nil {
121*e7b1675dSTing-Kang Chang    log.Fatal(err)
122*e7b1675dSTing-Kang Chang  }
123*e7b1675dSTing-Kang Chang
124*e7b1675dSTing-Kang Chang  // Get the key encryption AEAD from a KMS.
125*e7b1675dSTing-Kang Chang  gcpClient, err := gcpkms.NewClientWithCredentials(keyURI, credentialsPath)
126*e7b1675dSTing-Kang Chang  if err != nil {
127*e7b1675dSTing-Kang Chang    log.Fatal(err)
128*e7b1675dSTing-Kang Chang  }
129*e7b1675dSTing-Kang Chang  registry.RegisterKMSClient(gcpClient)
130*e7b1675dSTing-Kang Chang  keyEncryptionAEAD, err := gcpClient.GetAEAD(keyURI)
131*e7b1675dSTing-Kang Chang  if err != nil {
132*e7b1675dSTing-Kang Chang    log.Fatal(err)
133*e7b1675dSTing-Kang Chang  }
134*e7b1675dSTing-Kang Chang
135*e7b1675dSTing-Kang Chang  // Serialize and encrypt the keyset handle using the key encryption AEAD.
136*e7b1675dSTing-Kang Chang  // We strongly recommend that you encrypt the keyset handle before persisting
137*e7b1675dSTing-Kang Chang  // it.
138*e7b1675dSTing-Kang Chang  buf := new(bytes.Buffer)
139*e7b1675dSTing-Kang Chang  writer := keyset.NewBinaryWriter(buf)
140*e7b1675dSTing-Kang Chang  err = handle1.Write(writer, keyEncryptionAEAD)
141*e7b1675dSTing-Kang Chang  if err != nil {
142*e7b1675dSTing-Kang Chang    log.Fatal(err)
143*e7b1675dSTing-Kang Chang  }
144*e7b1675dSTing-Kang Chang  encryptedHandle := buf.Bytes()
145*e7b1675dSTing-Kang Chang
146*e7b1675dSTing-Kang Chang  // Decrypt and parse the encrypted keyset using the key encryption AEAD.
147*e7b1675dSTing-Kang Chang  reader := keyset.NewBinaryReader(bytes.NewReader(encryptedHandle))
148*e7b1675dSTing-Kang Chang  handle2, err := keyset.Read(reader, keyEncryptionAEAD)
149*e7b1675dSTing-Kang Chang  if err != nil {
150*e7b1675dSTing-Kang Chang    log.Fatal(err)
151*e7b1675dSTing-Kang Chang  }
152*e7b1675dSTing-Kang Chang}
153*e7b1675dSTing-Kang Chang```
154*e7b1675dSTing-Kang Chang
155*e7b1675dSTing-Kang Chang## AEAD
156*e7b1675dSTing-Kang Chang
157*e7b1675dSTing-Kang ChangThe AEAD primitive (authenticated encryption with associated data) is the most
158*e7b1675dSTing-Kang Changcommon primitive to ***encrypt*** data. It is symmetric, and using the same key
159*e7b1675dSTing-Kang Changfor encryption and decryption.
160*e7b1675dSTing-Kang Chang
161*e7b1675dSTing-Kang ChangCheck out the
162*e7b1675dSTing-Kang Chang[AEAD examples](https://pkg.go.dev/github.com/google/tink/go/aead#example-package).
163*e7b1675dSTing-Kang ChangThe `Play` button at the corner right allows you to run them on the Go
164*e7b1675dSTing-Kang ChangPlayground.
165*e7b1675dSTing-Kang Chang
166*e7b1675dSTing-Kang Chang## Deterministic AEAD
167*e7b1675dSTing-Kang Chang
168*e7b1675dSTing-Kang ChangThe Deterministic AEAD primitive (authenticated encryption with associated data)
169*e7b1675dSTing-Kang Changis used to ***deterministically encrypt*** data. It is symmetric, and using the
170*e7b1675dSTing-Kang Changsame key for encryption and decryption.
171*e7b1675dSTing-Kang Chang
172*e7b1675dSTing-Kang ChangUnlike AEAD, implementations of this interface are not semantically secure,
173*e7b1675dSTing-Kang Changbecause encrypting the same plaintext always yields the same ciphertext.
174*e7b1675dSTing-Kang Chang
175*e7b1675dSTing-Kang ChangCheck out the
176*e7b1675dSTing-Kang Chang[Deterministic AEAD examples](https://pkg.go.dev/github.com/google/tink/go/daead#example-package).
177*e7b1675dSTing-Kang ChangThe `Play` button at the corner right allows you to run them on the Go
178*e7b1675dSTing-Kang ChangPlayground.
179*e7b1675dSTing-Kang Chang
180*e7b1675dSTing-Kang Chang## MAC
181*e7b1675dSTing-Kang Chang
182*e7b1675dSTing-Kang ChangThe MAC primitive allows you to ensure that nobody tampers with data you own. It
183*e7b1675dSTing-Kang Changis symmetric, and using the same key for authentication and verification.
184*e7b1675dSTing-Kang Chang
185*e7b1675dSTing-Kang ChangCheck out the
186*e7b1675dSTing-Kang Chang[MAC examples](https://pkg.go.dev/github.com/google/tink/go/mac#example-package).
187*e7b1675dSTing-Kang ChangThe `Play` button at the corner right allows you to run them on the Go
188*e7b1675dSTing-Kang ChangPlayground.
189*e7b1675dSTing-Kang Chang
190*e7b1675dSTing-Kang Chang## Digital signature
191*e7b1675dSTing-Kang Chang
192*e7b1675dSTing-Kang ChangThe digital signature primitives allow you to ensure that nobody tampers with
193*e7b1675dSTing-Kang Changyour data. It is asymmetric, and hence comes with a pair of keys (public key and
194*e7b1675dSTing-Kang Changprivate key). The private key allows to sign messages, and the public key allows
195*e7b1675dSTing-Kang Changto verify.
196*e7b1675dSTing-Kang Chang
197*e7b1675dSTing-Kang ChangCheck out the
198*e7b1675dSTing-Kang Chang[digital signature examples](https://pkg.go.dev/github.com/google/tink/go/signature#example-package).
199*e7b1675dSTing-Kang ChangThe `Play` button at the corner right allows you to run them on the Go
200*e7b1675dSTing-Kang ChangPlayground.
201*e7b1675dSTing-Kang Chang
202*e7b1675dSTing-Kang Chang## Hybrid encryption
203*e7b1675dSTing-Kang Chang
204*e7b1675dSTing-Kang ChangThe hybrid encryption primitives allow you to encrypt data with a public key.
205*e7b1675dSTing-Kang ChangOnly users with the secret key will be able to decrypt the data.
206*e7b1675dSTing-Kang Chang
207*e7b1675dSTing-Kang ChangCheck out the
208*e7b1675dSTing-Kang Chang[hybrid encryption examples](https://pkg.go.dev/github.com/google/tink/go/hybrid#example-package).
209*e7b1675dSTing-Kang ChangThe `Play` button at the corner right allows you to run them on the Go
210*e7b1675dSTing-Kang ChangPlayground.
211*e7b1675dSTing-Kang Chang
212*e7b1675dSTing-Kang Chang## Envelope encryption
213*e7b1675dSTing-Kang Chang
214*e7b1675dSTing-Kang ChangVia the AEAD interface, Tink supports
215*e7b1675dSTing-Kang Chang[envelope encryption](KEY-MANAGEMENT.md#envelope-encryption).
216*e7b1675dSTing-Kang Chang
217*e7b1675dSTing-Kang ChangFor example, you can perform envelope encryption with a Google Cloud KMS key at
218*e7b1675dSTing-Kang Chang`gcp-kms://projects/tink-examples/locations/global/keyRings/foo/cryptoKeys/bar`
219*e7b1675dSTing-Kang Changusing the credentials in `credentials.json` as follows:
220*e7b1675dSTing-Kang Chang
221*e7b1675dSTing-Kang Chang```go
222*e7b1675dSTing-Kang Changpackage main
223*e7b1675dSTing-Kang Chang
224*e7b1675dSTing-Kang Changimport (
225*e7b1675dSTing-Kang Chang  "encoding/base64"
226*e7b1675dSTing-Kang Chang  "fmt"
227*e7b1675dSTing-Kang Chang
228*e7b1675dSTing-Kang Chang  "github.com/google/tink/go/aead"
229*e7b1675dSTing-Kang Chang  "github.com/google/tink/go/core/registry"
230*e7b1675dSTing-Kang Chang  "github.com/google/tink/go/integration/gcpkms"
231*e7b1675dSTing-Kang Chang  "github.com/google/tink/go/keyset"
232*e7b1675dSTing-Kang Chang)
233*e7b1675dSTing-Kang Chang
234*e7b1675dSTing-Kang Changconst (
235*e7b1675dSTing-Kang Chang   // Change this. AWS KMS, Google Cloud KMS and HashiCorp Vault are supported out of the box.
236*e7b1675dSTing-Kang Chang   keyURI          = "gcp-kms://projects/tink-examples/locations/global/keyRings/foo/cryptoKeys/bar"
237*e7b1675dSTing-Kang Chang   credentialsPath = "credentials.json"
238*e7b1675dSTing-Kang Chang)
239*e7b1675dSTing-Kang Chang
240*e7b1675dSTing-Kang Changfunc main() {
241*e7b1675dSTing-Kang Chang  gcpclient, err := gcpkms.NewClientWithCredentials(keyURI, credentialsPath)
242*e7b1675dSTing-Kang Chang  if err != nil {
243*e7b1675dSTing-Kang Chang    log.Fatal(err)
244*e7b1675dSTing-Kang Chang  }
245*e7b1675dSTing-Kang Chang  registry.RegisterKMSClient(gcpclient)
246*e7b1675dSTing-Kang Chang
247*e7b1675dSTing-Kang Chang  dek := aead.AES128CTRHMACSHA256KeyTemplate()
248*e7b1675dSTing-Kang Chang  kh, err := keyset.NewHandle(aead.KMSEnvelopeAEADKeyTemplate(keyURI, dek))
249*e7b1675dSTing-Kang Chang  if err != nil {
250*e7b1675dSTing-Kang Chang    log.Fatal(err)
251*e7b1675dSTing-Kang Chang  }
252*e7b1675dSTing-Kang Chang
253*e7b1675dSTing-Kang Chang  a, err := aead.New(kh)
254*e7b1675dSTing-Kang Chang  if err != nil {
255*e7b1675dSTing-Kang Chang    log.Fatal(err)
256*e7b1675dSTing-Kang Chang  }
257*e7b1675dSTing-Kang Chang
258*e7b1675dSTing-Kang Chang  msg := []byte("this message needs to be encrypted")
259*e7b1675dSTing-Kang Chang  aad := []byte("this data needs to be authenticated, but not encrypted")
260*e7b1675dSTing-Kang Chang  ct, err := a.Encrypt(msg, aad)
261*e7b1675dSTing-Kang Chang  if err != nil {
262*e7b1675dSTing-Kang Chang    log.Fatal(err)
263*e7b1675dSTing-Kang Chang  }
264*e7b1675dSTing-Kang Chang
265*e7b1675dSTing-Kang Chang  pt, err := a.Decrypt(ct, aad)
266*e7b1675dSTing-Kang Chang  if err != nil {
267*e7b1675dSTing-Kang Chang    log.Fatal(err)
268*e7b1675dSTing-Kang Chang  }
269*e7b1675dSTing-Kang Chang
270*e7b1675dSTing-Kang Chang  fmt.Printf("Ciphertext: %s\n", base64.StdEncoding.EncodeToString(ct))
271*e7b1675dSTing-Kang Chang  fmt.Printf("Original  plaintext: %s\n", msg)
272*e7b1675dSTing-Kang Chang  fmt.Printf("Decrypted Plaintext: %s\n", pt)
273*e7b1675dSTing-Kang Chang}
274*e7b1675dSTing-Kang Chang```
275