github.com/readium/readium-lcp-server@v0.0.0-20240101192032-6e95190e99f1/sign/canon.go (about)

     1  // Copyright 2017 European Digital Reading Lab. All rights reserved.
     2  // Licensed to the Readium Foundation under one or more contributor license agreements.
     3  // Use of this source code is governed by a BSD-style license
     4  // that can be found in the LICENSE file exposed on Github (readium) in the project repository.
     5  
     6  package sign
     7  
     8  import (
     9  	"bytes"
    10  	"encoding/json"
    11  	"io"
    12  	"strings"
    13  )
    14  
    15  func Canon(in interface{}) ([]byte, error) {
    16  	// the easiest way to canonicalize is to marshal it and reify it as a map
    17  	// which will sort stuff correctly
    18  	b, err1 := json.Marshal(in)
    19  	if err1 != nil {
    20  		return b, err1
    21  	}
    22  
    23  	var jsonObj interface{} // map[string]interface{} ==> auto sorting
    24  
    25  	dec := json.NewDecoder(strings.NewReader(string(b)))
    26  	dec.UseNumber()
    27  	for {
    28  		if err2 := dec.Decode(&jsonObj); err2 == io.EOF {
    29  			break
    30  		} else if err2 != nil {
    31  			return nil, err2
    32  		}
    33  	}
    34  	var buf bytes.Buffer
    35  	enc := json.NewEncoder(&buf)
    36  	// do not escape characters
    37  	enc.SetEscapeHTML(false)
    38  	err := enc.Encode(jsonObj)
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  	// remove the trailing newline, added by encode
    43  	return bytes.TrimRight(buf.Bytes(), "\n"), nil
    44  
    45  }