diff --git a/docs/getting-started/gs-encryption-decryption.md b/docs/getting-started/gs-encryption-decryption.md
index 66192c7d7..c1bc1522c 100644
--- a/docs/getting-started/gs-encryption-decryption.md
+++ b/docs/getting-started/gs-encryption-decryption.md
@@ -206,6 +206,11 @@ The following code example encrypts requests and decrypts responses using C#. Th
This file requires .NET 7.0. You can use an earlier version if required, but it must be .NET Core 3.0 or later. To change the version, replace the [top-level statements](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/top-level-statements) with a Main method and the [using declarations](https://learn.microsoft.com/en-us/cpp/cpp/using-declaration?view=msvc-170) with [using statements](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/using).
+
+
+
+The following code example encrypts requests and decrypts responses using Go. The required parameters are shown at the bottom of the file, or by running `go run uid2_request.go`.
+
@@ -577,4 +582,246 @@ else
```
+
+
+
+
+```go title="uid2_request.go"
+package main
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/rand"
+ "encoding/base64"
+ "encoding/binary"
+ "encoding/json"
+ "fmt"
+ "io"
+ "log"
+ "net/http"
+ "os"
+ "strings"
+ "time"
+)
+
+const (
+ nonceLengthBytes = 8
+ gcmIVLengthBytes = 12
+)
+
+func main() {
+ subArgs := os.Args[1:]
+
+ if len(subArgs) != 3 && len(subArgs) != 4 {
+ printUsage()
+ os.Exit(1)
+ }
+
+ url := subArgs[0]
+
+ response, err := func() (map[string]interface{}, error) {
+ if subArgs[1] == "--refresh-token" {
+ return refresh(url, subArgs[2], subArgs[3])
+ } else {
+ return generate(url, subArgs[1], subArgs[2])
+ }
+ }()
+
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ prettyPrint(response)
+}
+
+func refresh(url string, refreshToken string, refreshResponseKey string) (map[string]interface{}, error) {
+ fmt.Printf("Request: Sending refresh_token to %s\n", url)
+
+ response, err := http.Post(url, "", strings.NewReader(refreshToken))
+ if err != nil {
+ return nil, err
+ }
+
+ return deserializeResponse(response, refreshResponseKey, true)
+}
+
+func generate(url string, apiKey string, secret string) (map[string]interface{}, error) {
+ payload, err := io.ReadAll(os.Stdin)
+ if err != nil {
+ return nil, err
+ }
+
+ key, err := base64.StdEncoding.DecodeString(secret)
+ if err != nil {
+ return nil, err
+ }
+
+ unencryptedEnvelope, err := makeUnencryptedEnvelope(payload)
+ if err != nil {
+ return nil, err
+ }
+
+ envelope, err := makeEncryptedEnvelope(unencryptedEnvelope, key)
+ if err != nil {
+ return nil, err
+ }
+
+ req, err := http.NewRequest("POST", url, strings.NewReader(base64.StdEncoding.EncodeToString(envelope)))
+ if err != nil {
+ return nil, err
+ }
+
+ req.Header.Add("Authorization", "Bearer "+apiKey)
+
+ response, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return nil, err
+ }
+
+ return deserializeResponse(response, secret, false)
+}
+
+func aesgcm(key []byte) (cipher.AEAD, error) {
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, err
+ }
+
+ return cipher.NewGCM(block)
+}
+
+func decryptResponse(ciphertext string, key string) ([]byte, error) {
+ ciphertextBytes, err := base64.StdEncoding.DecodeString(ciphertext)
+ if err != nil {
+ return nil, err
+ }
+
+ keyBytes, err := base64.StdEncoding.DecodeString(key)
+ if err != nil {
+ return nil, err
+ }
+
+ aesgcm, err := aesgcm(keyBytes)
+ if err != nil {
+ return nil, err
+ }
+
+ iv := ciphertextBytes[:gcmIVLengthBytes]
+ return aesgcm.Open(nil, iv, ciphertextBytes[gcmIVLengthBytes:], nil)
+}
+
+func deserialize(bytes []byte) (map[string]interface{}, error) {
+ var anyJson map[string]interface{}
+ err := json.Unmarshal(bytes, &anyJson)
+ return anyJson, err
+}
+
+func prettyPrint(obj map[string]interface{}) error {
+ bytes, err := json.MarshalIndent(obj, "", " ")
+ if err != nil {
+ return err
+ }
+
+ fmt.Println(string(bytes))
+ return nil
+}
+
+func checkStatusCode(response *http.Response, body []byte) error {
+ if response.StatusCode != http.StatusOK {
+ return fmt.Errorf("Response: Error HTTP status code %d\n%s", response.StatusCode, body)
+ }
+
+ return nil
+}
+
+func makeUnencryptedEnvelope(payload []byte) ([]byte, error) {
+ timestamp := make([]byte, 8)
+ binary.BigEndian.PutUint64(timestamp, uint64(time.Now().UnixMilli()))
+
+ nonce := make([]byte, nonceLengthBytes)
+ _, err := rand.Read(nonce)
+ if err != nil {
+ return nil, err
+ }
+
+ var body bytes.Buffer
+ body.Write(timestamp)
+ body.Write(nonce)
+ body.Write(payload)
+ return body.Bytes(), nil
+}
+
+func encrypt(plaintext []byte, iv []byte, key []byte) ([]byte, error) {
+ aesgcm, err := aesgcm(key)
+ if err != nil {
+ return nil, err
+ }
+
+ return aesgcm.Seal(nil, iv, plaintext, nil), nil
+}
+
+func makeEncryptedEnvelope(payload []byte, key []byte) ([]byte, error) {
+ iv := make([]byte, gcmIVLengthBytes)
+ _, err := rand.Read(iv)
+ if err != nil {
+ return nil, err
+ }
+
+ ciphertext, err := encrypt(payload, iv, key)
+ if err != nil {
+ return nil, err
+ }
+
+ var envelope bytes.Buffer
+ envelope.WriteByte(1)
+ envelope.Write(iv)
+ envelope.Write(ciphertext)
+ return envelope.Bytes(), nil
+}
+
+func deserializeResponse(response *http.Response, key string, isRefresh bool) (map[string]interface{}, error) {
+ defer response.Body.Close()
+
+ body, err := io.ReadAll(response.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ err = checkStatusCode(response, body)
+ if err != nil {
+ return nil, err
+ }
+
+ plaintext, err := decryptResponse(string(body), key)
+ if err != nil {
+ return nil, err
+ }
+
+ offset := 16
+ if isRefresh {
+ offset = 0
+ }
+
+ return deserialize(plaintext[offset:])
+}
+
+func printUsage() {
+ fmt.Println(`Usage:
+ echo '' | go run uid2_request.go
+
+Example:
+ echo '{"email": "test@example.com", "optout_check": 1}' | go run uid2_request.go https://prod.uidapi.com/v2/token/generate UID2-C-L-999-fCXrMM.fsR3mDqAXELtWWMS+xG1s7RdgRTMqdOH2qaAo= wJ0hP19QU4hmpB64Y3fV2dAed8t/mupw3sjN5jNRFzg=
+
+
+Refresh Token Usage:
+ go run uid2_request.go --refresh-token
+
+Refresh Token Usage example:
+ go run uid2_request.go https://prod.uidapi.com/v2/token/refresh --refresh-token AAAAAxxJ...(truncated, total 388 chars) v2ixfQv8eaYNBpDsk5ktJ1yT4445eT47iKC66YJfb1s=`)
+}
+```
+
+