mirror of
https://github.com/lightninglabs/pool.git
synced 2026-08-13 12:33:04 +02:00
To allow a ticket to be transported easily over any communication channel we also provide an easy ascii compatible exchange format which includes a prefix and a checksum in addition to the tlv stream data. The string encoding chosen is URL safe base64.
96 lines
2.9 KiB
Go
96 lines
2.9 KiB
Go
package sidecar
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/sha256"
|
|
"encoding/base64"
|
|
"fmt"
|
|
)
|
|
|
|
const (
|
|
// checksumLen is the number of bytes we add as a checksum. We'll take
|
|
// this many bytes out of the full SHA256 hash and add it to the string
|
|
// encoded version of the ticket as an additional integrity check.
|
|
checksumLen = 4
|
|
)
|
|
|
|
var (
|
|
// defaultStringEncoding is the default encoding algorithm we use to
|
|
// encode the gzipped binary data as a string.
|
|
defaultStringEncoding = base64.URLEncoding
|
|
|
|
// sidecarPrefix is a specially prepared prefix that will spell out
|
|
// "sidecar" when encoded as base64. It will cause all our sidecar
|
|
// tickets to be easily recognizable with a human readable part.
|
|
sidecarPrefix = []byte{0xb2, 0x27, 0x5e, 0x71, 0xaa, 0xc0}
|
|
)
|
|
|
|
// EncodeToString serializes and encodes the ticket as an URL safe string that
|
|
// contains a human readable prefix and a checksum.
|
|
func EncodeToString(t *Ticket) (string, error) {
|
|
var buf bytes.Buffer
|
|
|
|
// Add a prefix to make the ticket easily recognizable by human eyes.
|
|
if _, err := buf.Write(sidecarPrefix); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Serialize the raw ticket itself.
|
|
if err := SerializeTicket(&buf, t); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Create a checksum (SHA256) of all the bytes so far (prefix + raw
|
|
// ticket) and add 4 bytes of that to the string encoded version. This
|
|
// will prevent the ticket from appearing valid even if parts of it were
|
|
// not copy/pasted correctly.
|
|
hash := sha256.New()
|
|
_, _ = hash.Write(buf.Bytes())
|
|
checksum := hash.Sum(nil)[0:4]
|
|
if _, err := buf.Write(checksum); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return defaultStringEncoding.EncodeToString(buf.Bytes()), nil
|
|
}
|
|
|
|
// DecodeString decodes and then deserializes the given sidecar ticket string.
|
|
func DecodeString(s string) (*Ticket, error) {
|
|
rawBytes, err := defaultStringEncoding.DecodeString(s)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(rawBytes) < len(sidecarPrefix)+checksumLen {
|
|
return nil, fmt.Errorf("not a sidecar ticket, invalid length")
|
|
}
|
|
|
|
totalLength := len(rawBytes)
|
|
prefixLength := len(sidecarPrefix)
|
|
payloadLength := totalLength - prefixLength - checksumLen
|
|
|
|
prefix := rawBytes[0:prefixLength]
|
|
payload := rawBytes[prefixLength : prefixLength+payloadLength]
|
|
checksum := rawBytes[totalLength-checksumLen : totalLength]
|
|
|
|
// Make sure the prefix matches our static prefix.
|
|
if !bytes.Equal(prefix, sidecarPrefix) {
|
|
return nil, fmt.Errorf("not a sicecar ticket, invalid prefix "+
|
|
"%x", prefix)
|
|
}
|
|
|
|
// Calculate the SHA256 sum of the prefix and payload and compare it to
|
|
// the checksum we also expect to be in the full string serialized
|
|
// ticket.
|
|
hash := sha256.New()
|
|
_, _ = hash.Write(prefix)
|
|
_, _ = hash.Write(payload)
|
|
calculatedChecksum := hash.Sum(nil)[0:4]
|
|
if !bytes.Equal(checksum, calculatedChecksum) {
|
|
return nil, fmt.Errorf("invalid sidecar ticket, checksum " +
|
|
"mismatch")
|
|
}
|
|
|
|
// Everything's fine, let's decode the actual payload.
|
|
return DeserializeTicket(bytes.NewReader(payload))
|
|
}
|