diff --git a/disco/types.go b/disco/types.go index 3ed158f..c0de4ba 100644 --- a/disco/types.go +++ b/disco/types.go @@ -171,8 +171,8 @@ type Datagram struct { Data []byte } -func (d *Datagram) TryDecrypt(aesCBC *secure.AESCBC) []byte { - b, err := aesCBC.Decrypt(d.Data, d.PeerID) +func (d *Datagram) TryDecrypt(symmAlgo secure.SymmAlgo) []byte { + b, err := symmAlgo.Decrypt(d.Data, d.PeerID.String()) if err != nil { slog.Debug("Datagram decrypt error", "err", err) return d.Data @@ -180,8 +180,8 @@ func (d *Datagram) TryDecrypt(aesCBC *secure.AESCBC) []byte { return b } -func (d *Datagram) TryEncrypt(aesCBC *secure.AESCBC) []byte { - b, err := aesCBC.Encrypt(d.Data, d.PeerID) +func (d *Datagram) TryEncrypt(symmAlgo secure.SymmAlgo) []byte { + b, err := symmAlgo.Encrypt(d.Data, d.PeerID.String()) if err != nil { slog.Debug("Datagram encrypt error", "err", err) return d.Data diff --git a/p2p/config.go b/p2p/config.go index 7948fc8..c6fd4aa 100644 --- a/p2p/config.go +++ b/p2p/config.go @@ -6,6 +6,7 @@ import ( "github.com/rkonfj/peerguard/peer" "github.com/rkonfj/peerguard/secure" + "github.com/rkonfj/peerguard/secure/aescbc" ) type Config struct { @@ -13,7 +14,7 @@ type Config struct { PeerID peer.PeerID DisableIPv6 bool DisableIPv4 bool - AES *secure.AESCBC + SymmAlgo secure.SymmAlgo Metadata peer.Metadata OnPeer OnPeer KeepAlivePeriod time.Duration @@ -35,7 +36,7 @@ func ListenUDPPort(port int) Option { func ListenPeerID(id string) Option { return func(cfg *Config) error { - if cfg.AES != nil { + if cfg.SymmAlgo != nil { return errors.New("options ListenPeerID and ListenPeerSecure/Curve25519 conflict") } peerID := peer.PeerID(id) @@ -48,14 +49,14 @@ func ListenPeerID(id string) Option { func ListenPeerSecure() Option { return func(cfg *Config) error { - if cfg.AES != nil { + if cfg.SymmAlgo != nil { return errors.New("repeat secure options") } priv, err := secure.GenerateCurve25519() if err != nil { return err } - cfg.AES = secure.NewAESCBC(priv) + cfg.SymmAlgo = aescbc.NewAESCBC(priv.SharedKey) cfg.PeerID = peer.PeerID(priv.PublicKey.String()) return nil } @@ -63,14 +64,14 @@ func ListenPeerSecure() Option { func ListenPeerCurve25519(privateKey string) Option { return func(cfg *Config) error { - if cfg.AES != nil { + if cfg.SymmAlgo != nil { return errors.New("repeat secure options") } priv, err := secure.Curve25519PrivateKey(privateKey) if err != nil { return err } - cfg.AES = secure.NewAESCBC(priv) + cfg.SymmAlgo = aescbc.NewAESCBC(priv.SharedKey) cfg.PeerID = peer.PeerID(priv.PublicKey.String()) return nil } diff --git a/p2p/conn.go b/p2p/conn.go index 728fe10..d460822 100644 --- a/p2p/conn.go +++ b/p2p/conn.go @@ -54,11 +54,11 @@ func (c *PeerPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { return case datagram := <-c.wsConn.Datagrams(): addr = datagram.PeerID - n = copy(p, datagram.TryDecrypt(c.cfg.AES)) + n = copy(p, datagram.TryDecrypt(c.cfg.SymmAlgo)) return case datagram := <-c.udpConn.Datagrams(): addr = datagram.PeerID - n = copy(p, datagram.TryDecrypt(c.cfg.AES)) + n = copy(p, datagram.TryDecrypt(c.cfg.SymmAlgo)) return } } @@ -73,7 +73,7 @@ func (c *PeerPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { } datagram := disco.Datagram{PeerID: addr.(peer.PeerID), Data: p} - p = datagram.TryEncrypt(c.cfg.AES) + p = datagram.TryEncrypt(c.cfg.SymmAlgo) n, err = c.udpConn.WriteToUDP(p, datagram.PeerID) if err != nil { diff --git a/peermap/auth/auth.go b/peermap/auth/auth.go index c0d5633..c4ef892 100644 --- a/peermap/auth/auth.go +++ b/peermap/auth/auth.go @@ -7,7 +7,7 @@ import ( "errors" "time" - "github.com/rkonfj/peerguard/secure" + "github.com/rkonfj/peerguard/secure/aescbc" ) var ( @@ -42,7 +42,7 @@ func (auth *authenticator) GenerateSecret(networkID string, validDuration time.D if err != nil { return "", err } - chiperData, err := secure.AESCBCEncrypt(auth.key, b) + chiperData, err := aescbc.Encrypt(auth.key, b) return base64.URLEncoding.EncodeToString(chiperData), err } @@ -51,7 +51,7 @@ func (auth *authenticator) ParseSecret(networkIDChiper string) (JSONSecret, erro if err != nil { return JSONSecret{}, ErrInvalidToken } - plainData, err := secure.AESCBCDecrypt(auth.key, chiperData) + plainData, err := aescbc.Decrypt(auth.key, chiperData) if err != nil { return JSONSecret{}, ErrInvalidToken } diff --git a/secure/aes.go b/secure/aescbc/aescbc.go similarity index 74% rename from secure/aes.go rename to secure/aescbc/aescbc.go index 006841b..f84df69 100644 --- a/secure/aes.go +++ b/secure/aescbc/aescbc.go @@ -1,4 +1,4 @@ -package secure +package aescbc import ( "bytes" @@ -11,7 +11,7 @@ import ( "sync" "github.com/rkonfj/peerguard/lru" - "github.com/rkonfj/peerguard/peer" + "github.com/rkonfj/peerguard/secure" ) func PKCS7Padding(data []byte, blockSize int) []byte { @@ -35,7 +35,7 @@ func PKCS7UnPadding(data []byte) ([]byte, error) { return data[:len(data)-int(padding)], nil } -func AESCBCEncrypt(key, data []byte) ([]byte, error) { +func Encrypt(key, data []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err @@ -55,7 +55,7 @@ func AESCBCEncrypt(key, data []byte) ([]byte, error) { return cipherText, nil } -func AESCBCDecrypt(key, data []byte) ([]byte, error) { +func Decrypt(key, data []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err @@ -74,24 +74,26 @@ func AESCBCDecrypt(key, data []byte) ([]byte, error) { return PKCS7UnPadding(data) } +var _ secure.SymmAlgo = (*AESCBC)(nil) + type AESCBC struct { - mut sync.RWMutex - cipher *lru.Cache[peer.PeerID, cipher.Block] - priv *PrivateKey + mut sync.RWMutex + cipher *lru.Cache[string, cipher.Block] + provideSecretKey secure.ProvideSecretKey } -func NewAESCBC(priv *PrivateKey) *AESCBC { +func NewAESCBC(provideSecretKey secure.ProvideSecretKey) *AESCBC { return &AESCBC{ - cipher: lru.New[peer.PeerID, cipher.Block](128), - priv: priv, + cipher: lru.New[string, cipher.Block](128), + provideSecretKey: provideSecretKey, } } -func (s *AESCBC) Encrypt(b []byte, peerID peer.PeerID) ([]byte, error) { +func (s *AESCBC) Encrypt(b []byte, pubKey string) ([]byte, error) { if s == nil { return nil, errors.New("aesCBC is nil") } - block, err := s.ensureChiperBlock(peerID) + block, err := s.ensureChiperBlock(pubKey) if err != nil { return nil, err } @@ -108,11 +110,11 @@ func (s *AESCBC) Encrypt(b []byte, peerID peer.PeerID) ([]byte, error) { return cipherText, nil } -func (s *AESCBC) Decrypt(b []byte, peerID peer.PeerID) ([]byte, error) { +func (s *AESCBC) Decrypt(b []byte, pubKey string) ([]byte, error) { if s == nil { return nil, errors.New("aesCBC is nil") } - block, err := s.ensureChiperBlock(peerID) + block, err := s.ensureChiperBlock(pubKey) if err != nil { return nil, err } @@ -129,12 +131,12 @@ func (s *AESCBC) Decrypt(b []byte, peerID peer.PeerID) ([]byte, error) { return PKCS7UnPadding(plainBytes) } -func (s *AESCBC) ensureChiperBlock(peerID peer.PeerID) (cipher.Block, error) { +func (s *AESCBC) ensureChiperBlock(pubKey string) (cipher.Block, error) { s.mut.RLock() - block, ok := s.cipher.Get(peerID) + block, ok := s.cipher.Get(pubKey) s.mut.RUnlock() if !ok { - secretKey, err := s.priv.SharedKey(peerID.String()) + secretKey, err := s.provideSecretKey(pubKey) if err != nil { return nil, err } @@ -144,7 +146,7 @@ func (s *AESCBC) ensureChiperBlock(peerID peer.PeerID) (cipher.Block, error) { } block = b s.mut.Lock() - s.cipher.Put(peerID, block) + s.cipher.Put(pubKey, block) s.mut.Unlock() } diff --git a/secure/symm_algo.go b/secure/symm_algo.go new file mode 100644 index 0000000..987a093 --- /dev/null +++ b/secure/symm_algo.go @@ -0,0 +1,8 @@ +package secure + +type ProvideSecretKey func(pubKey string) ([]byte, error) + +type SymmAlgo interface { + Encrypt(data []byte, pubKey string) ([]byte, error) + Decrypt(data []byte, pubKey string) ([]byte, error) +}