mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2026-05-21 05:16:29 +03:00
New handshake, use softcrdt upstream
This commit is contained in:
@@ -4,65 +4,107 @@ package core
|
||||
// Used in the initial connection setup and key exchange
|
||||
// Some of this could arguably go in wire.go instead
|
||||
|
||||
import "crypto/ed25519"
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ed25519"
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
// This is the version-specific metadata exchanged at the start of a connection.
|
||||
// It must always begin with the 4 bytes "meta" and a wire formatted uint64 major version number.
|
||||
// The current version also includes a minor version number, and the box/sig/link keys that need to be exchanged to open a connection.
|
||||
type version_metadata struct {
|
||||
meta [4]byte
|
||||
ver uint8 // 1 byte in this version
|
||||
// Everything after this point potentially depends on the version number, and is subject to change in future versions
|
||||
minorVer uint8 // 1 byte in this version
|
||||
key ed25519.PublicKey
|
||||
majorVer uint16
|
||||
minorVer uint16
|
||||
publicKey ed25519.PublicKey
|
||||
priority uint8
|
||||
}
|
||||
|
||||
const (
|
||||
ProtocolVersionMajor uint16 = 0
|
||||
ProtocolVersionMinor uint16 = 5
|
||||
)
|
||||
|
||||
const (
|
||||
metaVersionMajor uint16 = iota // uint16
|
||||
metaVersionMinor // uint16
|
||||
metaPublicKey // [32]byte
|
||||
metaPriority // uint8
|
||||
)
|
||||
|
||||
// Gets a base metadata with no keys set, but with the correct version numbers.
|
||||
func version_getBaseMetadata() version_metadata {
|
||||
return version_metadata{
|
||||
meta: [4]byte{'m', 'e', 't', 'a'},
|
||||
ver: 0,
|
||||
minorVer: 4,
|
||||
majorVer: ProtocolVersionMajor,
|
||||
minorVer: ProtocolVersionMinor,
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the length of the metadata for this version, used to know how many bytes to read from the start of a connection.
|
||||
func version_getMetaLength() (mlen int) {
|
||||
mlen += 4 // meta
|
||||
mlen++ // ver, as long as it's < 127, which it is in this version
|
||||
mlen++ // minorVer, as long as it's < 127, which it is in this version
|
||||
mlen += ed25519.PublicKeySize // key
|
||||
return
|
||||
}
|
||||
|
||||
// Encodes version metadata into its wire format.
|
||||
func (m *version_metadata) encode() []byte {
|
||||
bs := make([]byte, 0, version_getMetaLength())
|
||||
bs = append(bs, m.meta[:]...)
|
||||
bs = append(bs, m.ver)
|
||||
bs = append(bs, m.minorVer)
|
||||
bs = append(bs, m.key[:]...)
|
||||
if len(bs) != version_getMetaLength() {
|
||||
panic("Inconsistent metadata length")
|
||||
}
|
||||
bs := make([]byte, 0, 64)
|
||||
bs = append(bs, 'm', 'e', 't', 'a')
|
||||
|
||||
bs = binary.BigEndian.AppendUint16(bs, metaVersionMajor)
|
||||
bs = binary.BigEndian.AppendUint16(bs, 2)
|
||||
bs = binary.BigEndian.AppendUint16(bs, m.majorVer)
|
||||
|
||||
bs = binary.BigEndian.AppendUint16(bs, metaVersionMinor)
|
||||
bs = binary.BigEndian.AppendUint16(bs, 2)
|
||||
bs = binary.BigEndian.AppendUint16(bs, m.minorVer)
|
||||
|
||||
bs = binary.BigEndian.AppendUint16(bs, metaPublicKey)
|
||||
bs = binary.BigEndian.AppendUint16(bs, ed25519.PublicKeySize)
|
||||
bs = append(bs, m.publicKey[:]...)
|
||||
|
||||
bs = binary.BigEndian.AppendUint16(bs, metaPriority)
|
||||
bs = binary.BigEndian.AppendUint16(bs, 1)
|
||||
bs = append(bs, m.priority)
|
||||
|
||||
return bs
|
||||
}
|
||||
|
||||
// Decodes version metadata from its wire format into the struct.
|
||||
func (m *version_metadata) decode(bs []byte) bool {
|
||||
if len(bs) != version_getMetaLength() {
|
||||
meta := [4]byte{'m', 'e', 't', 'a'}
|
||||
if !bytes.Equal(bs[:4], meta[:]) {
|
||||
return false
|
||||
}
|
||||
offset := 0
|
||||
offset += copy(m.meta[:], bs[offset:])
|
||||
m.ver, offset = bs[offset], offset+1
|
||||
m.minorVer, offset = bs[offset], offset+1
|
||||
m.key = append([]byte(nil), bs[offset:]...)
|
||||
for bs = bs[4:]; len(bs) >= 4; {
|
||||
op := binary.BigEndian.Uint16(bs[:2])
|
||||
oplen := binary.BigEndian.Uint16(bs[2:4])
|
||||
if bs = bs[4:]; len(bs) < int(oplen) {
|
||||
break
|
||||
}
|
||||
switch op {
|
||||
case metaVersionMajor:
|
||||
m.majorVer = binary.BigEndian.Uint16(bs[:2])
|
||||
|
||||
case metaVersionMinor:
|
||||
m.minorVer = binary.BigEndian.Uint16(bs[:2])
|
||||
|
||||
case metaPublicKey:
|
||||
m.publicKey = make(ed25519.PublicKey, ed25519.PublicKeySize)
|
||||
copy(m.publicKey, bs[:ed25519.PublicKeySize])
|
||||
|
||||
case metaPriority:
|
||||
m.priority = bs[0]
|
||||
}
|
||||
bs = bs[oplen:]
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Checks that the "meta" bytes and the version numbers are the expected values.
|
||||
func (m *version_metadata) check() bool {
|
||||
base := version_getBaseMetadata()
|
||||
return base.meta == m.meta && base.ver == m.ver && base.minorVer == m.minorVer
|
||||
switch {
|
||||
case m.majorVer != ProtocolVersionMajor:
|
||||
return false
|
||||
case m.minorVer != ProtocolVersionMinor:
|
||||
return false
|
||||
case len(m.publicKey) != ed25519.PublicKeySize:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user