Skip to content

Commit fcc5a09

Browse files
committed
docs(ecdhkw): describe the migration from v0.1.0
Wrap and Unwrap now take the recipient's serialized protected header, and the KEK derivation changed, so v0.1.0 callers have both an API and a data migration ahead of them. Spell out the new call shape and say plainly that old wraps cannot be unwrapped: the two derivations differ and alg -31 covers both, so affected envelopes need decrypting with v0.1.0 and re-encrypting. Signed-off-by: Miroslav Bajtoš <oss@bajtos.net> Assisted-by: Claude:claude-opus-5
1 parent 24a3be0 commit fcc5a09

2 files changed

Lines changed: 29 additions & 1 deletion

File tree

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,11 @@ recipient = [ {1: alg}, {4: kid, ...}, wrappedKey ] # alg -31 or -5
351351
as the info parameter: `AlgorithmID` −5 (A256KW), empty PartyU/PartyV,
352352
`keyDataLength` 256, and the recipient's serialized protected header
353353
`h'a101381e'`. JOSE derives ECDH-ES differently (RFC 7518 §4.6 uses the NIST
354-
SP 800-56A single-step KDF); a KEK derived that way will not unwrap.
354+
SP 800-56A single-step KDF); a KEK derived that way will not unwrap. v0.1.0
355+
used the COSE Concat-KDF here, so envelopes it encrypted to X25519 recipients
356+
need decrypting with v0.1.0 and re-encrypting with this version; see the
357+
[`ecdhkw` package documentation](https://pkg.go.dev/github.com/filecoin-project/go-fee/ecdhkw)
358+
for the API change that comes with it.
355359

356360
## Security notes
357361

ecdhkw/ecdhkw.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,30 @@
2626
// CEK as the recipient ciphertext, keyed by a kid) is the job of the
2727
// higher-level fee package. Keys are passed as crypto/ecdh values directly; any
2828
// custody or key-provider abstraction lives above this layer.
29+
//
30+
// # Migrating from v0.1.0
31+
//
32+
// v0.1.0 derived the KEK with the COSE Concat-KDF and took no protected header:
33+
// Wrap(recipientPub, cek) and Unwrap(recipientPriv, w). Both signatures now take
34+
// the serialized COSE_Recipient protected header as a trailing argument, and the
35+
// derivation is HKDF-SHA-256 as RFC 9053 §6.3.1 requires.
36+
//
37+
// Callers that build the recipient with the cose package pass the bytes that
38+
// package produces:
39+
//
40+
// protected, err := cose.Headers{Protected: hdr}.ProtectedBytes()
41+
// w, err := ecdhkw.Wrap(recipientPub, cek, protected)
42+
//
43+
// A recipient with an empty protected bucket takes a nil or zero-length slice,
44+
// which reproduces v0.1.0's context except for the KDF itself. On the unwrap
45+
// side, pass the recipient's protected bytes exactly as they arrived on the
46+
// wire; cose.Headers.ProtectedBytes returns those for a decoded envelope.
47+
//
48+
// Wraps written by v0.1.0 do not survive the change. The two derivations produce
49+
// different KEKs from the same ECDH secret, so Unwrap on an old wrap fails with
50+
// aeskw.ErrIntegrity, and nothing on the wire distinguishes the two: both use
51+
// alg -31. Envelopes encrypted to X25519 recipients under v0.1.0 have to be
52+
// decrypted with v0.1.0 and re-encrypted with this version.
2953
package ecdhkw
3054

3155
import (

0 commit comments

Comments
 (0)