The keys
- A KMS key wraps each organization’s key, with the organization in the encryption context, so a wrapped key opens only as its own.
- The organization key wraps each of its project keys, bound to the project’s name and version.
- A project key is 256 random bits. Separate subkeys are derived from it with HKDF for chunk IDs, for content, and for authenticating records.
Sealing
- A chunk’s ID is an HMAC of its content under the project’s ID key. The same file has different IDs in different projects, so no one can tell whether a project holds a known file.
- Each chunk is compressed when that helps, then sealed with AES-256-GCM under a key derived for that chunk alone. The same content in the same project seals the same way, so it’s stored once. The same content in two projects never matches.
- Every chunk is checked against its ID when it’s read, so a store or a cache that serves the wrong bytes is caught.
- Records whose content changes under one name, like Bazel cache entries, are sealed with a fresh nonce each time.