117 lines
2.3 KiB
Go
117 lines
2.3 KiB
Go
package peer
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"log"
|
|
"net/netip"
|
|
"sync/atomic"
|
|
|
|
"golang.org/x/crypto/nacl/box"
|
|
"golang.org/x/crypto/nacl/sign"
|
|
)
|
|
|
|
type cryptoKeys struct {
|
|
PubKey []byte
|
|
PrivKey []byte
|
|
PubSignKey []byte
|
|
PrivSignKey []byte
|
|
}
|
|
|
|
func generateKeys() cryptoKeys {
|
|
pubKey, privKey, err := box.GenerateKey(rand.Reader)
|
|
if err != nil {
|
|
log.Fatalf("Failed to generate encryption keys: %v", err)
|
|
}
|
|
|
|
pubSignKey, privSignKey, err := sign.GenerateKey(rand.Reader)
|
|
if err != nil {
|
|
log.Fatalf("Failed to generate signing keys: %v", err)
|
|
}
|
|
|
|
return cryptoKeys{pubKey[:], privKey[:], pubSignKey[:], privSignKey[:]}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Peer must have a ControlCipher.
|
|
func encryptControlPacket(
|
|
localIP byte,
|
|
peer *RemotePeer,
|
|
pkt marshaller,
|
|
tmp []byte,
|
|
out []byte,
|
|
) []byte {
|
|
h := header{
|
|
StreamID: controlStreamID,
|
|
Counter: atomic.AddUint64(peer.Counter, 1),
|
|
SourceIP: localIP,
|
|
DestIP: peer.IP,
|
|
}
|
|
tmp = pkt.Marshal(tmp)
|
|
return peer.ControlCipher.Encrypt(h, tmp, out)
|
|
}
|
|
|
|
// Returns a controlMsg[PacketType]. Peer must have a non-nil ControlCipher.
|
|
//
|
|
// This function also drops packets with duplicate sequence numbers.
|
|
func decryptControlPacket(
|
|
peer *RemotePeer,
|
|
fromAddr netip.AddrPort,
|
|
h header,
|
|
encrypted []byte,
|
|
tmp []byte,
|
|
) (any, error) {
|
|
out, ok := peer.ControlCipher.Decrypt(encrypted, tmp)
|
|
if !ok {
|
|
return nil, errDecryptionFailed
|
|
}
|
|
|
|
if peer.DupCheck.IsDup(h.Counter) {
|
|
return nil, errDuplicateSeqNum
|
|
}
|
|
|
|
msg, err := parseControlMsg(h.SourceIP, fromAddr, out)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return msg, nil
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
func encryptDataPacket(
|
|
localIP byte,
|
|
destIP byte,
|
|
peer *RemotePeer,
|
|
data []byte,
|
|
out []byte,
|
|
) []byte {
|
|
h := header{
|
|
StreamID: dataStreamID,
|
|
Counter: atomic.AddUint64(peer.Counter, 1),
|
|
SourceIP: localIP,
|
|
DestIP: destIP,
|
|
}
|
|
return peer.DataCipher.Encrypt(h, data, out)
|
|
}
|
|
|
|
// Decrypts and de-dups incoming data packets.
|
|
func decryptDataPacket(
|
|
peer *RemotePeer,
|
|
h header,
|
|
encrypted []byte,
|
|
out []byte,
|
|
) ([]byte, error) {
|
|
dec, ok := peer.DataCipher.Decrypt(encrypted, out)
|
|
if !ok {
|
|
return nil, errDecryptionFailed
|
|
}
|
|
|
|
if peer.DupCheck.IsDup(h.Counter) {
|
|
return nil, errDuplicateSeqNum
|
|
}
|
|
|
|
return dec, nil
|
|
}
|