mirror of
https://git.numenor-labs.us/dsfx.git
synced 2025-04-29 08:10:34 +00:00
reorganize everything
This commit is contained in:
parent
2b291900b9
commit
2d3631af45
22
README.md
22
README.md
@ -33,13 +33,13 @@ cd dsfx
|
|||||||
Build the project:
|
Build the project:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
go build -o dist/ ./...
|
go build -o dist/ ./cmd/...
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also install the executables to your $GOPATH/bin:
|
You can also install the executables to your $GOPATH/bin:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
go install ./...
|
go install ./cmd/...
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -48,13 +48,13 @@ go install ./...
|
|||||||
|
|
||||||
### Starting the Server
|
### Starting the Server
|
||||||
|
|
||||||
The dsfx-server requires a listening host, port, and an identity key (ECDSA private key in PEM format). For example:
|
The dsfxnode requires a listening host, port, and an identity key (ECDSA private key in PEM format). For example:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
dsfx-server -host localhost -port 8000 -key /path/to/serverkey.pem
|
dsfxnode -host localhost -port 8000 -key /path/to/serverkey.pem
|
||||||
```
|
```
|
||||||
|
|
||||||
> Note, if you need to generate a new ECDSA key, you can use the following command: `go run ./cmd/genkey > path/to/masterkey.pem`
|
> Note, if you need to generate a new ECDSA key, you can use the following command: `go run ./tool/genkey > path/to/masterkey.pem`
|
||||||
|
|
||||||
Command-line flags for dsfx-server:
|
Command-line flags for dsfx-server:
|
||||||
|
|
||||||
@ -69,14 +69,14 @@ File path to the PEM-encoded ECDSA private key that serves as the server’s mas
|
|||||||
|
|
||||||
Once started, the server will bind to the specified host and port and wait for incoming secure file exchange (or other test) connections. When a client connects, the initial payload (up to 1024 bytes) from the client is read and logged.
|
Once started, the server will bind to the specified host and port and wait for incoming secure file exchange (or other test) connections. When a client connects, the initial payload (up to 1024 bytes) from the client is read and logged.
|
||||||
|
|
||||||
### Running the Client
|
### Running the Admin Client
|
||||||
|
|
||||||
The dsfx-client uses a private key for the client (also an ECDSA key in PEM format) and currently supports only the “test” command for checking connectivity to the server.
|
The dsfxctl uses a private key for the client (also an ECDSA key in PEM format) and currently supports only the “test” command for checking connectivity to the server.
|
||||||
|
|
||||||
Client command usage:
|
Client command usage:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
/dsfx-client -key /path/to/clientkey.pem test <remote_addr>
|
dsfxctl -key /path/to/clientkey.pem test <remote_addr>
|
||||||
```
|
```
|
||||||
|
|
||||||
Where:
|
Where:
|
||||||
@ -96,7 +96,7 @@ For example, `dsfx://127.0.0.1:8000#<base64 pubkey>” or “dsfx://127.0.0.1:80
|
|||||||
Example:
|
Example:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
dsfx-client -key ./dsfx-client/masterkey test dsfx://127.0.0.1:8000#eyJuIjoiLy8v..
|
dsfxctl -key ./dsfx-client/masterkey test dsfx://127.0.0.1:8000#eyJuIjoiLy8v..
|
||||||
```
|
```
|
||||||
|
|
||||||
If no command or an unrecognized command is provided, the client will print a brief usage message and exit.
|
If no command or an unrecognized command is provided, the client will print a brief usage message and exit.
|
||||||
@ -106,8 +106,8 @@ If no command or an unrecognized command is provided, the client will print a br
|
|||||||
For quick help, simply pass the -h flag:
|
For quick help, simply pass the -h flag:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
dsfx-server -h
|
dsfxctl -h
|
||||||
dsfx-client -h
|
dsfxnode -h
|
||||||
```
|
```
|
||||||
|
|
||||||
This will display the usage information along with available flags.
|
This will display the usage information along with available flags.
|
||||||
|
9
cmd/dsfx/main.go
Normal file
9
cmd/dsfx/main.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
log.Println("hello from dsfx!")
|
||||||
|
}
|
@ -9,9 +9,9 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"koti.casa/numenor-labs/dsfx/shared/dcrypto"
|
"koti.casa/numenor-labs/dsfx/pkg/crypto/identity"
|
||||||
"koti.casa/numenor-labs/dsfx/shared/dlog"
|
"koti.casa/numenor-labs/dsfx/pkg/logging"
|
||||||
"koti.casa/numenor-labs/dsfx/shared/dnet"
|
"koti.casa/numenor-labs/dsfx/pkg/network"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -31,13 +31,13 @@ func main() {
|
|||||||
// where the context is not available, or the context is not a child of the
|
// where the context is not available, or the context is not a child of the
|
||||||
// context with the logger, the default logger will be used.
|
// context with the logger, the default logger will be used.
|
||||||
slog.SetDefault(logger)
|
slog.SetDefault(logger)
|
||||||
ctx = dlog.WithContext(ctx, logger)
|
ctx = logging.WithContext(ctx, logger)
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Commands
|
// Commands
|
||||||
|
|
||||||
flag.Usage = func() {
|
flag.Usage = func() {
|
||||||
fmt.Fprintf(os.Stderr, "Usage: %s [command] [args]\n", os.Args[0])
|
fmt.Fprintf(os.Stderr, "Usage: dsfxctl [command] [args]\n")
|
||||||
fmt.Fprintf(os.Stderr, "Commands:\n")
|
fmt.Fprintf(os.Stderr, "Commands:\n")
|
||||||
fmt.Fprintf(os.Stderr, " test <remote_addr> Test the connection to the server\n")
|
fmt.Fprintf(os.Stderr, " test <remote_addr> Test the connection to the server\n")
|
||||||
fmt.Fprintf(os.Stderr, "Flags:\n")
|
fmt.Fprintf(os.Stderr, "Flags:\n")
|
||||||
@ -53,13 +53,13 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
identity, err := dcrypto.LoadSigningKeyFromFile(*flagKey)
|
identity, err := identity.LoadSigningKeyFromFile(*flagKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.ErrorContext(ctx, "failed to load private key", slog.Any("error", err))
|
logger.ErrorContext(ctx, "failed to load private key", slog.Any("error", err))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
laddr := dnet.NewAddr(
|
laddr := network.NewAddr(
|
||||||
net.ParseIP("0.0.0.0"),
|
net.ParseIP("0.0.0.0"),
|
||||||
0, // port 0 means any available port
|
0, // port 0 means any available port
|
||||||
&identity.PublicKey,
|
&identity.PublicKey,
|
||||||
@ -84,16 +84,16 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testConnection(ctx context.Context, identity *ecdsa.PrivateKey, laddr *dnet.Addr, raddrRaw string) {
|
func testConnection(ctx context.Context, identity *ecdsa.PrivateKey, laddr *network.Addr, raddrRaw string) {
|
||||||
logger := dlog.FromContext(context.Background())
|
logger := logging.FromContext(context.Background())
|
||||||
|
|
||||||
raddr, err := dnet.ParseAddr(raddrRaw)
|
raddr, err := network.ParseAddr(raddrRaw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.ErrorContext(ctx, "failed to parse server address", slog.Any("error", err))
|
logger.ErrorContext(ctx, "failed to parse server address", slog.Any("error", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err := dnet.Dial(ctx, identity, laddr, raddr)
|
conn, err := network.Dial(ctx, identity, laddr, raddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.ErrorContext(ctx, "failed to connect", slog.Any("error", err))
|
logger.ErrorContext(ctx, "failed to connect", slog.Any("error", err))
|
||||||
return
|
return
|
@ -8,9 +8,9 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"koti.casa/numenor-labs/dsfx/shared/dcrypto"
|
"koti.casa/numenor-labs/dsfx/pkg/crypto/identity"
|
||||||
"koti.casa/numenor-labs/dsfx/shared/dlog"
|
"koti.casa/numenor-labs/dsfx/pkg/logging"
|
||||||
"koti.casa/numenor-labs/dsfx/shared/dnet"
|
"koti.casa/numenor-labs/dsfx/pkg/network"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -36,7 +36,7 @@ func main() {
|
|||||||
// where the context is not available, or the context is not a child of the
|
// where the context is not available, or the context is not a child of the
|
||||||
// context with the logger, the default logger will be used.
|
// context with the logger, the default logger will be used.
|
||||||
slog.SetDefault(logger)
|
slog.SetDefault(logger)
|
||||||
ctx = dlog.WithContext(ctx, logger)
|
ctx = logging.WithContext(ctx, logger)
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Flags
|
// Flags
|
||||||
@ -48,7 +48,7 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
masterKey, err := dcrypto.LoadSigningKeyFromFile(*flagKey)
|
masterKey, err := identity.LoadSigningKeyFromFile(*flagKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.ErrorContext(ctx, "failed to load master key", slog.Any("error", err))
|
logger.ErrorContext(ctx, "failed to load master key", slog.Any("error", err))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -60,12 +60,12 @@ func main() {
|
|||||||
slog.ErrorContext(ctx, "invalid host or port")
|
slog.ErrorContext(ctx, "invalid host or port")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
addr := dnet.FromTCPAddr(tcpAddr, &masterKey.PublicKey)
|
addr := network.FromTCPAddr(tcpAddr, &masterKey.PublicKey)
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Listener
|
// Listener
|
||||||
|
|
||||||
listener, err := dnet.Listen(ctx, masterKey, addr)
|
listener, err := network.Listen(ctx, masterKey, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.ErrorContext(ctx, "listener error", slog.Any("error", err))
|
logger.ErrorContext(ctx, "listener error", slog.Any("error", err))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -87,7 +87,7 @@ func main() {
|
|||||||
func handleConnection(ctx context.Context, conn net.Conn) error {
|
func handleConnection(ctx context.Context, conn net.Conn) error {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
logger := dlog.FromContext(ctx)
|
logger := logging.FromContext(ctx)
|
||||||
|
|
||||||
msg := make([]byte, 1024)
|
msg := make([]byte, 1024)
|
||||||
n, err := conn.Read(msg)
|
n, err := conn.Read(msg)
|
@ -1,4 +1,4 @@
|
|||||||
package dcrypto
|
package encryption
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/aes"
|
"crypto/aes"
|
@ -1,4 +1,4 @@
|
|||||||
package dcrypto
|
package identity
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
@ -1,8 +1,10 @@
|
|||||||
package dcrypto
|
package keyexchange
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ecdh"
|
"crypto/ecdh"
|
||||||
|
"crypto/hkdf"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"crypto/sha256"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -17,7 +19,17 @@ func GenerateDHKey() (*ecdh.PrivateKey, error) {
|
|||||||
|
|
||||||
// ComputeDHSecret computes the shared secret from the private key and the public key.
|
// ComputeDHSecret computes the shared secret from the private key and the public key.
|
||||||
func ComputeDHSecret(priv *ecdh.PrivateKey, pub *ecdh.PublicKey) ([]byte, error) {
|
func ComputeDHSecret(priv *ecdh.PrivateKey, pub *ecdh.PublicKey) ([]byte, error) {
|
||||||
return priv.ECDH(pub)
|
secret, err := priv.ECDH(pub)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
key, err := hkdf.Key(sha256.New, secret, nil, "", 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return key, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExportDHPublicKey exports the public key as a byte slice.
|
// ExportDHPublicKey exports the public key as a byte slice.
|
@ -1,4 +1,4 @@
|
|||||||
package dnet
|
package frame
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
@ -1,11 +1,11 @@
|
|||||||
package dnet_test
|
package frame_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"koti.casa/numenor-labs/dsfx/shared/dnet"
|
"koti.casa/numenor-labs/dsfx/pkg/frame"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLenPrefixedWriteTo(t *testing.T) {
|
func TestLenPrefixedWriteTo(t *testing.T) {
|
||||||
@ -16,7 +16,7 @@ func TestLenPrefixedWriteTo(t *testing.T) {
|
|||||||
|
|
||||||
// When ...
|
// When ...
|
||||||
|
|
||||||
n, err := dnet.NewFrame(msg).WriteTo(buf)
|
n, err := frame.NewFrame(msg).WriteTo(buf)
|
||||||
|
|
||||||
// Then ...
|
// Then ...
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ func TestLenPrefixedReadFrom(t *testing.T) {
|
|||||||
expectedBytesRead := len(msg)
|
expectedBytesRead := len(msg)
|
||||||
|
|
||||||
// When ...
|
// When ...
|
||||||
f := dnet.NewFrame(nil)
|
f := frame.NewFrame(nil)
|
||||||
n, err := f.ReadFrom(buf)
|
n, err := f.ReadFrom(buf)
|
||||||
|
|
||||||
// Then ...
|
// Then ...
|
@ -1,4 +1,4 @@
|
|||||||
package dnet
|
package handshake
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -11,8 +11,11 @@ import (
|
|||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"koti.casa/numenor-labs/dsfx/pkg/assert"
|
"koti.casa/numenor-labs/dsfx/pkg/assert"
|
||||||
"koti.casa/numenor-labs/dsfx/shared/dcrypto"
|
"koti.casa/numenor-labs/dsfx/pkg/crypto/encryption"
|
||||||
"koti.casa/numenor-labs/dsfx/shared/dlog"
|
"koti.casa/numenor-labs/dsfx/pkg/crypto/identity"
|
||||||
|
"koti.casa/numenor-labs/dsfx/pkg/crypto/keyexchange"
|
||||||
|
"koti.casa/numenor-labs/dsfx/pkg/frame"
|
||||||
|
"koti.casa/numenor-labs/dsfx/pkg/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -34,14 +37,14 @@ func Handshake(
|
|||||||
lPrivKey *ecdsa.PrivateKey,
|
lPrivKey *ecdsa.PrivateKey,
|
||||||
rPubKey *ecdsa.PublicKey,
|
rPubKey *ecdsa.PublicKey,
|
||||||
) ([]byte, error) {
|
) ([]byte, error) {
|
||||||
logger := dlog.FromContext(ctx).WithGroup("handshake")
|
logger := logging.FromContext(ctx).WithGroup("handshake")
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Step 1: Ephemeral Key Exchange To Server
|
// Step 1: Ephemeral Key Exchange To Server
|
||||||
|
|
||||||
logger.DebugContext(ctx, "creating dh key")
|
logger.DebugContext(ctx, "creating dh key")
|
||||||
// Create a new ECDH private key for the actor.
|
// Create a new ECDH private key for the actor.
|
||||||
ourDHKey, err := dcrypto.GenerateDHKey()
|
ourDHKey, err := keyexchange.GenerateDHKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -49,7 +52,7 @@ func Handshake(
|
|||||||
|
|
||||||
logger.DebugContext(ctx, "exporting dh key")
|
logger.DebugContext(ctx, "exporting dh key")
|
||||||
// Export the public key of the actor's ECDH private key.
|
// Export the public key of the actor's ECDH private key.
|
||||||
ourDHKeyRaw, err := dcrypto.ExportDHPublicKey(ourDHKey.PublicKey())
|
ourDHKeyRaw, err := keyexchange.ExportDHPublicKey(ourDHKey.PublicKey())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -57,7 +60,7 @@ func Handshake(
|
|||||||
|
|
||||||
// Write the actor's public key to the connection.
|
// Write the actor's public key to the connection.
|
||||||
logger.DebugContext(ctx, "sending dh key", slog.Int("key.size", len(ourDHKeyRaw)))
|
logger.DebugContext(ctx, "sending dh key", slog.Int("key.size", len(ourDHKeyRaw)))
|
||||||
_, err = NewFrame(ourDHKeyRaw).WriteTo(conn)
|
_, err = frame.NewFrame(ourDHKeyRaw).WriteTo(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -67,7 +70,7 @@ func Handshake(
|
|||||||
|
|
||||||
// Read the remote actor's public key from the connection.
|
// Read the remote actor's public key from the connection.
|
||||||
logger.DebugContext(ctx, "waiting for server's dh key")
|
logger.DebugContext(ctx, "waiting for server's dh key")
|
||||||
remoteDHKeyFrame := NewFrame(nil)
|
remoteDHKeyFrame := frame.NewFrame(nil)
|
||||||
_, err = remoteDHKeyFrame.ReadFrom(conn)
|
_, err = remoteDHKeyFrame.ReadFrom(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -78,7 +81,7 @@ func Handshake(
|
|||||||
|
|
||||||
// Import the remote actor's public key.
|
// Import the remote actor's public key.
|
||||||
logger.DebugContext(ctx, "importing server's dh key")
|
logger.DebugContext(ctx, "importing server's dh key")
|
||||||
remoteDHKey, err := dcrypto.ImportDHPublicKey(remoteDHKeyFrame.Contents())
|
remoteDHKey, err := keyexchange.ImportDHPublicKey(remoteDHKeyFrame.Contents())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -88,13 +91,13 @@ func Handshake(
|
|||||||
|
|
||||||
// Export the public key of the actor's signing key.
|
// Export the public key of the actor's signing key.
|
||||||
logger.DebugContext(ctx, "exporting public signing key")
|
logger.DebugContext(ctx, "exporting public signing key")
|
||||||
ourPublicKeyRaw, err := dcrypto.ExportPublicSigningKey(&lPrivKey.PublicKey)
|
ourPublicKeyRaw, err := identity.ExportPublicSigningKey(&lPrivKey.PublicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.DebugContext(ctx, "exporting remote public signing key")
|
logger.DebugContext(ctx, "exporting remote public signing key")
|
||||||
remotePublicKeyRaw, err := dcrypto.ExportPublicSigningKey(rPubKey)
|
remotePublicKeyRaw, err := identity.ExportPublicSigningKey(rPubKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -114,26 +117,18 @@ func Handshake(
|
|||||||
|
|
||||||
// Sign the message with the actor's private key.
|
// Sign the message with the actor's private key.
|
||||||
logger.DebugContext(ctx, "signing authentication message")
|
logger.DebugContext(ctx, "signing authentication message")
|
||||||
signature, err := dcrypto.Sign(lPrivKey, authMessage)
|
signature, err := identity.Sign(lPrivKey, authMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the shared secret between the actor and the remote actor.
|
// Compute the shared secret between the actor and the remote actor.
|
||||||
logger.DebugContext(ctx, "computing shared secret")
|
logger.DebugContext(ctx, "computing shared secret")
|
||||||
sharedSecret, err := dcrypto.ComputeDHSecret(ourDHKey, remoteDHKey)
|
derivedKey, err := keyexchange.ComputeDHSecret(ourDHKey, remoteDHKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
assert.Assert(len(sharedSecret) == 48, "invalid shared secret size")
|
assert.Assert(len(derivedKey) == 32, "invalid shared secret size")
|
||||||
|
|
||||||
// Derive a key from the shared secret using HKDF.
|
|
||||||
logger.DebugContext(ctx, "deriving key from shared secret")
|
|
||||||
derivedKey, err := dcrypto.Key(sharedSecret, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
assert.Assert(len(derivedKey) == 32, "invalid derived key size")
|
|
||||||
|
|
||||||
plaintext := make([]byte, 0, len(ourPublicKeyRaw)+len(signature))
|
plaintext := make([]byte, 0, len(ourPublicKeyRaw)+len(signature))
|
||||||
plaintext = append(plaintext, ourPublicKeyRaw...)
|
plaintext = append(plaintext, ourPublicKeyRaw...)
|
||||||
@ -141,14 +136,14 @@ func Handshake(
|
|||||||
|
|
||||||
// Encrypt the message with the derived key.
|
// Encrypt the message with the derived key.
|
||||||
logger.DebugContext(ctx, "encrypting authentication message")
|
logger.DebugContext(ctx, "encrypting authentication message")
|
||||||
boxedMsg, err := dcrypto.Encrypt(derivedKey, plaintext)
|
boxedMsg, err := encryption.Encrypt(derivedKey, plaintext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the boxed message to the connection.
|
// Write the boxed message to the connection.
|
||||||
logger.DebugContext(ctx, "sending authentication message", slog.Int("message.size", len(boxedMsg)))
|
logger.DebugContext(ctx, "sending authentication message", slog.Int("message.size", len(boxedMsg)))
|
||||||
_, err = NewFrame(boxedMsg).WriteTo(conn)
|
_, err = frame.NewFrame(boxedMsg).WriteTo(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -158,7 +153,7 @@ func Handshake(
|
|||||||
|
|
||||||
// Read the authentication message from the connection.
|
// Read the authentication message from the connection.
|
||||||
logger.DebugContext(ctx, "waiting for server's authentication message")
|
logger.DebugContext(ctx, "waiting for server's authentication message")
|
||||||
authMessageFrame := NewFrame(nil)
|
authMessageFrame := frame.NewFrame(nil)
|
||||||
n, err := authMessageFrame.ReadFrom(conn)
|
n, err := authMessageFrame.ReadFrom(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -167,7 +162,7 @@ func Handshake(
|
|||||||
|
|
||||||
// Decrypt the authentication message with the derived key.
|
// Decrypt the authentication message with the derived key.
|
||||||
logger.DebugContext(ctx, "decrypting authentication message")
|
logger.DebugContext(ctx, "decrypting authentication message")
|
||||||
plaintext, err = dcrypto.Decrypt(derivedKey, authMessageFrame.Contents())
|
plaintext, err = encryption.Decrypt(derivedKey, authMessageFrame.Contents())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -175,20 +170,20 @@ func Handshake(
|
|||||||
// The server authentication is just verifying the signature it created of
|
// The server authentication is just verifying the signature it created of
|
||||||
// the client authentication message.
|
// the client authentication message.
|
||||||
logger.DebugContext(ctx, "importing server's public signing key")
|
logger.DebugContext(ctx, "importing server's public signing key")
|
||||||
remotePublicKey, err := dcrypto.ImportPublicSigningKey(remotePublicKeyRaw)
|
remotePublicKey, err := identity.ImportPublicSigningKey(remotePublicKeyRaw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.DebugContext(ctx, "verifying server's signature")
|
logger.DebugContext(ctx, "verifying server's signature")
|
||||||
if !dcrypto.Verify(remotePublicKey, authMessage, plaintext) {
|
if !identity.Verify(remotePublicKey, authMessage, plaintext) {
|
||||||
return nil, errors.New("failed to verify server's signature")
|
return nil, errors.New("failed to verify server's signature")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, we need to let the server know that the handshake is complete.
|
// Finally, we need to let the server know that the handshake is complete.
|
||||||
logger.DebugContext(ctx, "sending handshake complete message")
|
logger.DebugContext(ctx, "sending handshake complete message")
|
||||||
handshakeCompleteMsg := []byte{0x01}
|
handshakeCompleteMsg := []byte{0x01}
|
||||||
_, err = NewFrame(handshakeCompleteMsg).WriteTo(conn)
|
_, err = frame.NewFrame(handshakeCompleteMsg).WriteTo(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -200,14 +195,14 @@ func Handshake(
|
|||||||
// AcceptHandshake accepts a handshake from the given actor and connection. It
|
// AcceptHandshake accepts a handshake from the given actor and connection. It
|
||||||
// returns the shared secret between the actor and the remote actor.
|
// returns the shared secret between the actor and the remote actor.
|
||||||
func AcceptHandshake(ctx context.Context, conn io.ReadWriteCloser, lPrivKey *ecdsa.PrivateKey) (*ecdsa.PublicKey, []byte, error) {
|
func AcceptHandshake(ctx context.Context, conn io.ReadWriteCloser, lPrivKey *ecdsa.PrivateKey) (*ecdsa.PublicKey, []byte, error) {
|
||||||
logger := dlog.FromContext(ctx).WithGroup("handshake")
|
logger := logging.FromContext(ctx).WithGroup("handshake")
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Step 1: Ephemeral Key Exchange From Client
|
// Step 1: Ephemeral Key Exchange From Client
|
||||||
|
|
||||||
// Read the remote actor's public key from the connection.
|
// Read the remote actor's public key from the connection.
|
||||||
logger.DebugContext(ctx, "waiting for client's dh key")
|
logger.DebugContext(ctx, "waiting for client's dh key")
|
||||||
remoteDHKeyFrame := NewFrame(nil)
|
remoteDHKeyFrame := frame.NewFrame(nil)
|
||||||
_, err := remoteDHKeyFrame.ReadFrom(conn)
|
_, err := remoteDHKeyFrame.ReadFrom(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
@ -215,7 +210,7 @@ func AcceptHandshake(ctx context.Context, conn io.ReadWriteCloser, lPrivKey *ecd
|
|||||||
|
|
||||||
// Import the remote actor's public key.
|
// Import the remote actor's public key.
|
||||||
logger.DebugContext(ctx, "importing client's dh key")
|
logger.DebugContext(ctx, "importing client's dh key")
|
||||||
remoteDHKey, err := dcrypto.ImportDHPublicKey(remoteDHKeyFrame.Contents())
|
remoteDHKey, err := keyexchange.ImportDHPublicKey(remoteDHKeyFrame.Contents())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -225,21 +220,21 @@ func AcceptHandshake(ctx context.Context, conn io.ReadWriteCloser, lPrivKey *ecd
|
|||||||
|
|
||||||
// Create a new ECDH private key for the actor.
|
// Create a new ECDH private key for the actor.
|
||||||
logger.DebugContext(ctx, "creating dh key")
|
logger.DebugContext(ctx, "creating dh key")
|
||||||
ourDHKey, err := dcrypto.GenerateDHKey()
|
ourDHKey, err := keyexchange.GenerateDHKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export the public key of the actor's ECDH private key.
|
// Export the public key of the actor's ECDH private key.
|
||||||
logger.DebugContext(ctx, "exporting dh key")
|
logger.DebugContext(ctx, "exporting dh key")
|
||||||
ourDHKeyRaw, err := dcrypto.ExportDHPublicKey(ourDHKey.PublicKey())
|
ourDHKeyRaw, err := keyexchange.ExportDHPublicKey(ourDHKey.PublicKey())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the actor's public key to the connection.
|
// Write the actor's public key to the connection.
|
||||||
logger.DebugContext(ctx, "sending dh key", slog.Int("key.size", len(ourDHKeyRaw)))
|
logger.DebugContext(ctx, "sending dh key", slog.Int("key.size", len(ourDHKeyRaw)))
|
||||||
_, err = NewFrame(ourDHKeyRaw).WriteTo(conn)
|
_, err = frame.NewFrame(ourDHKeyRaw).WriteTo(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -249,7 +244,7 @@ func AcceptHandshake(ctx context.Context, conn io.ReadWriteCloser, lPrivKey *ecd
|
|||||||
|
|
||||||
// Read the authentication message from the connection.
|
// Read the authentication message from the connection.
|
||||||
logger.DebugContext(ctx, "waiting for client's authentication message")
|
logger.DebugContext(ctx, "waiting for client's authentication message")
|
||||||
authMessageFrame := NewFrame(nil)
|
authMessageFrame := frame.NewFrame(nil)
|
||||||
n, err := authMessageFrame.ReadFrom(conn)
|
n, err := authMessageFrame.ReadFrom(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
@ -258,20 +253,13 @@ func AcceptHandshake(ctx context.Context, conn io.ReadWriteCloser, lPrivKey *ecd
|
|||||||
|
|
||||||
// Decrypt the authentication message with the derived key.
|
// Decrypt the authentication message with the derived key.
|
||||||
logger.DebugContext(ctx, "computing shared secret")
|
logger.DebugContext(ctx, "computing shared secret")
|
||||||
sharedSecret, err := dcrypto.ComputeDHSecret(ourDHKey, remoteDHKey)
|
derivedKey, err := keyexchange.ComputeDHSecret(ourDHKey, remoteDHKey)
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Derive a key from the shared secret using HKDF.
|
|
||||||
logger.DebugContext(ctx, "deriving key from shared secret")
|
|
||||||
derivedKey, err := dcrypto.Key(sharedSecret, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.DebugContext(ctx, "decrypting authentication message")
|
logger.DebugContext(ctx, "decrypting authentication message")
|
||||||
plaintext, err := dcrypto.Decrypt(derivedKey, authMessageFrame.Contents())
|
plaintext, err := encryption.Decrypt(derivedKey, authMessageFrame.Contents())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -281,7 +269,7 @@ func AcceptHandshake(ctx context.Context, conn io.ReadWriteCloser, lPrivKey *ecd
|
|||||||
|
|
||||||
// Verify the client's public key and signature.
|
// Verify the client's public key and signature.
|
||||||
logger.DebugContext(ctx, "importing client's public signing key")
|
logger.DebugContext(ctx, "importing client's public signing key")
|
||||||
clientPublicKey, err := dcrypto.ImportPublicSigningKey(clientPublicKeyRaw)
|
clientPublicKey, err := identity.ImportPublicSigningKey(clientPublicKeyRaw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -300,7 +288,7 @@ func AcceptHandshake(ctx context.Context, conn io.ReadWriteCloser, lPrivKey *ecd
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.DebugContext(ctx, "verifying client's signature")
|
logger.DebugContext(ctx, "verifying client's signature")
|
||||||
if !dcrypto.Verify(clientPublicKey, authMessage, signature) {
|
if !identity.Verify(clientPublicKey, authMessage, signature) {
|
||||||
return nil, nil, errors.New("failed to verify client's signature")
|
return nil, nil, errors.New("failed to verify client's signature")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,27 +296,27 @@ func AcceptHandshake(ctx context.Context, conn io.ReadWriteCloser, lPrivKey *ecd
|
|||||||
// key. This will be sent back to the client in the next step to authenticate
|
// key. This will be sent back to the client in the next step to authenticate
|
||||||
// the server to the client.
|
// the server to the client.
|
||||||
logger.DebugContext(ctx, "signing authentication message")
|
logger.DebugContext(ctx, "signing authentication message")
|
||||||
serverSignature, err := dcrypto.Sign(lPrivKey, authMessage)
|
serverSignature, err := identity.Sign(lPrivKey, authMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.DebugContext(ctx, "encrypting server's signature")
|
logger.DebugContext(ctx, "encrypting server's signature")
|
||||||
boxedMsg, err := dcrypto.Encrypt(derivedKey, serverSignature)
|
boxedMsg, err := encryption.Encrypt(derivedKey, serverSignature)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the server's signature back to the client.
|
// Send the server's signature back to the client.
|
||||||
logger.DebugContext(ctx, "sending authentication message", slog.Int("message.size", len(boxedMsg)))
|
logger.DebugContext(ctx, "sending authentication message", slog.Int("message.size", len(boxedMsg)))
|
||||||
_, err = NewFrame(boxedMsg).WriteTo(conn)
|
_, err = frame.NewFrame(boxedMsg).WriteTo(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.DebugContext(ctx, "waiting for handshake complete message")
|
logger.DebugContext(ctx, "waiting for handshake complete message")
|
||||||
// Read the handshake complete message from the client.
|
// Read the handshake complete message from the client.
|
||||||
handshakeCompleteFrame := NewFrame(nil)
|
handshakeCompleteFrame := frame.NewFrame(nil)
|
||||||
_, err = handshakeCompleteFrame.ReadFrom(conn)
|
_, err = handshakeCompleteFrame.ReadFrom(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
@ -345,11 +333,11 @@ func AcceptHandshake(ctx context.Context, conn io.ReadWriteCloser, lPrivKey *ecd
|
|||||||
}
|
}
|
||||||
|
|
||||||
func buildMessage(clientPubKey *ecdh.PublicKey, serverPubKey *ecdh.PublicKey) ([]byte, error) {
|
func buildMessage(clientPubKey *ecdh.PublicKey, serverPubKey *ecdh.PublicKey) ([]byte, error) {
|
||||||
clientPubKeyRaw, err := dcrypto.ExportDHPublicKey(clientPubKey)
|
clientPubKeyRaw, err := keyexchange.ExportDHPublicKey(clientPubKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
serverPubKeyRaw, err := dcrypto.ExportDHPublicKey(serverPubKey)
|
serverPubKeyRaw, err := keyexchange.ExportDHPublicKey(serverPubKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package dnet_test
|
package handshake_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -10,17 +10,17 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"koti.casa/numenor-labs/dsfx/shared/dcrypto"
|
"koti.casa/numenor-labs/dsfx/pkg/crypto/identity"
|
||||||
"koti.casa/numenor-labs/dsfx/shared/dnet"
|
"koti.casa/numenor-labs/dsfx/pkg/handshake"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHandshake(t *testing.T) {
|
func TestHandshake(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
// alice, represented by an ecdsa key pair.
|
// alice, represented by an ecdsa key pair.
|
||||||
alice, _ := dcrypto.GenerateSigningKey()
|
alice, _ := identity.GenerateSigningKey()
|
||||||
// bob, also represented by an ecdsa key pair.
|
// bob, also represented by an ecdsa key pair.
|
||||||
bob, _ := dcrypto.GenerateSigningKey()
|
bob, _ := identity.GenerateSigningKey()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// the secret that alice should arrive at on her own
|
// the secret that alice should arrive at on her own
|
||||||
@ -47,11 +47,11 @@ func TestHandshake(t *testing.T) {
|
|||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Add(2)
|
wg.Add(2)
|
||||||
go func() {
|
go func() {
|
||||||
aliceSecret, aliceErr = dnet.Handshake(ctx, client, alice, &bob.PublicKey)
|
aliceSecret, aliceErr = handshake.Handshake(ctx, client, alice, &bob.PublicKey)
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
discoveredAlicePublicKey, bobSecret, bobErr = dnet.AcceptHandshake(ctx, server, bob)
|
discoveredAlicePublicKey, bobSecret, bobErr = handshake.AcceptHandshake(ctx, server, bob)
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
@ -94,9 +94,9 @@ func runSimulation() error {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
// alice, represented by an ecdsa key pair.
|
// alice, represented by an ecdsa key pair.
|
||||||
alice, _ := dcrypto.GenerateSigningKey()
|
alice, _ := identity.GenerateSigningKey()
|
||||||
// bob, also represented by an ecdsa key pair.
|
// bob, also represented by an ecdsa key pair.
|
||||||
bob, _ := dcrypto.GenerateSigningKey()
|
bob, _ := identity.GenerateSigningKey()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// the secret that alice should arrive at on her own
|
// the secret that alice should arrive at on her own
|
||||||
@ -123,11 +123,11 @@ func runSimulation() error {
|
|||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Add(2)
|
wg.Add(2)
|
||||||
go func() {
|
go func() {
|
||||||
_, aliceErr = dnet.Handshake(ctx, client, alice, &bob.PublicKey)
|
_, aliceErr = handshake.Handshake(ctx, client, alice, &bob.PublicKey)
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
_, _, bobErr = dnet.AcceptHandshake(ctx, server, bob)
|
_, _, bobErr = handshake.AcceptHandshake(ctx, server, bob)
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
wg.Wait()
|
wg.Wait()
|
@ -1,4 +1,4 @@
|
|||||||
package dlog
|
package logging
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
@ -1,4 +1,4 @@
|
|||||||
package dnet
|
package network
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
@ -8,7 +8,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"koti.casa/numenor-labs/dsfx/shared/dcrypto"
|
"koti.casa/numenor-labs/dsfx/pkg/crypto/identity"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -60,7 +60,7 @@ func ParseAddr(addrRaw string) (*Addr, error) {
|
|||||||
return nil, ErrInvalidFormat
|
return nil, ErrInvalidFormat
|
||||||
}
|
}
|
||||||
|
|
||||||
publicKey, err := dcrypto.ImportPublicSigningKey(publicKeyBytes)
|
publicKey, err := identity.ImportPublicSigningKey(publicKeyBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ErrInvalidFormat
|
return nil, ErrInvalidFormat
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ func (a *Addr) Network() string {
|
|||||||
|
|
||||||
// String implements net.Addr.
|
// String implements net.Addr.
|
||||||
func (a *Addr) String() string {
|
func (a *Addr) String() string {
|
||||||
exported, _ := dcrypto.ExportPublicSigningKey(a.publicKey)
|
exported, _ := identity.ExportPublicSigningKey(a.publicKey)
|
||||||
exportedBase64 := base64.StdEncoding.EncodeToString(exported)
|
exportedBase64 := base64.StdEncoding.EncodeToString(exported)
|
||||||
return fmt.Sprintf("%s://%s:%d#%s", a.network, a.ip, a.port, exportedBase64)
|
return fmt.Sprintf("%s://%s:%d#%s", a.network, a.ip, a.port, exportedBase64)
|
||||||
}
|
}
|
@ -1,11 +1,12 @@
|
|||||||
package dnet
|
package network
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"koti.casa/numenor-labs/dsfx/shared/dcrypto"
|
"koti.casa/numenor-labs/dsfx/pkg/crypto/encryption"
|
||||||
|
"koti.casa/numenor-labs/dsfx/pkg/frame"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Conn is a wrapper around net.TCPConn that encrypts and decrypts data as it is
|
// Conn is a wrapper around net.TCPConn that encrypts and decrypts data as it is
|
||||||
@ -27,12 +28,12 @@ func NewConn(conn *net.TCPConn, sessionKey []byte, localIdentity, remoteIdentity
|
|||||||
// The ciphertext that is actually transferred over the network is larger, so you
|
// The ciphertext that is actually transferred over the network is larger, so you
|
||||||
// should not rely on this number as an indication of network metrics.
|
// should not rely on this number as an indication of network metrics.
|
||||||
func (c *Conn) Read(b []byte) (int, error) {
|
func (c *Conn) Read(b []byte) (int, error) {
|
||||||
f := NewFrame(nil)
|
f := frame.NewFrame(nil)
|
||||||
_, err := f.ReadFrom(c.conn)
|
_, err := f.ReadFrom(c.conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
plaintext, err := dcrypto.Decrypt(c.sessionKey, f.Contents())
|
plaintext, err := encryption.Decrypt(c.sessionKey, f.Contents())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -42,11 +43,11 @@ func (c *Conn) Read(b []byte) (int, error) {
|
|||||||
|
|
||||||
// Write implements io.Writer.
|
// Write implements io.Writer.
|
||||||
func (c *Conn) Write(b []byte) (int, error) {
|
func (c *Conn) Write(b []byte) (int, error) {
|
||||||
ciphertext, err := dcrypto.Encrypt(c.sessionKey, b)
|
ciphertext, err := encryption.Encrypt(c.sessionKey, b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
_, err = NewFrame(ciphertext).WriteTo(c.conn)
|
_, err = frame.NewFrame(ciphertext).WriteTo(c.conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
@ -1,10 +1,12 @@
|
|||||||
package dnet
|
package network
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"koti.casa/numenor-labs/dsfx/pkg/handshake"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Listener ...
|
// Listener ...
|
||||||
@ -23,7 +25,7 @@ func (l *Listener) Accept() (net.Conn, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
clientIdentity, sessionKey, err := AcceptHandshake(ctx, conn, l.identity)
|
clientIdentity, sessionKey, err := handshake.AcceptHandshake(ctx, conn, l.identity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
@ -1,11 +1,12 @@
|
|||||||
package dnet
|
package network
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"koti.casa/numenor-labs/dsfx/shared/dlog"
|
"koti.casa/numenor-labs/dsfx/pkg/handshake"
|
||||||
|
"koti.casa/numenor-labs/dsfx/pkg/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Dial ...
|
// Dial ...
|
||||||
@ -20,7 +21,7 @@ func Dial(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionKey, err := Handshake(ctx, conn, identity, raddr.PublicKey())
|
sessionKey, err := handshake.Handshake(ctx, conn, identity, raddr.PublicKey())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -39,7 +40,7 @@ func Listen(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
logger := dlog.FromContext(ctx)
|
logger := logging.FromContext(ctx)
|
||||||
|
|
||||||
return &Listener{logger, tcpListener, identity}, nil
|
return &Listener{logger, tcpListener, identity}, nil
|
||||||
}
|
}
|
@ -1,11 +0,0 @@
|
|||||||
package dcrypto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/hkdf"
|
|
||||||
"crypto/sha256"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Key creates a key from the given secret and salt using HKDF.
|
|
||||||
func Key(secret, salt []byte) ([]byte, error) {
|
|
||||||
return hkdf.Key(sha256.New, secret, salt, "", 32)
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
package dcrypto
|
|
||||||
|
|
||||||
import "crypto/rand"
|
|
||||||
|
|
||||||
// Challenge generates a random challenge of n bytes.
|
|
||||||
func Challenge(n int) []byte {
|
|
||||||
challenge := make([]byte, n)
|
|
||||||
if _, err := rand.Read(challenge); err != nil || len(challenge) != n {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return challenge
|
|
||||||
}
|
|
@ -6,11 +6,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"koti.casa/numenor-labs/dsfx/shared/dcrypto"
|
"koti.casa/numenor-labs/dsfx/pkg/crypto/identity"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
key, err := dcrypto.GenerateSigningKey()
|
key, err := identity.GenerateSigningKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user