types, pubkey and signature codec
This commit is contained in:
13
pkg/codec/codec.go
Normal file
13
pkg/codec/codec.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package codec
|
||||
|
||||
// C is an interface for encoding and decoding that allows embedding encoders
|
||||
// inside other encoders by the use of append for Marshal and slice for
|
||||
// Unmarshal.
|
||||
type C interface {
|
||||
// Marshal data by appending it to the provided destination, and return the
|
||||
// resultant slice.
|
||||
Marshal(dst []byte) (result []byte, err error)
|
||||
// Unmarshal the next expected data element from the provided slice and return
|
||||
// the remainder after the expected separator.
|
||||
Unmarshal(data []byte) (rem []byte, err error)
|
||||
}
|
||||
14
pkg/event/event.go
Normal file
14
pkg/event/event.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package event
|
||||
|
||||
import (
|
||||
"protocol.realy.lol/pkg/event/types"
|
||||
)
|
||||
|
||||
type Event struct {
|
||||
Type types.T
|
||||
Pubkey []byte
|
||||
Timestamp int64
|
||||
Tags [][]byte
|
||||
Content []byte
|
||||
Signature []byte
|
||||
}
|
||||
9
pkg/event/log.go
Normal file
9
pkg/event/log.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package event
|
||||
|
||||
import (
|
||||
"protocol.realy.lol/pkg/lol"
|
||||
)
|
||||
|
||||
var (
|
||||
log, chk, errorf = lol.Main.Log, lol.Main.Check, lol.Main.Errorf
|
||||
)
|
||||
9
pkg/event/types/log.go
Normal file
9
pkg/event/types/log.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"protocol.realy.lol/pkg/lol"
|
||||
)
|
||||
|
||||
var (
|
||||
log, chk, errorf = lol.Main.Log, lol.Main.Check, lol.Main.Errorf
|
||||
)
|
||||
44
pkg/event/types/types.go
Normal file
44
pkg/event/types/types.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// A T is a type descriptor, that is terminated by a newline.
|
||||
type T []byte
|
||||
|
||||
// Marshal append the T to a slice and appends a terminal newline, and returns
|
||||
// the result.
|
||||
func (t *T) Marshal(dst []byte) (result []byte, err error) {
|
||||
if t == nil {
|
||||
return
|
||||
}
|
||||
result = append(append(dst, []byte(*t)...), '\n')
|
||||
return
|
||||
}
|
||||
|
||||
// Unmarshal expects an identifier followed by a newline. If the buffer ends
|
||||
// without a newline an EOF is returned.
|
||||
func (t *T) Unmarshal(data []byte) (rem []byte, err error) {
|
||||
rem = data
|
||||
if t == nil {
|
||||
err = errorf.E("can't unmarshal into nil types.T")
|
||||
return
|
||||
}
|
||||
if len(rem) < 2 {
|
||||
err = errorf.E("can't unmarshal nothing")
|
||||
return
|
||||
}
|
||||
for i := range rem {
|
||||
if rem[i] == '\n' {
|
||||
// write read data up to the newline and return the remainder after
|
||||
// the newline.
|
||||
*t = rem[:i]
|
||||
rem = rem[i+1:]
|
||||
return
|
||||
}
|
||||
}
|
||||
// a T must end with a newline or an io.EOF is returned.
|
||||
err = io.EOF
|
||||
return
|
||||
}
|
||||
28
pkg/event/types/types_test.go
Normal file
28
pkg/event/types/types_test.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestT_Marshal_Unmarshal(t *testing.T) {
|
||||
typ := T("note")
|
||||
var err error
|
||||
var res []byte
|
||||
if res, err = typ.Marshal(nil); chk.E(err) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
log.I.S(res)
|
||||
t2 := new(T)
|
||||
var rem []byte
|
||||
if rem, err = t2.Unmarshal(res); chk.E(err) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(rem) > 0 {
|
||||
log.I.S(rem)
|
||||
}
|
||||
log.I.S(t2)
|
||||
if !bytes.Equal(typ, *t2) {
|
||||
t.Fatal("types.T did not encode/decode faithfully")
|
||||
}
|
||||
}
|
||||
9
pkg/pubkey/log.go
Normal file
9
pkg/pubkey/log.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package pubkey
|
||||
|
||||
import (
|
||||
"protocol.realy.lol/pkg/lol"
|
||||
)
|
||||
|
||||
var (
|
||||
log, chk, errorf = lol.Main.Log, lol.Main.Check, lol.Main.Errorf
|
||||
)
|
||||
74
pkg/pubkey/pubkey.go
Normal file
74
pkg/pubkey/pubkey.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package pubkey
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ed25519"
|
||||
"encoding/base64"
|
||||
"io"
|
||||
)
|
||||
|
||||
const Len = 44
|
||||
|
||||
type P struct{ ed25519.PublicKey }
|
||||
|
||||
func New(pk []byte) (p *P, err error) {
|
||||
if len(pk) != ed25519.PublicKeySize {
|
||||
err = errorf.E("invalid public key size: %d; require %d",
|
||||
len(pk), ed25519.PublicKeySize)
|
||||
return
|
||||
}
|
||||
p = &P{pk}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *P) Marshal(dst []byte) (result []byte, err error) {
|
||||
result = dst
|
||||
if p == nil || p.PublicKey == nil || len(p.PublicKey) == 0 {
|
||||
err = errorf.E("nil/zero length pubkey")
|
||||
return
|
||||
}
|
||||
if len(p.PublicKey) != ed25519.PublicKeySize {
|
||||
err = errorf.E("invalid public key length %d; require %d '%0x'",
|
||||
len(p.PublicKey), ed25519.PublicKeySize, p.PublicKey)
|
||||
return
|
||||
}
|
||||
buf := bytes.NewBuffer(result)
|
||||
w := base64.NewEncoder(base64.URLEncoding, buf)
|
||||
if _, err = w.Write(p.PublicKey); chk.E(err) {
|
||||
return
|
||||
}
|
||||
if err = w.Close(); chk.E(err) {
|
||||
return
|
||||
}
|
||||
result = append(buf.Bytes(), '\n')
|
||||
return
|
||||
}
|
||||
|
||||
func (p *P) Unmarshal(data []byte) (rem []byte, err error) {
|
||||
rem = data
|
||||
if p == nil {
|
||||
err = errorf.E("can't unmarshal into nil types.T")
|
||||
return
|
||||
}
|
||||
if len(rem) < 2 {
|
||||
err = errorf.E("can't unmarshal nothing")
|
||||
return
|
||||
}
|
||||
for i := range rem {
|
||||
if rem[i] == '\n' {
|
||||
if i != Len {
|
||||
err = errorf.E("invalid encoded pubkey length %d; require %d '%0x'",
|
||||
i, Len, rem[:i])
|
||||
return
|
||||
}
|
||||
p.PublicKey = make([]byte, ed25519.PublicKeySize)
|
||||
if _, err = base64.URLEncoding.Decode(p.PublicKey, rem[:i]); chk.E(err) {
|
||||
return
|
||||
}
|
||||
rem = rem[i+1:]
|
||||
return
|
||||
}
|
||||
}
|
||||
err = io.EOF
|
||||
return
|
||||
}
|
||||
38
pkg/pubkey/pubkey_test.go
Normal file
38
pkg/pubkey/pubkey_test.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package pubkey
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestP_Marshal_Unmarshal(t *testing.T) {
|
||||
pk := make([]byte, ed25519.PublicKeySize)
|
||||
var err error
|
||||
if _, err = rand.Read(pk); chk.E(err) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
log.I.S(pk)
|
||||
var p *P
|
||||
if p, err = New(pk); chk.E(err) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var o []byte
|
||||
if o, err = p.Marshal(nil); chk.E(err) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
log.I.F("%d %s", len(o), o)
|
||||
p2 := &P{}
|
||||
var rem []byte
|
||||
if rem, err = p2.Unmarshal(o); chk.E(err) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(rem) > 0 {
|
||||
log.I.F("%d %s", len(rem), rem)
|
||||
}
|
||||
log.I.S(p2.PublicKey)
|
||||
if !bytes.Equal(pk, p2.PublicKey) {
|
||||
t.Fatal("public key did not encode/decode faithfully")
|
||||
}
|
||||
}
|
||||
9
pkg/signature/log.go
Normal file
9
pkg/signature/log.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package signature
|
||||
|
||||
import (
|
||||
"protocol.realy.lol/pkg/lol"
|
||||
)
|
||||
|
||||
var (
|
||||
log, chk, errorf = lol.Main.Log, lol.Main.Check, lol.Main.Errorf
|
||||
)
|
||||
74
pkg/signature/signature.go
Normal file
74
pkg/signature/signature.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package signature
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ed25519"
|
||||
"encoding/base64"
|
||||
"io"
|
||||
)
|
||||
|
||||
const Len = 88
|
||||
|
||||
type S struct{ Signature []byte }
|
||||
|
||||
func New(sig []byte) (p *S, err error) {
|
||||
if len(sig) != ed25519.SignatureSize {
|
||||
err = errorf.E("invalid signature size: %d; require %d",
|
||||
len(sig), ed25519.SignatureSize)
|
||||
return
|
||||
}
|
||||
p = &S{sig}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *S) Marshal(dst []byte) (result []byte, err error) {
|
||||
result = dst
|
||||
if p == nil || p.Signature == nil || len(p.Signature) == 0 {
|
||||
err = errorf.E("nil/zero length signature")
|
||||
return
|
||||
}
|
||||
if len(p.Signature) != ed25519.SignatureSize {
|
||||
err = errorf.E("invalid signature length %d; require %d '%0x'",
|
||||
len(p.Signature), ed25519.SignatureSize, p.Signature)
|
||||
return
|
||||
}
|
||||
buf := bytes.NewBuffer(result)
|
||||
w := base64.NewEncoder(base64.URLEncoding, buf)
|
||||
if _, err = w.Write(p.Signature); chk.E(err) {
|
||||
return
|
||||
}
|
||||
if err = w.Close(); chk.E(err) {
|
||||
return
|
||||
}
|
||||
result = append(buf.Bytes(), '\n')
|
||||
return
|
||||
}
|
||||
|
||||
func (p *S) Unmarshal(data []byte) (rem []byte, err error) {
|
||||
rem = data
|
||||
if p == nil {
|
||||
err = errorf.E("can't unmarshal into nil types.T")
|
||||
return
|
||||
}
|
||||
if len(rem) < 2 {
|
||||
err = errorf.E("can't unmarshal nothing")
|
||||
return
|
||||
}
|
||||
for i := range rem {
|
||||
if rem[i] == '\n' {
|
||||
if i != Len {
|
||||
err = errorf.E("invalid encoded signature length %d; require %d '%0x'",
|
||||
i, Len, rem[:i])
|
||||
return
|
||||
}
|
||||
p.Signature = make([]byte, ed25519.SignatureSize)
|
||||
if _, err = base64.URLEncoding.Decode(p.Signature, rem[:i]); chk.E(err) {
|
||||
return
|
||||
}
|
||||
rem = rem[i+1:]
|
||||
return
|
||||
}
|
||||
}
|
||||
err = io.EOF
|
||||
return
|
||||
}
|
||||
38
pkg/signature/signature_test.go
Normal file
38
pkg/signature/signature_test.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package signature
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestS_Marshal_Unmarshal(t *testing.T) {
|
||||
sig := make([]byte, ed25519.SignatureSize)
|
||||
var err error
|
||||
if _, err = rand.Read(sig); chk.E(err) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
log.I.S(sig)
|
||||
var s *S
|
||||
if s, err = New(sig); chk.E(err) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var o []byte
|
||||
if o, err = s.Marshal(nil); chk.E(err) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
log.I.F("%d %s", len(o), o)
|
||||
p2 := &S{}
|
||||
var rem []byte
|
||||
if rem, err = p2.Unmarshal(o); chk.E(err) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(rem) > 0 {
|
||||
log.I.F("%d %s", len(rem), rem)
|
||||
}
|
||||
log.I.S(p2.Signature)
|
||||
if !bytes.Equal(sig, p2.Signature) {
|
||||
t.Fatal("signature did not encode/decode faithfully")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user