|
|
@ -6,6 +6,7 @@ import ( |
|
|
|
"crypto/rand" |
|
|
|
"crypto/rand" |
|
|
|
"encoding/base64" |
|
|
|
"encoding/base64" |
|
|
|
"encoding/hex" |
|
|
|
"encoding/hex" |
|
|
|
|
|
|
|
"encoding/json" |
|
|
|
"errors" |
|
|
|
"errors" |
|
|
|
"github.com/ugorji/go/codec" |
|
|
|
"github.com/ugorji/go/codec" |
|
|
|
"hash/crc64" |
|
|
|
"hash/crc64" |
|
|
@ -16,7 +17,7 @@ const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 |
|
|
|
|
|
|
|
|
|
|
|
var b64 = base64.NewEncoding(alphabet).WithPadding(base64.NoPadding) |
|
|
|
var b64 = base64.NewEncoding(alphabet).WithPadding(base64.NoPadding) |
|
|
|
|
|
|
|
|
|
|
|
type linkData struct { |
|
|
|
type tokenData struct { |
|
|
|
Signature []byte `codec:"s"` |
|
|
|
Signature []byte `codec:"s"` |
|
|
|
Payload []byte `codec:"p"` |
|
|
|
Payload []byte `codec:"p"` |
|
|
|
} |
|
|
|
} |
|
|
@ -50,6 +51,42 @@ func (tc TokenCoder) SeedHex() string { |
|
|
|
return hex.EncodeToString(tc.Seed()) |
|
|
|
return hex.EncodeToString(tc.Seed()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func Format(token string) (txt string, err error) { |
|
|
|
|
|
|
|
var payload any |
|
|
|
|
|
|
|
var data []byte |
|
|
|
|
|
|
|
data, err = b64.DecodeString(strings.TrimFunc(token, trim)) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
buf := bytes.NewBuffer(nil) |
|
|
|
|
|
|
|
var handle codec.CborHandle |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
buf.Write(data) |
|
|
|
|
|
|
|
dec := codec.NewDecoder(buf, &handle) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var td tokenData |
|
|
|
|
|
|
|
err = dec.Decode(&td) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
buf.Reset() |
|
|
|
|
|
|
|
buf.Write(td.Payload) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
err = dec.Decode(&payload) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
buf.Reset() |
|
|
|
|
|
|
|
buf.Write([]byte("SIGNATURE=" + hex.EncodeToString(td.Signature) + "\n")) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enc := json.NewEncoder(buf) |
|
|
|
|
|
|
|
enc.SetEscapeHTML(false) |
|
|
|
|
|
|
|
enc.SetIndent("", "\t") |
|
|
|
|
|
|
|
err = enc.Encode(payload) |
|
|
|
|
|
|
|
txt = buf.String() |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func NewTokenCoderWithSeed(seed []byte, pubKeys ...[]byte) (tc TokenCoder, err error) { |
|
|
|
func NewTokenCoderWithSeed(seed []byte, pubKeys ...[]byte) (tc TokenCoder, err error) { |
|
|
|
if len(seed) != ed25519.SeedSize { |
|
|
|
if len(seed) != ed25519.SeedSize { |
|
|
|
err = errors.New("Incorrect seed size") |
|
|
|
err = errors.New("Incorrect seed size") |
|
|
@ -123,11 +160,11 @@ func (tc TokenCoder) Encode(payload interface{}) (token string, err error) { |
|
|
|
enc := codec.NewEncoder(buf, &handle) |
|
|
|
enc := codec.NewEncoder(buf, &handle) |
|
|
|
enc.Encode(payload) |
|
|
|
enc.Encode(payload) |
|
|
|
|
|
|
|
|
|
|
|
var ld linkData |
|
|
|
var td tokenData |
|
|
|
ld.Signature = ed25519.Sign(tc.privKey, buf.Bytes()) |
|
|
|
td.Signature = ed25519.Sign(tc.privKey, buf.Bytes()) |
|
|
|
ld.Payload = buf.Bytes() |
|
|
|
td.Payload = buf.Bytes() |
|
|
|
buf.Reset() |
|
|
|
buf.Reset() |
|
|
|
enc.Encode(ld) |
|
|
|
enc.Encode(td) |
|
|
|
token = b64.EncodeToString(buf.Bytes()) |
|
|
|
token = b64.EncodeToString(buf.Bytes()) |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
@ -150,15 +187,15 @@ func (tc TokenCoder) Decode(token string, payload interface{}) (sum string, err |
|
|
|
buf.Write(data) |
|
|
|
buf.Write(data) |
|
|
|
dec := codec.NewDecoder(buf, &handle) |
|
|
|
dec := codec.NewDecoder(buf, &handle) |
|
|
|
|
|
|
|
|
|
|
|
var ld linkData |
|
|
|
var td tokenData |
|
|
|
err = dec.Decode(&ld) |
|
|
|
err = dec.Decode(&td) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ok := false |
|
|
|
ok := false |
|
|
|
for _, key := range tc.pubKeys { |
|
|
|
for _, key := range tc.pubKeys { |
|
|
|
if ed25519.Verify(key, ld.Payload, ld.Signature) { |
|
|
|
if ed25519.Verify(key, td.Payload, td.Signature) { |
|
|
|
ok = true |
|
|
|
ok = true |
|
|
|
break |
|
|
|
break |
|
|
|
} |
|
|
|
} |
|
|
@ -170,10 +207,10 @@ func (tc TokenCoder) Decode(token string, payload interface{}) (sum string, err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
buf.Reset() |
|
|
|
buf.Reset() |
|
|
|
buf.Write(ld.Payload) |
|
|
|
buf.Write(td.Payload) |
|
|
|
|
|
|
|
|
|
|
|
hash := crc64.New(crc64.MakeTable(crc64.ISO)) |
|
|
|
hash := crc64.New(crc64.MakeTable(crc64.ISO)) |
|
|
|
hash.Write(ld.Payload) |
|
|
|
hash.Write(td.Payload) |
|
|
|
|
|
|
|
|
|
|
|
sum = hex.EncodeToString(hash.Sum(nil)) |
|
|
|
sum = hex.EncodeToString(hash.Sum(nil)) |
|
|
|
err = dec.Decode(&payload) |
|
|
|
err = dec.Decode(&payload) |
|
|
|