Skip to content

Commit 9f740aa

Browse files
committed
refactor: rename body material to descriptor
Use descriptor terminology for the cached, non-secret envelope\nmetadata returned by Encrypt and consumed by range decryption.\nThis matches the review feedback and avoids implying that the\nvalue carries key material.\n\nAssisted-by: GPT-5.4:gpt-5.4
1 parent 5cbd1e2 commit 9f740aa

6 files changed

Lines changed: 161 additions & 160 deletions

File tree

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ import (
4646

4747
| Package | Purpose |
4848
|---|---|
49-
| [`fee`](.) (root) | Composes the primitives below into a small API: whole-object `Encrypt`/`Decrypt`, byte-range `DecryptRange`, and the cacheable envelope parameters (`BodyMaterial`) that let a range read skip the header. Adds no cryptography of its own. |
49+
| [`fee`](.) (root) | Composes the primitives below into a small API: whole-object `Encrypt`/`Decrypt`, byte-range `DecryptRange`, and the cacheable envelope parameters (`BodyDescriptor`) that let a range read skip the header. Adds no cryptography of its own. |
5050
| [`aesstream`](./aesstream) | The chunked AES-256-GCM STREAM body cipher: streaming `Writer`/`Reader` plus the range primitives (`CiphertextRange`, `SpanReader`, `OpenSpan`) that `fee.DecryptRange` is built on. |
5151
| [`cose`](./cose) | Just enough of COSE (RFC 9052): `COSE_Encrypt` (tag 96) / `COSE_Encrypt0` (tag 16) with a detached payload, and the `Enc_structure` AAD. |
5252
| [`ecdhkw`](./ecdhkw) | ECDH-ES+A256KW key wrap over X25519 (COSE algorithm −31). |
@@ -327,13 +327,13 @@ They are complete before any plaintext is read, so a writer can store them while
327327
the upload is still streaming:
328328

329329
```go
330-
// m goes alongside the blob's location and size.
331-
r, m, err := fee.Encrypt(plaintext, recipients)
330+
// d goes alongside the blob's location and size.
331+
r, d, err := fee.Encrypt(plaintext, recipients)
332332
```
333333

334-
`fee.DecryptRangeWithMaterial(blob, blobSize, m, cek, off, length)` then serves a
334+
`fee.DecryptRangeWithDescriptor(blob, blobSize, d, cek, off, length)` then serves a
335335
range with no envelope round trip at all: the only bytes fetched are the
336-
ciphertext chunks the range overlaps. `m.PlaintextSize(blobSize)` answers a `HEAD`
336+
ciphertext chunks the range overlaps. `d.PlaintextSize(blobSize)` answers a `HEAD`
337337
or resolves a suffix range from the stored record alone, reading nothing.
338338

339339
Every field is non-secret — all four are already in the clear at the front of the

material.go renamed to descriptor.go

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ import (
88
"github.com/filecoin-project/go-fee/aesstream"
99
)
1010

11-
// ErrIncompleteMaterial means a [BodyMaterial] is missing a field, or carries one
12-
// that cannot describe a FEE body — a value that could not decrypt anything.
13-
var ErrIncompleteMaterial = errors.New("fee: incomplete body material")
11+
// ErrIncompleteDescriptor means a [BodyDescriptor] is missing a field, or carries
12+
// one that cannot describe a FEE body — a value that could not decrypt anything.
13+
var ErrIncompleteDescriptor = errors.New("fee: incomplete body descriptor")
1414

15-
// BodyMaterial is everything a range decrypt needs from a FEE envelope, so a
15+
// BodyDescriptor is everything a range decrypt needs from a FEE envelope, so a
1616
// caller that cached it can serve a byte range without fetching or decoding the
1717
// envelope header at all. It is returned by [Encrypt] / [EncryptWithCEK] at
18-
// encryption time and consumed by [DecryptRangeWithMaterial].
18+
// encryption time and consumed by [DecryptRangeWithDescriptor].
1919
//
2020
// It exists for stores that keep their own metadata alongside the blob: the
2121
// envelope is a fixed prefix of every stored object, so re-reading it on each
@@ -35,8 +35,8 @@ var ErrIncompleteMaterial = errors.New("fee: incomplete body material")
3535
// plausible-looking plaintext. The worst case is an unreadable object, not an
3636
// incorrect one.
3737
//
38-
// The zero value is not usable; see [BodyMaterial.Validate].
39-
type BodyMaterial struct {
38+
// The zero value is not usable; see [BodyDescriptor.Validate].
39+
type BodyDescriptor struct {
4040
// HeaderLen is the encoded length of the envelope, and so the offset within
4141
// the blob at which the detached ciphertext begins.
4242
HeaderLen int64
@@ -53,7 +53,7 @@ type BodyMaterial struct {
5353
// protected header because the Enc_structure's context string differs
5454
// between a COSE_Encrypt and a recipient-less COSE_Encrypt0, a distinction
5555
// this value has no other way to record. Caching the finished bytes keeps
56-
// BodyMaterial identical for both envelope forms. The protected header
56+
// BodyDescriptor identical for both envelope forms. The protected header
5757
// remains recoverable from it: it is the structure's second element.
5858
AAD []byte
5959
}
@@ -63,22 +63,22 @@ type BodyMaterial struct {
6363
// material — a partially populated record would produce a row that no later
6464
// range read could use.
6565
//
66-
// [DecryptRangeWithMaterial] calls it, so a bad value fails there with
67-
// [ErrIncompleteMaterial] rather than as an authentication error further down.
68-
func (m BodyMaterial) Validate() error {
66+
// [DecryptRangeWithDescriptor] calls it, so a bad value fails there with
67+
// [ErrIncompleteDescriptor] rather than as an authentication error further down.
68+
func (m BodyDescriptor) Validate() error {
6969
if m.HeaderLen <= 0 {
70-
return fmt.Errorf("%w: header length %d is not positive", ErrIncompleteMaterial, m.HeaderLen)
70+
return fmt.Errorf("%w: header length %d is not positive", ErrIncompleteDescriptor, m.HeaderLen)
7171
}
7272
if len(m.BaseNonce) != aesstream.BaseNonceSize {
7373
return fmt.Errorf("%w: base nonce is %d bytes, want %d",
74-
ErrIncompleteMaterial, len(m.BaseNonce), aesstream.BaseNonceSize)
74+
ErrIncompleteDescriptor, len(m.BaseNonce), aesstream.BaseNonceSize)
7575
}
7676
if m.ChunkSize < aesstream.MinChunkSize || m.ChunkSize > aesstream.MaxChunkSize {
7777
return fmt.Errorf("%w: chunk size %d out of range [%d, %d]",
78-
ErrIncompleteMaterial, m.ChunkSize, aesstream.MinChunkSize, aesstream.MaxChunkSize)
78+
ErrIncompleteDescriptor, m.ChunkSize, aesstream.MinChunkSize, aesstream.MaxChunkSize)
7979
}
8080
if len(m.AAD) == 0 {
81-
return fmt.Errorf("%w: missing AAD", ErrIncompleteMaterial)
81+
return fmt.Errorf("%w: missing AAD", ErrIncompleteDescriptor)
8282
}
8383
return nil
8484
}
@@ -89,10 +89,10 @@ func (m BodyMaterial) Validate() error {
8989
// suffix range ("bytes=-N" is off = size-N) from cached metadata alone.
9090
//
9191
// blobSize is the whole stored object, envelope included, exactly as passed to
92-
// [DecryptRangeWithMaterial]. It reports [ErrIncompleteMaterial] for an unusable
92+
// [DecryptRangeWithDescriptor]. It reports [ErrIncompleteDescriptor] for an unusable
9393
// m, and [aesstream.ErrCiphertextSize] if blobSize cannot describe a FEE blob at
9494
// this header length and chunk size.
95-
func (m BodyMaterial) PlaintextSize(blobSize int64) (int64, error) {
95+
func (m BodyDescriptor) PlaintextSize(blobSize int64) (int64, error) {
9696
if err := m.Validate(); err != nil {
9797
return 0, err
9898
}
@@ -103,7 +103,7 @@ func (m BodyMaterial) PlaintextSize(blobSize int64) (int64, error) {
103103
// whose envelope occupies headerLen bytes and whose STREAM chunks carry chunkSize
104104
// plaintext bytes each.
105105
//
106-
// It is shared by [BodyMaterial.PlaintextSize] and the envelope-backed paths (via
106+
// It is shared by [BodyDescriptor.PlaintextSize] and the envelope-backed paths (via
107107
// envelopePlaintextSize), so a blob size that cannot describe a FEE body is reported
108108
// the same way whether the parameters came from a cache or from the envelope.
109109
func plaintextSizeFrom(blobSize, headerLen int64, chunkSize int) (int64, error) {
@@ -122,14 +122,14 @@ func plaintextSizeFrom(blobSize, headerLen int64, chunkSize int) (int64, error)
122122
// body returns the envelope body parameters m describes, for the range wiring it
123123
// shares with the envelope-backed paths. HeaderLen is not among them: it says
124124
// where the ciphertext starts, not how to decrypt it.
125-
func (m BodyMaterial) body() bodyParams {
125+
func (m BodyDescriptor) body() bodyParams {
126126
return bodyParams{baseNonce: m.BaseNonce, chunkSize: m.ChunkSize, aad: m.AAD}
127127
}
128128

129-
// clone returns a deep copy, so a BodyMaterial handed to a caller shares no
129+
// clone returns a deep copy, so a BodyDescriptor handed to a caller shares no
130130
// backing array with the envelope it came from (and one handed back to us cannot
131131
// be mutated underneath a live reader).
132-
func (m BodyMaterial) clone() BodyMaterial {
132+
func (m BodyDescriptor) clone() BodyDescriptor {
133133
m.BaseNonce = bytes.Clone(m.BaseNonce)
134134
m.AAD = bytes.Clone(m.AAD)
135135
return m

0 commit comments

Comments
 (0)