aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--handshake.go79
2 files changed, 56 insertions, 24 deletions
diff --git a/.gitignore b/.gitignore
index 38bf9c6..3b96afd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
/hose
acme.dump
+.plan
diff --git a/handshake.go b/handshake.go
index d26d62a..c12d8e7 100644
--- a/handshake.go
+++ b/handshake.go
@@ -3,10 +3,12 @@ package main
import (
"bufio"
"context"
+ "errors"
"fmt"
"golang.org/x/sync/errgroup"
"io"
"net"
+ "net/netip"
"os"
"slices"
"strings"
@@ -22,6 +24,15 @@ const (
retryInterval = 500 * time.Millisecond
)
+var errHostKey = errors.New("host key verification failed")
+
+type keyType string
+
+const (
+ boxPublicKey keyType = "Public encryption key"
+ sigPublicKey = "Public signature verification key"
+)
+
// handshake exchanges public keys with a remote host.
// The user is asked to verify the received key
// before it is saved in the known hosts file.
@@ -54,10 +65,10 @@ func handshake(rhost string) error {
}
}
-// handshakeSend sends the local public key to a remote host.
+// handshakeSend sends the local public box (encryption) key to a remote host.
func handshakeSend(rhost string) error {
- util.Logf("loading public key...")
- pubkey, err := key.LoadPublicKey()
+ util.Logf("loading public encryption key...")
+ pubBoxkey, err := key.LoadBoxPublicKey()
if err != nil {
return err
}
@@ -71,11 +82,11 @@ func handshakeSend(rhost string) error {
defer conn.Close()
util.Logf("connected to %s", raddr)
- if _, err := conn.Write(pubkey[:]); err != nil {
+ if _, err := conn.Write(pubBoxkey[:]); err != nil {
return err
}
- util.Logf("sent public key to %s", rhost)
+ util.Logf("sent public encryption key to %s", rhost)
return nil
}
@@ -115,38 +126,58 @@ func handshakeRecv(rhost string) error {
defer conn.Close()
util.Logf("accepted connection from %s", conn.RemoteAddr())
- // Receive public key from remote host.
- var rpubkey [32]byte
- _, err = io.ReadFull(conn, rpubkey[:])
+ // Receive public box (encryption) key from remote host.
+ var rBoxPubKey key.BoxPublicKey
+ _, err = io.ReadFull(conn, rBoxPubKey[:])
if err != nil {
return err
}
- util.Logf("received public key from %s", conn.RemoteAddr())
+ util.Logf("received public encryption key from %s", conn.RemoteAddr())
- // Ask user to verify the key.
- ok, err := verifyPublicKey(conn.RemoteAddr(), rpubkey)
+ // Receive public signature verification key from remote host.
+ var rSigPubKey key.SigPublicKey
+ _, err = io.ReadFull(conn, rSigPubKey[:])
if err != nil {
return err
}
- if !ok {
- // User rejected the key.
- return fmt.Errorf("host key verification failed")
- }
+ util.Logf("receive public signature verification key from %s", conn.RemoteAddr())
- return hosts.Set(conn.RemoteAddr(), rpubkey)
-}
+ // Ask user to verify the keys.
+ host, _, err := net.SplitHostPort(conn.RemoteAddr().String())
+ if err != nil {
+ return err
+ }
+ // Verify box key.
+ ok, err := verifyKey(host, rBoxPubKey[:], boxPublicKey)
+ if err != nil {
+ return err
+ }
+ if !ok { // user rejected the key.
+ return errHostKey
+ }
+ // Verify signature verification key.
+ ok, err = verifyKey(host, rSigPubKey[:], sigPublicKey)
+ if err != nil {
+ return err
+ }
+ if !ok { // user rejected the key.
+ return errHostKey
+ }
-// verifyPublicKey asks the user to verify the public key of a remote host.
-// It returns true if the user accepts the key, or false if they don't, or a non-nil error.
-func verifyPublicKey(addr net.Addr, pubkey [32]byte) (bool, error) {
- host, _, err := net.SplitHostPort(addr.String())
+ // Save in known hosts file.
+ rAddr, err := netip.ParseAddr(conn.RemoteAddr().String())
if err != nil {
- return false, err
+ return err
}
+ return hosts.Add(hosts.Host{rAddr, rBoxPubKey, rSigPubKey})
+}
+// verifyKey asks the user to verify a key received from a remote host.
+// It returns true if the user accepts the key, or false if they don't, or a non-nil error.
+func verifyKey(host string, key []byte, kt keyType) (bool, error) {
// Ask host to verify the key.
- util.Logf("Public key of host %q: %x\nIs this the correct key (yes/[no])?",
- host, pubkey[:])
+ util.Logf("%s key of host %q: %x\nIs this the correct key (yes/[no])?",
+ kt, host, key[:])
response, err := scan([]string{"yes", "no", ""})
if err != nil {
return false, err