mirror of
https://github.com/1f349/dendrite.git
synced 2024-11-10 06:53:00 +00:00
Improvements to Yggdrasil demo (#1114)
* Improvements to Yggdrasil demo * Fix missing copyright * Fix tie-break
This commit is contained in:
parent
90a0aa9b3e
commit
3b4be90000
53
cmd/dendrite-demo-yggdrasil/convert/25519.go
Normal file
53
cmd/dendrite-demo-yggdrasil/convert/25519.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// Copyright 2019 Google LLC
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file or at
|
||||||
|
// https://developers.google.com/open-source/licenses/bsd
|
||||||
|
//
|
||||||
|
// Original code from https://github.com/FiloSottile/age/blob/bbab440e198a4d67ba78591176c7853e62d29e04/internal/age/ssh.go
|
||||||
|
|
||||||
|
package convert
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ed25519"
|
||||||
|
"crypto/sha512"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/curve25519"
|
||||||
|
)
|
||||||
|
|
||||||
|
var curve25519P, _ = new(big.Int).SetString("57896044618658097711785492504343953926634992332820282019728792003956564819949", 10)
|
||||||
|
|
||||||
|
func Ed25519PrivateKeyToCurve25519(pk ed25519.PrivateKey) []byte {
|
||||||
|
h := sha512.New()
|
||||||
|
_, _ = h.Write(pk.Seed())
|
||||||
|
out := h.Sum(nil)
|
||||||
|
return out[:curve25519.ScalarSize]
|
||||||
|
}
|
||||||
|
|
||||||
|
func Ed25519PublicKeyToCurve25519(pk ed25519.PublicKey) []byte {
|
||||||
|
// ed25519.PublicKey is a little endian representation of the y-coordinate,
|
||||||
|
// with the most significant bit set based on the sign of the x-coordinate.
|
||||||
|
bigEndianY := make([]byte, ed25519.PublicKeySize)
|
||||||
|
for i, b := range pk {
|
||||||
|
bigEndianY[ed25519.PublicKeySize-i-1] = b
|
||||||
|
}
|
||||||
|
bigEndianY[0] &= 0b0111_1111
|
||||||
|
|
||||||
|
// The Montgomery u-coordinate is derived through the bilinear map
|
||||||
|
// u = (1 + y) / (1 - y)
|
||||||
|
// See https://blog.filippo.io/using-ed25519-keys-for-encryption.
|
||||||
|
y := new(big.Int).SetBytes(bigEndianY)
|
||||||
|
denom := big.NewInt(1)
|
||||||
|
denom.ModInverse(denom.Sub(denom, y), curve25519P) // 1 / (1 - y)
|
||||||
|
u := y.Mul(y.Add(y, big.NewInt(1)), denom)
|
||||||
|
u.Mod(u, curve25519P)
|
||||||
|
|
||||||
|
out := make([]byte, curve25519.PointSize)
|
||||||
|
uBytes := u.Bytes()
|
||||||
|
for i, b := range uBytes {
|
||||||
|
out[len(uBytes)-i-1] = b
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
51
cmd/dendrite-demo-yggdrasil/convert/25519_test.go
Normal file
51
cmd/dendrite-demo-yggdrasil/convert/25519_test.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package convert
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/ed25519"
|
||||||
|
"encoding/hex"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/curve25519"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestKeyConversion(t *testing.T) {
|
||||||
|
edPub, edPriv, err := ed25519.GenerateKey(nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log("Signing public:", hex.EncodeToString(edPub))
|
||||||
|
t.Log("Signing private:", hex.EncodeToString(edPriv))
|
||||||
|
|
||||||
|
cuPriv := Ed25519PrivateKeyToCurve25519(edPriv)
|
||||||
|
t.Log("Encryption private:", hex.EncodeToString(cuPriv))
|
||||||
|
|
||||||
|
cuPub := Ed25519PublicKeyToCurve25519(edPub)
|
||||||
|
t.Log("Converted encryption public:", hex.EncodeToString(cuPub))
|
||||||
|
|
||||||
|
var realPub, realPriv [32]byte
|
||||||
|
copy(realPriv[:32], cuPriv[:32])
|
||||||
|
curve25519.ScalarBaseMult(&realPub, &realPriv)
|
||||||
|
t.Log("Scalar-multed encryption public:", hex.EncodeToString(realPub[:]))
|
||||||
|
|
||||||
|
if !bytes.Equal(realPriv[:], cuPriv[:]) {
|
||||||
|
t.Fatal("Private keys should be equal (this means the test is broken)")
|
||||||
|
}
|
||||||
|
if !bytes.Equal(realPub[:], cuPub[:]) {
|
||||||
|
t.Fatal("Public keys should be equal")
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,9 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/ed25519"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"encoding/hex"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
@ -25,6 +27,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/appservice"
|
"github.com/matrix-org/dendrite/appservice"
|
||||||
|
"github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/convert"
|
||||||
|
"github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/signing"
|
||||||
"github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/yggconn"
|
"github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/yggconn"
|
||||||
"github.com/matrix-org/dendrite/eduserver"
|
"github.com/matrix-org/dendrite/eduserver"
|
||||||
"github.com/matrix-org/dendrite/eduserver/cache"
|
"github.com/matrix-org/dendrite/eduserver/cache"
|
||||||
@ -35,7 +39,6 @@ import (
|
|||||||
"github.com/matrix-org/dendrite/internal/setup"
|
"github.com/matrix-org/dendrite/internal/setup"
|
||||||
"github.com/matrix-org/dendrite/publicroomsapi/storage"
|
"github.com/matrix-org/dendrite/publicroomsapi/storage"
|
||||||
"github.com/matrix-org/dendrite/roomserver"
|
"github.com/matrix-org/dendrite/roomserver"
|
||||||
"github.com/matrix-org/dendrite/serverkeyapi"
|
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@ -61,7 +64,13 @@ func createFederationClient(
|
|||||||
) *gomatrixserverlib.FederationClient {
|
) *gomatrixserverlib.FederationClient {
|
||||||
yggdialer := func(_, address string) (net.Conn, error) {
|
yggdialer := func(_, address string) (net.Conn, error) {
|
||||||
tokens := strings.Split(address, ":")
|
tokens := strings.Split(address, ":")
|
||||||
return n.Dial("curve25519", tokens[0])
|
raw, err := hex.DecodeString(tokens[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("hex.DecodeString: %w", err)
|
||||||
|
}
|
||||||
|
converted := convert.Ed25519PublicKeyToCurve25519(ed25519.PublicKey(raw))
|
||||||
|
convhex := hex.EncodeToString(converted)
|
||||||
|
return n.Dial("curve25519", convhex)
|
||||||
}
|
}
|
||||||
yggdialerctx := func(ctx context.Context, network, address string) (net.Conn, error) {
|
yggdialerctx := func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||||
return yggdialer(network, address)
|
return yggdialer(network, address)
|
||||||
@ -102,9 +111,9 @@ func main() {
|
|||||||
|
|
||||||
cfg := &config.Dendrite{}
|
cfg := &config.Dendrite{}
|
||||||
cfg.SetDefaults()
|
cfg.SetDefaults()
|
||||||
cfg.Matrix.ServerName = gomatrixserverlib.ServerName(ygg.EncryptionPublicKey())
|
cfg.Matrix.ServerName = gomatrixserverlib.ServerName(ygg.DerivedServerName())
|
||||||
cfg.Matrix.PrivateKey = ygg.SigningPrivateKey()
|
cfg.Matrix.PrivateKey = ygg.SigningPrivateKey()
|
||||||
cfg.Matrix.KeyID = gomatrixserverlib.KeyID("ed25519:auto")
|
cfg.Matrix.KeyID = gomatrixserverlib.KeyID(signing.KeyID)
|
||||||
cfg.Kafka.UseNaffka = true
|
cfg.Kafka.UseNaffka = true
|
||||||
cfg.Kafka.Topics.OutputRoomEvent = "roomserverOutput"
|
cfg.Kafka.Topics.OutputRoomEvent = "roomserverOutput"
|
||||||
cfg.Kafka.Topics.OutputClientData = "clientapiOutput"
|
cfg.Kafka.Topics.OutputClientData = "clientapiOutput"
|
||||||
@ -130,9 +139,7 @@ func main() {
|
|||||||
deviceDB := base.CreateDeviceDB()
|
deviceDB := base.CreateDeviceDB()
|
||||||
federation := createFederationClient(base, ygg)
|
federation := createFederationClient(base, ygg)
|
||||||
|
|
||||||
serverKeyAPI := serverkeyapi.NewInternalAPI(
|
serverKeyAPI := &signing.YggdrasilKeys{}
|
||||||
base.Cfg, federation, base.Caches,
|
|
||||||
)
|
|
||||||
keyRing := serverKeyAPI.KeyRing()
|
keyRing := serverKeyAPI.KeyRing()
|
||||||
|
|
||||||
rsComponent := roomserver.NewInternalAPI(
|
rsComponent := roomserver.NewInternalAPI(
|
||||||
@ -170,7 +177,7 @@ func main() {
|
|||||||
EDUInternalAPI: eduInputAPI,
|
EDUInternalAPI: eduInputAPI,
|
||||||
FederationSenderAPI: fsAPI,
|
FederationSenderAPI: fsAPI,
|
||||||
RoomserverAPI: rsAPI,
|
RoomserverAPI: rsAPI,
|
||||||
ServerKeyAPI: serverKeyAPI,
|
//ServerKeyAPI: serverKeyAPI,
|
||||||
|
|
||||||
PublicRoomsDB: publicRoomsDB,
|
PublicRoomsDB: publicRoomsDB,
|
||||||
}
|
}
|
||||||
@ -185,7 +192,7 @@ func main() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
logrus.Info("Listening on ", ygg.EncryptionPublicKey())
|
logrus.Info("Listening on ", ygg.DerivedServerName())
|
||||||
logrus.Fatal(httpServer.Serve(ygg))
|
logrus.Fatal(httpServer.Serve(ygg))
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
|
69
cmd/dendrite-demo-yggdrasil/signing/fetcher.go
Normal file
69
cmd/dendrite-demo-yggdrasil/signing/fetcher.go
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package signing
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
|
)
|
||||||
|
|
||||||
|
const KeyID = "ed25519:dendrite-demo-yggdrasil"
|
||||||
|
|
||||||
|
type YggdrasilKeys struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *YggdrasilKeys) KeyRing() *gomatrixserverlib.KeyRing {
|
||||||
|
return &gomatrixserverlib.KeyRing{
|
||||||
|
KeyDatabase: f,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *YggdrasilKeys) FetchKeys(
|
||||||
|
ctx context.Context,
|
||||||
|
requests map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp,
|
||||||
|
) (map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult, error) {
|
||||||
|
res := make(map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult)
|
||||||
|
for req := range requests {
|
||||||
|
if req.KeyID != KeyID {
|
||||||
|
return nil, fmt.Errorf("FetchKeys: cannot fetch key with ID %s, should be %s", req.KeyID, KeyID)
|
||||||
|
}
|
||||||
|
|
||||||
|
hexkey, err := hex.DecodeString(string(req.ServerName))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("FetchKeys: can't decode server name %q: %w", req.ServerName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
res[req] = gomatrixserverlib.PublicKeyLookupResult{
|
||||||
|
VerifyKey: gomatrixserverlib.VerifyKey{
|
||||||
|
Key: hexkey,
|
||||||
|
},
|
||||||
|
ExpiredTS: gomatrixserverlib.PublicKeyNotExpired,
|
||||||
|
ValidUntilTS: gomatrixserverlib.AsTimestamp(time.Now().Add(24 * time.Hour * 365)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *YggdrasilKeys) FetcherName() string {
|
||||||
|
return "YggdrasilKeys"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *YggdrasilKeys) StoreKeys(ctx context.Context, results map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult) error {
|
||||||
|
return nil
|
||||||
|
}
|
@ -24,6 +24,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/convert"
|
||||||
|
|
||||||
"github.com/libp2p/go-yamux"
|
"github.com/libp2p/go-yamux"
|
||||||
yggdrasiladmin "github.com/yggdrasil-network/yggdrasil-go/src/admin"
|
yggdrasiladmin "github.com/yggdrasil-network/yggdrasil-go/src/admin"
|
||||||
yggdrasilconfig "github.com/yggdrasil-network/yggdrasil-go/src/config"
|
yggdrasilconfig "github.com/yggdrasil-network/yggdrasil-go/src/config"
|
||||||
@ -56,8 +58,6 @@ func Setup(instanceName, instancePeer string) (*Node, error) {
|
|||||||
log: gologme.New(os.Stdout, "YGG ", log.Flags()),
|
log: gologme.New(os.Stdout, "YGG ", log.Flags()),
|
||||||
incoming: make(chan *yamux.Stream),
|
incoming: make(chan *yamux.Stream),
|
||||||
}
|
}
|
||||||
n.config.AdminListen = fmt.Sprintf("unix://./%s-yggdrasil.sock", instanceName)
|
|
||||||
n.config.MulticastInterfaces = []string{".*"}
|
|
||||||
|
|
||||||
yggfile := fmt.Sprintf("%s-yggdrasil.conf", instanceName)
|
yggfile := fmt.Sprintf("%s-yggdrasil.conf", instanceName)
|
||||||
if _, err := os.Stat(yggfile); !os.IsNotExist(err) {
|
if _, err := os.Stat(yggfile); !os.IsNotExist(err) {
|
||||||
@ -69,6 +69,11 @@ func Setup(instanceName, instancePeer string) (*Node, error) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
n.config.AdminListen = fmt.Sprintf("unix://./%s-yggdrasil.sock", instanceName)
|
||||||
|
n.config.MulticastInterfaces = []string{".*"}
|
||||||
|
n.config.EncryptionPrivateKey = hex.EncodeToString(n.EncryptionPrivateKey())
|
||||||
|
n.config.EncryptionPublicKey = hex.EncodeToString(n.EncryptionPublicKey())
|
||||||
|
|
||||||
j, err := json.MarshalIndent(n.config, "", " ")
|
j, err := json.MarshalIndent(n.config, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -119,8 +124,23 @@ func Setup(instanceName, instancePeer string) (*Node, error) {
|
|||||||
return n, nil
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Node) EncryptionPublicKey() string {
|
func (n *Node) DerivedServerName() string {
|
||||||
return n.core.EncryptionPublicKey()
|
return hex.EncodeToString(n.SigningPublicKey())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) EncryptionPublicKey() []byte {
|
||||||
|
edkey := n.SigningPublicKey()
|
||||||
|
return convert.Ed25519PublicKeyToCurve25519(edkey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) EncryptionPrivateKey() []byte {
|
||||||
|
edkey := n.SigningPrivateKey()
|
||||||
|
return convert.Ed25519PrivateKeyToCurve25519(edkey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) SigningPublicKey() ed25519.PublicKey {
|
||||||
|
pubBytes, _ := hex.DecodeString(n.config.SigningPublicKey)
|
||||||
|
return ed25519.PublicKey(pubBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Node) SigningPrivateKey() ed25519.PrivateKey {
|
func (n *Node) SigningPrivateKey() ed25519.PrivateKey {
|
||||||
|
@ -40,10 +40,10 @@ func (n *Node) listenFromYgg() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
var session *yamux.Session
|
var session *yamux.Session
|
||||||
if strings.Compare(n.EncryptionPublicKey(), conn.RemoteAddr().String()) < 0 {
|
if strings.Compare(conn.RemoteAddr().String(), n.DerivedServerName()) < 0 {
|
||||||
session, err = yamux.Client(conn, n.yamuxConfig())
|
|
||||||
} else {
|
|
||||||
session, err = yamux.Server(conn, n.yamuxConfig())
|
session, err = yamux.Server(conn, n.yamuxConfig())
|
||||||
|
} else {
|
||||||
|
session, err = yamux.Client(conn, n.yamuxConfig())
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -96,7 +96,7 @@ func (n *Node) DialContext(ctx context.Context, network, address string) (net.Co
|
|||||||
n.log.Println("n.dialer.DialContext:", err)
|
n.log.Println("n.dialer.DialContext:", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if strings.Compare(n.EncryptionPublicKey(), address) < 0 {
|
if strings.Compare(address, n.DerivedServerName()) > 0 {
|
||||||
session, err = yamux.Client(conn, n.yamuxConfig())
|
session, err = yamux.Client(conn, n.yamuxConfig())
|
||||||
} else {
|
} else {
|
||||||
session, err = yamux.Server(conn, n.yamuxConfig())
|
session, err = yamux.Server(conn, n.yamuxConfig())
|
||||||
|
Loading…
Reference in New Issue
Block a user