Tink APIs take arbitrary binary blobs as input. This means that if you want to
encrypt structured data, like
[protocol buffers](https://developers.google.com/protocol-buffers), you need to
encode the data first.

## Encrypt a protobuf

To encrypt:

1. Serialize the protobuf to a byte array.
2. Encrypt the serialized bytes, then store or send the resulting ciphertext. Use:
   - [Authenticated encryption with associated data (AEAD)](https://developers.google.com/tink/aead)
   - [Hybrid encryption](https://developers.google.com/tink/hybrid)
   - [Deterministic AEAD](https://developers.google.com/tink/deterministic-aead)

To decrypt:

1. Decrypt the ciphertext.
2. If Step 1 was successful, deserialize the protobuf.

## Protect a protobuf from tampering

In most cases, encrypting a protobuf is preferable to authentication alone.

To protect a protobuf from tampering:

1. Serialize the protobuf to a byte array.
2. Sign or authenticate the serialized bytes. Use:
   - [Digital signature](https://developers.google.com/tink/digital-signature)
   - [MAC](https://developers.google.com/tink/mac)
3. Store the serialized bytes together with the signature (or MAC).

To verify:

1. Get the serialized protobuf and its signature (or MAC).
2. Verify the signature (or MAC).
3. Deserialize the protobuf.

Note that a valid signature or MAC does not guarantee that the data is correctly
formatted. An implementation that parses the data should always expect that the
data might be corrupt.

## Protect multiple data items

To protect multiple data items, use a serialization method. Add all of the data
items to a protobuf, and encrypt (or authenticate) it as described above.

You can also serialize as follows:

    serialize(data1 , data2 , ..., datan) = 4-byte-data1's length || data1 || 4-byte-data2's length || data2 || ... || 4-byte-dataN's length || dataN

> [!WARNING]
> **Warning:** Concatenating without a length prefix, like `data1 || data2 || ... || dataN`, can lead to vulnerabilities as the resulting encoding is ambiguous. For example if `data1 = "foo"` and `data2 = "bar"`, this would lead to the same encoded data as `data1 = "fooba"` and `data2 = "r"`.

Finally, encrypt (or authenticate) the resulting byte array.