Documentation
¶
Overview ¶
Package jcs provides an implementation of the JSON Canonicalization Scheme (JCS) as defined in RFC 8785.
JCS defines a strict, deterministic serialization of JSON data so that logically equivalent values always produce the same byte sequence. This canonical form is essential for cryptographic applications such as digital signatures, hashing, and secure data exchange.
Features of this implementation:
- Canonical serialization of primitive types (null, booleans, strings, numbers) following RFC 8785 rules.
- Enforcement of IEEE‑754 double precision constraints: integers outside ±(2^53 − 1) cannot be represented exactly and return ErrNumberOOR.
- Canonical ordering of object keys using UTF‑16 code unit comparison, ensuring correct handling of non‑BMP characters (surrogate pairs).
- Support for slices of common Go types (ints, uints, floats, strings, bools, any) and maps with string keys.
- Rejection of unsupported or non‑representable types with ErrUnsupportedType.
The core entry point is Append, which appends the canonical JSON representation of a Go value to a destination byte slice. Helper functions such as appendSlice and appendObject handle composite types. Errors are returned when values cannot be represented according to RFC 8785.
This package is intended for use in contexts where canonical JSON is required for interoperability, compliance, or cryptographic integrity.
Example ¶
Example shows how to use Append in documentation.
var buf []byte
response := map[string]any{
"user_id": "c3f65f70-eb2f-4979-ba73-24bcbde9fdd9",
"age": 31,
}
// Append a string
buf, _ = Append(buf, response)
fmt.Println(string(buf))
Output: {"age":31,"user_id":"c3f65f70-eb2f-4979-ba73-24bcbde9fdd9"}
Index ¶
Examples ¶
Constants ¶
const MaxSafeNumber = 1<<53 - 1
MaxSafeNumber defines the largest integer that can be represented exactly in IEEE‑754 double precision (binary64), as required by RFC 8785 (JSON Canonicalization Scheme).
RFC 8785 3.2.2 mandates that all JSON numbers must be preserved exactly when serialized. Since canonical JSON relies on IEEE‑754 binary64, only integers in the range [‑(2^53‑1), +(2^53‑1)] are considered "safe". Any integer outside this range cannot be represented without precision loss and must cause canonicalization to fail.
MaxSafeNumber is therefore set to 2^53‑1 (9007199254740991).
Variables ¶
var ( // ErrUnsupportedType is returned when the encoder encounters a value // of an unsupported type. The encoder only supports specific types // like integers, strings, maps, and slices. Custom structs or other // complex types may trigger this error. ErrUnsupportedType = errors.New("jcs: value has unsupported type") // ErrNaN is returned when the encoder encounters a NaN (Not a Number) // value. RFC 8785 disallows NaN values in the canonical JSON format, // so this error is triggered when an attempt is made to encode a NaN. ErrNaN = errors.New("jcs: cannot c14n NaN") // ErrInf is returned when the encoder encounters an Inf (infinity) value. // RFC 8785 also disallows Inf values (both +Inf and -Inf) in the canonical // JSON format, which leads to this error when such values are encountered. ErrInf = errors.New("jcs: cannot c14n Inf") // ErrInvalidUTF8 is returned when the encoder encounters a string containing // invalid UTF-8 byte sequences. JCS requires that all strings be valid UTF-8, // so this error is triggered if a string contains non-UTF-8 characters. ErrInvalidUTF8 = errors.New("jcs: value has invalid utf8 character") // ErrNumberOOR is returned when a number exceeds the valid range for precise // representation in the IEEE-754 double precision format (±2^53). // Numbers larger than ±2^53 cannot be exactly represented, and JCS requires // exact round-trip encoding. This error occurs when such a number is encountered. ErrNumberOOR = errors.New("jcs: value number out of range (v ± 2^53)") )
Functions ¶
func Append ¶
Append function is part of the jcs package, which implements the JSON Canonicalization Scheme (JCS) as defined in RFC 8785. This function appends the canonicalized JSON representation of various Go types to a byte slice (dst). It returns the canonicalized representation of the provided value v in the appropriate format.
Supported types include:
- nil → serialized as "null"
- bool → serialized as "true" or "false"
- string → serialized with proper escaping
- float64 → serialized as a canonical JSON number
- float32, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64 → converted to float64 when within IEEE‑754 safe range (±(2^53 − 1)); otherwise ErrNumberOOR is returned
- slices of common types (ints, uints, floats, strings, bools, any)
- map[string]any → serialized as a JSON object with keys ordered by UTF‑16 code unit comparison, as required by RFC 8785
Errors:
- ErrNumberOOR is returned when an integer cannot be represented exactly in IEEE‑754 double precision.
- ErrUnsupportedType is returned when v is of a type not supported by this implementation.
This function is the core entry point for canonical JSON serialization in the package. It ensures deterministic output suitable for cryptographic operations such as hashing and signing. Example:
var buf []byte
response := map[string]any{
"user_id": "c3f65f70-eb2f-4979-ba73-24bcbde9fdd9",
"age": 31,
}
buf, _ = jcs.Append(buf, response)
fmt.Println(string(buf))
Output: {"age":31,"user_id":"c3f65f70-eb2f-4979-ba73-24bcbde9fdd9"}
Types ¶
This section is empty.