65 lines
1.6 KiB
Go
65 lines
1.6 KiB
Go
package queue
|
|
|
|
import (
|
|
"crypto/sha3"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"io"
|
|
|
|
"github.com/go-json-experiment/json/jsontext"
|
|
)
|
|
|
|
// sender is an obfuscated sender ID.
|
|
//
|
|
// It acts approximately as a quotient type: since it is unexported, the only
|
|
// way to obtain values of type sender without unusual effort is to use the
|
|
// constructors provided by this package.
|
|
// This helps to prevent misuse that exposes actual user IDs.
|
|
type sender [28]byte
|
|
|
|
// Sender constructs an obfuscated sender ID.
|
|
// The salt must be shared by all ingesters.
|
|
// While the salt may be of any length, a length between 16 and 64 bytes is suggested.
|
|
func Sender(salt []byte, channel, user string) sender {
|
|
b := make([]byte, 128)
|
|
b = append(b, channel...)
|
|
b = append(b, 0)
|
|
b = append(b, salt...)
|
|
b = append(b, 0)
|
|
b = append(b, user...)
|
|
return sender(sha3.Sum224(b))
|
|
}
|
|
|
|
func (s sender) String() string {
|
|
b := base64.RawStdEncoding.AppendEncode(make([]byte, 0, 38), s[:])
|
|
return string(b)
|
|
}
|
|
|
|
func (s sender) MarshalJSONTo(e *jsontext.Encoder) error {
|
|
return e.WriteToken(jsontext.String(s.String()))
|
|
}
|
|
|
|
func (s *sender) UnmarshalJSONFrom(d *jsontext.Decoder) error {
|
|
t, err := d.ReadToken()
|
|
switch err {
|
|
case nil: // do nothing
|
|
case io.EOF:
|
|
return io.ErrUnexpectedEOF
|
|
default:
|
|
return err
|
|
}
|
|
e := t.String()
|
|
if t.Kind() != '"' {
|
|
return fmt.Errorf("invalid token for sender %q", e)
|
|
}
|
|
if len(e) != 38 {
|
|
return fmt.Errorf("invalid string for sender %q", e)
|
|
}
|
|
b, err := base64.RawStdEncoding.AppendDecode(make([]byte, 0, 28), []byte(e))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*s = sender(b)
|
|
return nil
|
|
}
|