libs5-go/protocol/registry.go

164 lines
3.7 KiB
Go
Raw Permalink Normal View History

2024-01-10 11:21:03 +00:00
package protocol
import (
ed25519p "crypto/ed25519"
"errors"
"git.lumeweb.com/LumeWeb/libs5-go/ed25519"
"git.lumeweb.com/LumeWeb/libs5-go/types"
"git.lumeweb.com/LumeWeb/libs5-go/utils"
)
var (
_ SignedRegistryEntry = (*SignedRegistryEntryImpl)(nil)
_ SignedRegistryEntry = (*SignedRegistryEntryImpl)(nil)
2024-01-10 11:21:03 +00:00
)
type SignedRegistryEntry interface {
PK() []byte
Revision() uint64
Data() []byte
Signature() []byte
SetPK(pk []byte)
SetRevision(revision uint64)
SetData(data []byte)
SetSignature(signature []byte)
Verify() bool
}
type RegistryEntry interface {
Sign() SignedRegistryEntry
}
2024-01-10 11:21:03 +00:00
type SignedRegistryEntryImpl struct {
pk []byte
revision uint64
data []byte
signature []byte
}
func (s *SignedRegistryEntryImpl) Verify() bool {
return VerifyRegistryEntry(s)
}
func (s *SignedRegistryEntryImpl) PK() []byte {
return s.pk
}
func (s *SignedRegistryEntryImpl) SetPK(pk []byte) {
s.pk = pk
}
func (s *SignedRegistryEntryImpl) Revision() uint64 {
return s.revision
}
func (s *SignedRegistryEntryImpl) SetRevision(revision uint64) {
s.revision = revision
}
func (s *SignedRegistryEntryImpl) Data() []byte {
return s.data
}
func (s *SignedRegistryEntryImpl) SetData(data []byte) {
s.data = data
}
func (s *SignedRegistryEntryImpl) Signature() []byte {
return s.signature
}
func (s *SignedRegistryEntryImpl) SetSignature(signature []byte) {
s.signature = signature
}
func NewSignedRegistryEntry(pk []byte, revision uint64, data []byte, signature []byte) SignedRegistryEntry {
2024-01-10 11:21:03 +00:00
return &SignedRegistryEntryImpl{
pk: pk,
revision: revision,
data: data,
signature: signature,
}
}
type RegistryEntryImpl struct {
kp ed25519.KeyPairEd25519
data []byte
revision uint64
}
func NewRegistryEntry(kp ed25519.KeyPairEd25519, data []byte, revision uint64) RegistryEntry {
2024-01-10 11:21:03 +00:00
return &RegistryEntryImpl{
kp: kp,
data: data,
revision: revision,
}
}
func (r *RegistryEntryImpl) Sign() SignedRegistryEntry {
2024-01-10 11:21:03 +00:00
return SignRegistryEntry(r.kp, r.data, r.revision)
}
func SignRegistryEntry(kp ed25519.KeyPairEd25519, data []byte, revision uint64) SignedRegistryEntry {
buffer := MarshalRegistryEntry(nil, data, revision)
2024-01-10 11:21:03 +00:00
privateKey := kp.ExtractBytes()
signature := ed25519p.Sign(privateKey, buffer)
return NewSignedRegistryEntry(kp.PublicKey(), uint64(revision), data, signature)
}
func VerifyRegistryEntry(sre SignedRegistryEntry) bool {
buffer := MarshalRegistryEntry(nil, sre.Data(), sre.Revision())
2024-01-10 11:21:03 +00:00
publicKey := sre.PK()[1:]
return ed25519p.Verify(publicKey, buffer, sre.Signature())
}
func MarshalSignedRegistryEntry(sre SignedRegistryEntry) []byte {
buffer := MarshalRegistryEntry(sre.PK(), sre.Data(), sre.Revision())
2024-01-10 11:21:03 +00:00
buffer = append(buffer, sre.Signature()...)
return buffer
}
func MarshalRegistryEntry(pk []byte, data []byte, revision uint64) []byte {
2024-01-10 11:21:03 +00:00
var buffer []byte
buffer = append(buffer, byte(types.RecordTypeRegistryEntry))
if pk != nil {
buffer = append(buffer, pk...)
}
2024-01-10 11:21:03 +00:00
revBytes := utils.EncodeEndian(revision, 8)
2024-01-10 11:21:03 +00:00
buffer = append(buffer, revBytes...)
buffer = append(buffer, byte(len(data)))
buffer = append(buffer, data...)
return buffer
}
func UnmarshalSignedRegistryEntry(event []byte) (sre SignedRegistryEntry, err error) {
2024-01-10 11:21:03 +00:00
if len(event) < 43 {
return nil, errors.New("Invalid registry entry")
}
dataLength := int(event[42])
if len(event) < 43+dataLength {
return nil, errors.New("Invalid registry entry")
}
pk := event[1:34]
revisionBytes := event[34:42]
revision := utils.DecodeEndian(revisionBytes)
signatureStart := 43 + dataLength
var signature []byte
if signatureStart < len(event) {
signature = event[signatureStart:]
} else {
return nil, errors.New("Invalid signature")
}
return NewSignedRegistryEntry(pk, uint64(revision), event[43:signatureStart], signature), nil
}