diff --git a/docs/sdks/tdf.mdx b/docs/sdks/tdf.mdx index af082cdf..319e8ca3 100644 --- a/docs/sdks/tdf.mdx +++ b/docs/sdks/tdf.mdx @@ -1,10 +1,234 @@ --- sidebar_position: 4 +title: TDF --- import EncryptionTDF from '../../code_samples/tdf/encryption_ztdf.mdx' +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +# TDF Encryption and Decryption -# Creating TDFs +This page covers TDF encryption/decryption behavior, SDK method usage patterns, and operational checks. - \ No newline at end of file +## Overview + +TDF combines encrypted payload data with policy metadata so access control can travel with the data itself. + +When you create a TDF, you are packaging: + +1. Encrypted payload bytes. +2. Policy metadata (for example attribute value FQNs). +3. Key access metadata used by the KAS to enforce decryption authorization. + +At read time, decryption succeeds only if the caller identity is entitled for the policy encoded in the TDF. + +## SDK Method Reference + +### Go SDK (platform code) + +| Method | Purpose | +| --- | --- | +| `SDK.CreateTDF` | Encrypt input and write a TDF artifact. | +| `SDK.CreateTDFContext` | Context-aware version of `CreateTDF`. | +| `SDK.LoadTDF` | Load/parse TDF and return a `Reader`. | +| `TDFObject.Size` | Return generated TDF size. | +| `TDFObject.Manifest` | Return manifest from created TDF object. | +| `Reader.Manifest` | Return loaded manifest. | +| `Reader.Init` | Perform network/key unwrap initialization before reads. | +| `Reader.Read` | Read decrypted payload bytes sequentially. | +| `Reader.Seek` | Move read cursor for `Read`/`WriteTo`. | +| `Reader.WriteTo` | Stream decrypted payload to a writer. | +| `Reader.ReadAt` | Read decrypted payload bytes at offset. | +| `Reader.UnencryptedMetadata` | Return decrypted metadata from manifest. | +| `Reader.Policy` | Return policy object from manifest. | +| `Reader.DataAttributes` | Return data attribute FQNs in policy. | +| `Reader.Obligations` | Return required obligations for access. | +| `Reader.UnsafePayloadKeyRetrieval` | Return payload key (unsafe/debug use). | + +### Java and TypeScript (methods currently documented in this repo) + +| Operation | Java | TypeScript | +| --- | --- | --- | +| Encrypt | `createTDF` | `createZTDF` | +| Load/read encrypted artifact | `loadTDF` | `read` | +| Emit decrypted payload | `readPayload` | consume returned `DecoratedStream` | + +## Method Details + +### `CreateTDF` / `createTDF` / `createZTDF` + +Encrypts input data and returns/writes a TDF artifact. + + + + +```go +manifest, err := client.CreateTDF(outputWriter, inputReader /* opts... */) +``` + + + + +```java +sdk.createTDF(inputStream, outputStream, tdfConfig); +``` + + + + +```typescript +const tdf = await client.createZTDF(opts); +``` + + + + +### `LoadTDF` / `loadTDF` / `read` + +Loads encrypted TDF content and prepares it for decryption. + + + + +```go +tdfReader, err := client.LoadTDF(bytes.NewReader(tdfBytes) /* opts... */) +``` + + + + +```java +var reader = sdk.loadTDF(fileChannel, readerConfig); +``` + + + + +```typescript +const decoratedStream = await client.read(readOptions); +``` + + + + +### `WriteTo` / `readPayload` / consume `DecoratedStream` + +Produces decrypted payload bytes after key unwrap and policy checks succeed. + + + + +```go +_, err = tdfReader.WriteTo(&decryptedBuffer) +``` + + + + +```java +reader.readPayload(decryptedOutput); +``` + + + + +```typescript +const decrypted = await new Response(decoratedStream).text(); +``` + + + + +## Encryption and Decryption Flow + +```mermaid +flowchart TB + A["1. Plaintext input"] --> B["2. Create TDF or zTDF"] + B --> C["3. Attach ABAC attributes"] + C --> D["4. Add KAS key wrapping metadata"] + D --> E["5. Encrypted TDF artifact"] + E --> F["6. Load artifact for read"] + F --> G["7. KAS rewrap and policy check"] + G --> H["8. Decrypt payload if entitled"] +``` + +## End-to-End Example (Go, Java, TypeScript) + +The sample below includes encrypt + decrypt flows for all three SDK ecosystems: + + + +## ABAC Attributes + +Policy is enforced at decrypt time, so getting attribute values right at encryption time is critical. + +Recommended pattern: + +1. Validate attribute value FQNs before encryption using `GetAttributeValuesByFqns` (or the equivalent helper exposed by your SDK wrapper). +2. Encrypt with those validated FQNs. +3. Ensure a [subject mapping](/components/policy/subject_mappings) exists for identities that should decrypt. + +Related guides: + +- Attribute validation and discovery: [/sdks/discovery](/sdks/discovery) +- Subject mappings and actions: [/sdks/policy](/sdks/policy) +- Permission failure diagnosis: [/sdks/troubleshooting#permission-denied--insufficient-entitlements](/sdks/troubleshooting#permission-denied--insufficient-entitlements) + +## Decryption Patterns + +### In-memory data + +Use in-memory readers/writers when payloads are small and request-scoped. +Examples include `bytes.Buffer` (Go), `ByteArrayInputStream`/`ByteArrayOutputStream` (Java), and `Buffer`/`ReadableStream` (TypeScript). + +### File-based workflow + +Use file streams/channels for larger payloads or asynchronous pipelines (encrypt now, decrypt later in another process). + +### Offline handoff + +You can persist `.tdf` artifacts and decrypt later, as long as the decrypting identity can still reach required platform services (for example KAS and authorization dependencies) and has valid entitlements. + +## Encryption Options + +For production use, avoid relying on implicit defaults. + +1. KAS endpoint configuration. +2. Attribute value set (policy scope). +3. Wrapping/encapsulation algorithm choice where supported. +4. Data handling model: in-memory vs stream/file. +5. Expected interoperability target (`zTDF` profile vs full container exchange). + +You can see concrete option usage in the SDK quickstarts and the multi-language end-to-end example above. + +## Error Handling + +Treat these as first-class integration paths, not edge cases: + +| Failure Class | Typical Symptom | What to Do | +| --- | --- | --- | +| Authentication | `Unauthenticated`, `401` | Verify credentials and OIDC/client setup. See [Authentication Failed](/sdks/troubleshooting#authentication-failed). | +| TLS trust | cert validation failures | Trust local CA correctly; avoid disabling verification in production. See [Certificate Errors](/sdks/troubleshooting#certificate-errors-ssltls). | +| Missing entitlements | split-key/rewrap failures, `PermissionDenied` | Create/verify subject mappings for required attribute values. See [Permission Denied](/sdks/troubleshooting#permission-denied--insufficient-entitlements). | +| Missing attributes | `not_found` during policy resolution | Validate attribute value FQNs before encryption and create absent values. If an attribute definition allows traversal, encryption can proceed with definition-level scope while decryption remains blocked until the specific value exists. See [Discovery docs](/sdks/discovery) and [Resource Not Found](/sdks/troubleshooting#resource-not-found). | + +For concrete SDK-specific error text and commands, use [/sdks/troubleshooting](/sdks/troubleshooting). + +For the Go SDK specifically, `LoadTDF` parses and prepares the reader. KAS rewrap and policy authorization happen when payload key unwrap is triggered by `Init()`, `Read()`, or `WriteTo()`. + +## Best Practices + +1. Validate attribute FQNs before every encryption boundary where user input can influence policy. +2. Keep subject mapping creation idempotent in automation. +3. Store encrypted artifacts separately from entitlement management logic. +4. Log policy FQNs and key access identifiers (not plaintext) for observability. +5. Deactivate attributes instead of deleting them when historical TDF decryptability matters. +6. Add integration tests that perform both encrypt and decrypt with expected allow/deny identities. + +## Related Documentation + +- SDK quickstarts: [/sdks/quickstart](/sdks/quickstart) +- Discovery docs: [/sdks/discovery](/sdks/discovery) +- Authorization docs: [/sdks/authorization](/sdks/authorization) +- TDF schema spec: [/spec/schema/opentdf](/spec/schema/opentdf)