wirecodec.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. // Package wirecodec holds the shared envelope codec for node-to-node config
  2. // transport: zstd (de)compression, SHA-256 integrity hashing, and the header /
  3. // capability constants both the panel (sender) and node (receiver) agree on.
  4. package wirecodec
  5. import (
  6. "crypto/sha256"
  7. "encoding/hex"
  8. "errors"
  9. "github.com/klauspost/compress/zstd"
  10. )
  11. const (
  12. // HashHeader carries the lowercase-hex SHA-256 of the (uncompressed) body.
  13. HashHeader = "X-Config-Sha256"
  14. // CapsHeader is set by a node on its API responses to advertise support.
  15. CapsHeader = "X-3x-Node-Caps"
  16. // MasterPushHeader marks a request as a master's push, whatever its token scope.
  17. MasterPushHeader = "X-3x-Master-Push"
  18. // EncodingZstd is the Content-Encoding value for a zstd-compressed body.
  19. EncodingZstd = "zstd"
  20. // CapZstd is the capability token advertised in CapsHeader.
  21. CapZstd = "zstd"
  22. // maxDecodeBytes bounds in-memory decompression to defuse a zstd bomb from
  23. // an (authenticated) node-API caller.
  24. maxDecodeBytes = 16 << 20
  25. )
  26. // EncodeAll/DecodeAll on these shared instances are safe for concurrent use.
  27. var (
  28. zstdEncoder, _ = zstd.NewWriter(nil)
  29. zstdDecoder, _ = zstd.NewReader(nil, zstd.WithDecoderMaxMemory(maxDecodeBytes))
  30. )
  31. // Compress zstd-compresses b.
  32. func Compress(b []byte) []byte {
  33. return zstdEncoder.EncodeAll(b, nil)
  34. }
  35. // Decompress zstd-decompresses src, rejecting output larger than maxOut (and any
  36. // input that would blow the in-memory bomb ceiling).
  37. func Decompress(src []byte, maxOut int) ([]byte, error) {
  38. out, err := zstdDecoder.DecodeAll(src, nil)
  39. if err != nil {
  40. return nil, err
  41. }
  42. if maxOut > 0 && len(out) > maxOut {
  43. return nil, errors.New("wirecodec: decompressed body exceeds limit")
  44. }
  45. return out, nil
  46. }
  47. // Sha256Hex returns the lowercase-hex SHA-256 of b.
  48. func Sha256Hex(b []byte) string {
  49. sum := sha256.Sum256(b)
  50. return hex.EncodeToString(sum[:])
  51. }