reorganize everything

This commit is contained in:
Dustin Stiles 2025-03-09 15:52:33 -04:00
parent 2b291900b9
commit 2d3631af45
Signed by: duwstiles
GPG Key ID: BCD9912EC231FC87
20 changed files with 135 additions and 145 deletions

View File

@ -33,13 +33,13 @@ cd dsfx
Build the project:
```sh
go build -o dist/ ./...
go build -o dist/ ./cmd/...
```
You can also install the executables to your $GOPATH/bin:
```sh
go install ./...
go install ./cmd/...
```
---
@ -48,13 +48,13 @@ go install ./...
### 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
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:
@ -69,14 +69,14 @@ File path to the PEM-encoded ECDSA private key that serves as the servers 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.
### 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:
```sh
/dsfx-client -key /path/to/clientkey.pem test <remote_addr>
dsfxctl -key /path/to/clientkey.pem test <remote_addr>
```
Where:
@ -96,7 +96,7 @@ For example, `dsfx://127.0.0.1:8000#<base64 pubkey>” or “dsfx://127.0.0.1:80
Example:
```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.
@ -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:
```sh
dsfx-server -h
dsfx-client -h
dsfxctl -h
dsfxnode -h
```
This will display the usage information along with available flags.

9
cmd/dsfx/main.go Normal file
View File

@ -0,0 +1,9 @@
package main
import (
"log"
)
func main() {
log.Println("hello from dsfx!")
}

View File

@ -9,9 +9,9 @@ import (
"net"
"os"
"koti.casa/numenor-labs/dsfx/shared/dcrypto"
"koti.casa/numenor-labs/dsfx/shared/dlog"
"koti.casa/numenor-labs/dsfx/shared/dnet"
"koti.casa/numenor-labs/dsfx/pkg/crypto/identity"
"koti.casa/numenor-labs/dsfx/pkg/logging"
"koti.casa/numenor-labs/dsfx/pkg/network"
)
func main() {
@ -31,13 +31,13 @@ func main() {
// 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.
slog.SetDefault(logger)
ctx = dlog.WithContext(ctx, logger)
ctx = logging.WithContext(ctx, logger)
// ---------------------------------------------------------------------------
// Commands
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, " test <remote_addr> Test the connection to the server\n")
fmt.Fprintf(os.Stderr, "Flags:\n")
@ -53,13 +53,13 @@ func main() {
os.Exit(1)
}
identity, err := dcrypto.LoadSigningKeyFromFile(*flagKey)
identity, err := identity.LoadSigningKeyFromFile(*flagKey)
if err != nil {
logger.ErrorContext(ctx, "failed to load private key", slog.Any("error", err))
os.Exit(1)
}
laddr := dnet.NewAddr(
laddr := network.NewAddr(
net.ParseIP("0.0.0.0"),
0, // port 0 means any available port
&identity.PublicKey,
@ -84,16 +84,16 @@ func main() {
}
}
func testConnection(ctx context.Context, identity *ecdsa.PrivateKey, laddr *dnet.Addr, raddrRaw string) {
logger := dlog.FromContext(context.Background())
func testConnection(ctx context.Context, identity *ecdsa.PrivateKey, laddr *network.Addr, raddrRaw string) {
logger := logging.FromContext(context.Background())
raddr, err := dnet.ParseAddr(raddrRaw)
raddr, err := network.ParseAddr(raddrRaw)
if err != nil {
logger.ErrorContext(ctx, "failed to parse server address", slog.Any("error", err))
return
}
conn, err := dnet.Dial(ctx, identity, laddr, raddr)
conn, err := network.Dial(ctx, identity, laddr, raddr)
if err != nil {
logger.ErrorContext(ctx, "failed to connect", slog.Any("error", err))
return

View File

@ -8,9 +8,9 @@ import (
"net"
"os"
"koti.casa/numenor-labs/dsfx/shared/dcrypto"
"koti.casa/numenor-labs/dsfx/shared/dlog"
"koti.casa/numenor-labs/dsfx/shared/dnet"
"koti.casa/numenor-labs/dsfx/pkg/crypto/identity"
"koti.casa/numenor-labs/dsfx/pkg/logging"
"koti.casa/numenor-labs/dsfx/pkg/network"
)
var (
@ -36,7 +36,7 @@ func main() {
// 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.
slog.SetDefault(logger)
ctx = dlog.WithContext(ctx, logger)
ctx = logging.WithContext(ctx, logger)
// ---------------------------------------------------------------------------
// Flags
@ -48,7 +48,7 @@ func main() {
os.Exit(1)
}
masterKey, err := dcrypto.LoadSigningKeyFromFile(*flagKey)
masterKey, err := identity.LoadSigningKeyFromFile(*flagKey)
if err != nil {
logger.ErrorContext(ctx, "failed to load master key", slog.Any("error", err))
os.Exit(1)
@ -60,12 +60,12 @@ func main() {
slog.ErrorContext(ctx, "invalid host or port")
os.Exit(1)
}
addr := dnet.FromTCPAddr(tcpAddr, &masterKey.PublicKey)
addr := network.FromTCPAddr(tcpAddr, &masterKey.PublicKey)
// ---------------------------------------------------------------------------
// Listener
listener, err := dnet.Listen(ctx, masterKey, addr)
listener, err := network.Listen(ctx, masterKey, addr)
if err != nil {
logger.ErrorContext(ctx, "listener error", slog.Any("error", err))
os.Exit(1)
@ -87,7 +87,7 @@ func main() {
func handleConnection(ctx context.Context, conn net.Conn) error {
defer conn.Close()
logger := dlog.FromContext(ctx)
logger := logging.FromContext(ctx)
msg := make([]byte, 1024)
n, err := conn.Read(msg)

View File

@ -1,4 +1,4 @@
package dcrypto
package encryption
import (
"crypto/aes"

View File

@ -1,4 +1,4 @@
package dcrypto
package identity
import (
"crypto/ecdsa"

View File

@ -1,8 +1,10 @@
package dcrypto
package keyexchange
import (
"crypto/ecdh"
"crypto/hkdf"
"crypto/rand"
"crypto/sha256"
)
var (
@ -17,7 +19,17 @@ func GenerateDHKey() (*ecdh.PrivateKey, error) {
// ComputeDHSecret computes the shared secret from the private key and the public key.
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.

View File

@ -1,4 +1,4 @@
package dnet
package frame
import (
"encoding/binary"

View File

@ -1,11 +1,11 @@
package dnet_test
package frame_test
import (
"bufio"
"bytes"
"testing"
"koti.casa/numenor-labs/dsfx/shared/dnet"
"koti.casa/numenor-labs/dsfx/pkg/frame"
)
func TestLenPrefixedWriteTo(t *testing.T) {
@ -16,7 +16,7 @@ func TestLenPrefixedWriteTo(t *testing.T) {
// When ...
n, err := dnet.NewFrame(msg).WriteTo(buf)
n, err := frame.NewFrame(msg).WriteTo(buf)
// Then ...
@ -49,7 +49,7 @@ func TestLenPrefixedReadFrom(t *testing.T) {
expectedBytesRead := len(msg)
// When ...
f := dnet.NewFrame(nil)
f := frame.NewFrame(nil)
n, err := f.ReadFrom(buf)
// Then ...

View File

@ -1,4 +1,4 @@
package dnet
package handshake
import (
"bytes"
@ -11,8 +11,11 @@ import (
"log/slog"
"koti.casa/numenor-labs/dsfx/pkg/assert"
"koti.casa/numenor-labs/dsfx/shared/dcrypto"
"koti.casa/numenor-labs/dsfx/shared/dlog"
"koti.casa/numenor-labs/dsfx/pkg/crypto/encryption"
"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 (
@ -34,14 +37,14 @@ func Handshake(
lPrivKey *ecdsa.PrivateKey,
rPubKey *ecdsa.PublicKey,
) ([]byte, error) {
logger := dlog.FromContext(ctx).WithGroup("handshake")
logger := logging.FromContext(ctx).WithGroup("handshake")
// ------------------------------------------------------------------------
// Step 1: Ephemeral Key Exchange To Server
logger.DebugContext(ctx, "creating dh key")
// Create a new ECDH private key for the actor.
ourDHKey, err := dcrypto.GenerateDHKey()
ourDHKey, err := keyexchange.GenerateDHKey()
if err != nil {
return nil, err
}
@ -49,7 +52,7 @@ func Handshake(
logger.DebugContext(ctx, "exporting dh 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 {
return nil, err
}
@ -57,7 +60,7 @@ func Handshake(
// Write the actor's public key to the connection.
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 {
return nil, err
}
@ -67,7 +70,7 @@ func Handshake(
// Read the remote actor's public key from the connection.
logger.DebugContext(ctx, "waiting for server's dh key")
remoteDHKeyFrame := NewFrame(nil)
remoteDHKeyFrame := frame.NewFrame(nil)
_, err = remoteDHKeyFrame.ReadFrom(conn)
if err != nil {
return nil, err
@ -78,7 +81,7 @@ func Handshake(
// Import the remote actor's public key.
logger.DebugContext(ctx, "importing server's dh key")
remoteDHKey, err := dcrypto.ImportDHPublicKey(remoteDHKeyFrame.Contents())
remoteDHKey, err := keyexchange.ImportDHPublicKey(remoteDHKeyFrame.Contents())
if err != nil {
return nil, err
}
@ -88,13 +91,13 @@ func Handshake(
// Export the public key of the actor's signing key.
logger.DebugContext(ctx, "exporting public signing key")
ourPublicKeyRaw, err := dcrypto.ExportPublicSigningKey(&lPrivKey.PublicKey)
ourPublicKeyRaw, err := identity.ExportPublicSigningKey(&lPrivKey.PublicKey)
if err != nil {
return nil, err
}
logger.DebugContext(ctx, "exporting remote public signing key")
remotePublicKeyRaw, err := dcrypto.ExportPublicSigningKey(rPubKey)
remotePublicKeyRaw, err := identity.ExportPublicSigningKey(rPubKey)
if err != nil {
return nil, err
}
@ -114,26 +117,18 @@ func Handshake(
// Sign the message with the actor's private key.
logger.DebugContext(ctx, "signing authentication message")
signature, err := dcrypto.Sign(lPrivKey, authMessage)
signature, err := identity.Sign(lPrivKey, authMessage)
if err != nil {
return nil, err
}
// Compute the shared secret between the actor and the remote actor.
logger.DebugContext(ctx, "computing shared secret")
sharedSecret, err := dcrypto.ComputeDHSecret(ourDHKey, remoteDHKey)
derivedKey, err := keyexchange.ComputeDHSecret(ourDHKey, remoteDHKey)
if err != nil {
return nil, err
}
assert.Assert(len(sharedSecret) == 48, "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")
assert.Assert(len(derivedKey) == 32, "invalid shared secret size")
plaintext := make([]byte, 0, len(ourPublicKeyRaw)+len(signature))
plaintext = append(plaintext, ourPublicKeyRaw...)
@ -141,14 +136,14 @@ func Handshake(
// Encrypt the message with the derived key.
logger.DebugContext(ctx, "encrypting authentication message")
boxedMsg, err := dcrypto.Encrypt(derivedKey, plaintext)
boxedMsg, err := encryption.Encrypt(derivedKey, plaintext)
if err != nil {
return nil, err
}
// Write the boxed message to the connection.
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 {
return nil, err
}
@ -158,7 +153,7 @@ func Handshake(
// Read the authentication message from the connection.
logger.DebugContext(ctx, "waiting for server's authentication message")
authMessageFrame := NewFrame(nil)
authMessageFrame := frame.NewFrame(nil)
n, err := authMessageFrame.ReadFrom(conn)
if err != nil {
return nil, err
@ -167,7 +162,7 @@ func Handshake(
// Decrypt the authentication message with the derived key.
logger.DebugContext(ctx, "decrypting authentication message")
plaintext, err = dcrypto.Decrypt(derivedKey, authMessageFrame.Contents())
plaintext, err = encryption.Decrypt(derivedKey, authMessageFrame.Contents())
if err != nil {
return nil, err
}
@ -175,20 +170,20 @@ func Handshake(
// The server authentication is just verifying the signature it created of
// the client authentication message.
logger.DebugContext(ctx, "importing server's public signing key")
remotePublicKey, err := dcrypto.ImportPublicSigningKey(remotePublicKeyRaw)
remotePublicKey, err := identity.ImportPublicSigningKey(remotePublicKeyRaw)
if err != nil {
return nil, err
}
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")
}
// Finally, we need to let the server know that the handshake is complete.
logger.DebugContext(ctx, "sending handshake complete message")
handshakeCompleteMsg := []byte{0x01}
_, err = NewFrame(handshakeCompleteMsg).WriteTo(conn)
_, err = frame.NewFrame(handshakeCompleteMsg).WriteTo(conn)
if err != nil {
return nil, err
}
@ -200,14 +195,14 @@ func Handshake(
// AcceptHandshake accepts a handshake from the given actor and connection. It
// 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) {
logger := dlog.FromContext(ctx).WithGroup("handshake")
logger := logging.FromContext(ctx).WithGroup("handshake")
// ------------------------------------------------------------------------
// Step 1: Ephemeral Key Exchange From Client
// Read the remote actor's public key from the connection.
logger.DebugContext(ctx, "waiting for client's dh key")
remoteDHKeyFrame := NewFrame(nil)
remoteDHKeyFrame := frame.NewFrame(nil)
_, err := remoteDHKeyFrame.ReadFrom(conn)
if err != nil {
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.
logger.DebugContext(ctx, "importing client's dh key")
remoteDHKey, err := dcrypto.ImportDHPublicKey(remoteDHKeyFrame.Contents())
remoteDHKey, err := keyexchange.ImportDHPublicKey(remoteDHKeyFrame.Contents())
if err != nil {
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.
logger.DebugContext(ctx, "creating dh key")
ourDHKey, err := dcrypto.GenerateDHKey()
ourDHKey, err := keyexchange.GenerateDHKey()
if err != nil {
return nil, nil, err
}
// Export the public key of the actor's ECDH private key.
logger.DebugContext(ctx, "exporting dh key")
ourDHKeyRaw, err := dcrypto.ExportDHPublicKey(ourDHKey.PublicKey())
ourDHKeyRaw, err := keyexchange.ExportDHPublicKey(ourDHKey.PublicKey())
if err != nil {
return nil, nil, err
}
// Write the actor's public key to the connection.
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 {
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.
logger.DebugContext(ctx, "waiting for client's authentication message")
authMessageFrame := NewFrame(nil)
authMessageFrame := frame.NewFrame(nil)
n, err := authMessageFrame.ReadFrom(conn)
if err != nil {
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.
logger.DebugContext(ctx, "computing shared secret")
sharedSecret, err := dcrypto.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)
derivedKey, err := keyexchange.ComputeDHSecret(ourDHKey, remoteDHKey)
if err != nil {
return nil, nil, err
}
logger.DebugContext(ctx, "decrypting authentication message")
plaintext, err := dcrypto.Decrypt(derivedKey, authMessageFrame.Contents())
plaintext, err := encryption.Decrypt(derivedKey, authMessageFrame.Contents())
if err != nil {
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.
logger.DebugContext(ctx, "importing client's public signing key")
clientPublicKey, err := dcrypto.ImportPublicSigningKey(clientPublicKeyRaw)
clientPublicKey, err := identity.ImportPublicSigningKey(clientPublicKeyRaw)
if err != nil {
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")
if !dcrypto.Verify(clientPublicKey, authMessage, signature) {
if !identity.Verify(clientPublicKey, authMessage, 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
// the server to the client.
logger.DebugContext(ctx, "signing authentication message")
serverSignature, err := dcrypto.Sign(lPrivKey, authMessage)
serverSignature, err := identity.Sign(lPrivKey, authMessage)
if err != nil {
return nil, nil, err
}
logger.DebugContext(ctx, "encrypting server's signature")
boxedMsg, err := dcrypto.Encrypt(derivedKey, serverSignature)
boxedMsg, err := encryption.Encrypt(derivedKey, serverSignature)
if err != nil {
return nil, nil, err
}
// Send the server's signature back to the client.
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 {
return nil, nil, err
}
logger.DebugContext(ctx, "waiting for handshake complete message")
// Read the handshake complete message from the client.
handshakeCompleteFrame := NewFrame(nil)
handshakeCompleteFrame := frame.NewFrame(nil)
_, err = handshakeCompleteFrame.ReadFrom(conn)
if err != nil {
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) {
clientPubKeyRaw, err := dcrypto.ExportDHPublicKey(clientPubKey)
clientPubKeyRaw, err := keyexchange.ExportDHPublicKey(clientPubKey)
if err != nil {
return nil, err
}
serverPubKeyRaw, err := dcrypto.ExportDHPublicKey(serverPubKey)
serverPubKeyRaw, err := keyexchange.ExportDHPublicKey(serverPubKey)
if err != nil {
return nil, err
}

View File

@ -1,4 +1,4 @@
package dnet_test
package handshake_test
import (
"bytes"
@ -10,17 +10,17 @@ import (
"sync"
"testing"
"koti.casa/numenor-labs/dsfx/shared/dcrypto"
"koti.casa/numenor-labs/dsfx/shared/dnet"
"koti.casa/numenor-labs/dsfx/pkg/crypto/identity"
"koti.casa/numenor-labs/dsfx/pkg/handshake"
)
func TestHandshake(t *testing.T) {
ctx := context.Background()
// alice, represented by an ecdsa key pair.
alice, _ := dcrypto.GenerateSigningKey()
alice, _ := identity.GenerateSigningKey()
// bob, also represented by an ecdsa key pair.
bob, _ := dcrypto.GenerateSigningKey()
bob, _ := identity.GenerateSigningKey()
var (
// the secret that alice should arrive at on her own
@ -47,11 +47,11 @@ func TestHandshake(t *testing.T) {
var wg sync.WaitGroup
wg.Add(2)
go func() {
aliceSecret, aliceErr = dnet.Handshake(ctx, client, alice, &bob.PublicKey)
aliceSecret, aliceErr = handshake.Handshake(ctx, client, alice, &bob.PublicKey)
wg.Done()
}()
go func() {
discoveredAlicePublicKey, bobSecret, bobErr = dnet.AcceptHandshake(ctx, server, bob)
discoveredAlicePublicKey, bobSecret, bobErr = handshake.AcceptHandshake(ctx, server, bob)
wg.Done()
}()
wg.Wait()
@ -94,9 +94,9 @@ func runSimulation() error {
ctx := context.Background()
// alice, represented by an ecdsa key pair.
alice, _ := dcrypto.GenerateSigningKey()
alice, _ := identity.GenerateSigningKey()
// bob, also represented by an ecdsa key pair.
bob, _ := dcrypto.GenerateSigningKey()
bob, _ := identity.GenerateSigningKey()
var (
// the secret that alice should arrive at on her own
@ -123,11 +123,11 @@ func runSimulation() error {
var wg sync.WaitGroup
wg.Add(2)
go func() {
_, aliceErr = dnet.Handshake(ctx, client, alice, &bob.PublicKey)
_, aliceErr = handshake.Handshake(ctx, client, alice, &bob.PublicKey)
wg.Done()
}()
go func() {
_, _, bobErr = dnet.AcceptHandshake(ctx, server, bob)
_, _, bobErr = handshake.AcceptHandshake(ctx, server, bob)
wg.Done()
}()
wg.Wait()

View File

@ -1,4 +1,4 @@
package dlog
package logging
import (
"context"

View File

@ -1,4 +1,4 @@
package dnet
package network
import (
"crypto/ecdsa"
@ -8,7 +8,7 @@ import (
"net"
"strings"
"koti.casa/numenor-labs/dsfx/shared/dcrypto"
"koti.casa/numenor-labs/dsfx/pkg/crypto/identity"
)
var (
@ -60,7 +60,7 @@ func ParseAddr(addrRaw string) (*Addr, error) {
return nil, ErrInvalidFormat
}
publicKey, err := dcrypto.ImportPublicSigningKey(publicKeyBytes)
publicKey, err := identity.ImportPublicSigningKey(publicKeyBytes)
if err != nil {
return nil, ErrInvalidFormat
}
@ -86,7 +86,7 @@ func (a *Addr) Network() string {
// String implements net.Addr.
func (a *Addr) String() string {
exported, _ := dcrypto.ExportPublicSigningKey(a.publicKey)
exported, _ := identity.ExportPublicSigningKey(a.publicKey)
exportedBase64 := base64.StdEncoding.EncodeToString(exported)
return fmt.Sprintf("%s://%s:%d#%s", a.network, a.ip, a.port, exportedBase64)
}

View File

@ -1,11 +1,12 @@
package dnet
package network
import (
"crypto/ecdsa"
"net"
"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
@ -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
// should not rely on this number as an indication of network metrics.
func (c *Conn) Read(b []byte) (int, error) {
f := NewFrame(nil)
f := frame.NewFrame(nil)
_, err := f.ReadFrom(c.conn)
if err != nil {
return 0, err
}
plaintext, err := dcrypto.Decrypt(c.sessionKey, f.Contents())
plaintext, err := encryption.Decrypt(c.sessionKey, f.Contents())
if err != nil {
return 0, err
}
@ -42,11 +43,11 @@ func (c *Conn) Read(b []byte) (int, error) {
// Write implements io.Writer.
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 {
return 0, err
}
_, err = NewFrame(ciphertext).WriteTo(c.conn)
_, err = frame.NewFrame(ciphertext).WriteTo(c.conn)
if err != nil {
return 0, err
}

View File

@ -1,10 +1,12 @@
package dnet
package network
import (
"context"
"crypto/ecdsa"
"log/slog"
"net"
"koti.casa/numenor-labs/dsfx/pkg/handshake"
)
// Listener ...
@ -23,7 +25,7 @@ func (l *Listener) Accept() (net.Conn, error) {
return nil, err
}
clientIdentity, sessionKey, err := AcceptHandshake(ctx, conn, l.identity)
clientIdentity, sessionKey, err := handshake.AcceptHandshake(ctx, conn, l.identity)
if err != nil {
return nil, err
}

View File

@ -1,11 +1,12 @@
package dnet
package network
import (
"context"
"crypto/ecdsa"
"net"
"koti.casa/numenor-labs/dsfx/shared/dlog"
"koti.casa/numenor-labs/dsfx/pkg/handshake"
"koti.casa/numenor-labs/dsfx/pkg/logging"
)
// Dial ...
@ -20,7 +21,7 @@ func Dial(
return nil, err
}
sessionKey, err := Handshake(ctx, conn, identity, raddr.PublicKey())
sessionKey, err := handshake.Handshake(ctx, conn, identity, raddr.PublicKey())
if err != nil {
return nil, err
}
@ -39,7 +40,7 @@ func Listen(
return nil, err
}
logger := dlog.FromContext(ctx)
logger := logging.FromContext(ctx)
return &Listener{logger, tcpListener, identity}, nil
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -6,11 +6,11 @@ import (
"fmt"
"os"
"koti.casa/numenor-labs/dsfx/shared/dcrypto"
"koti.casa/numenor-labs/dsfx/pkg/crypto/identity"
)
func main() {
key, err := dcrypto.GenerateSigningKey()
key, err := identity.GenerateSigningKey()
if err != nil {
panic(err)
}