abstract symmetric encryption algorithm

This commit is contained in:
rkonfj
2024-03-10 14:37:33 +08:00
parent 3b40717cbf
commit f04f14d6d2
6 changed files with 45 additions and 34 deletions

View File

@@ -171,8 +171,8 @@ type Datagram struct {
Data []byte Data []byte
} }
func (d *Datagram) TryDecrypt(aesCBC *secure.AESCBC) []byte { func (d *Datagram) TryDecrypt(symmAlgo secure.SymmAlgo) []byte {
b, err := aesCBC.Decrypt(d.Data, d.PeerID) b, err := symmAlgo.Decrypt(d.Data, d.PeerID.String())
if err != nil { if err != nil {
slog.Debug("Datagram decrypt error", "err", err) slog.Debug("Datagram decrypt error", "err", err)
return d.Data return d.Data
@@ -180,8 +180,8 @@ func (d *Datagram) TryDecrypt(aesCBC *secure.AESCBC) []byte {
return b return b
} }
func (d *Datagram) TryEncrypt(aesCBC *secure.AESCBC) []byte { func (d *Datagram) TryEncrypt(symmAlgo secure.SymmAlgo) []byte {
b, err := aesCBC.Encrypt(d.Data, d.PeerID) b, err := symmAlgo.Encrypt(d.Data, d.PeerID.String())
if err != nil { if err != nil {
slog.Debug("Datagram encrypt error", "err", err) slog.Debug("Datagram encrypt error", "err", err)
return d.Data return d.Data

View File

@@ -6,6 +6,7 @@ import (
"github.com/rkonfj/peerguard/peer" "github.com/rkonfj/peerguard/peer"
"github.com/rkonfj/peerguard/secure" "github.com/rkonfj/peerguard/secure"
"github.com/rkonfj/peerguard/secure/aescbc"
) )
type Config struct { type Config struct {
@@ -13,7 +14,7 @@ type Config struct {
PeerID peer.PeerID PeerID peer.PeerID
DisableIPv6 bool DisableIPv6 bool
DisableIPv4 bool DisableIPv4 bool
AES *secure.AESCBC SymmAlgo secure.SymmAlgo
Metadata peer.Metadata Metadata peer.Metadata
OnPeer OnPeer OnPeer OnPeer
KeepAlivePeriod time.Duration KeepAlivePeriod time.Duration
@@ -35,7 +36,7 @@ func ListenUDPPort(port int) Option {
func ListenPeerID(id string) Option { func ListenPeerID(id string) Option {
return func(cfg *Config) error { return func(cfg *Config) error {
if cfg.AES != nil { if cfg.SymmAlgo != nil {
return errors.New("options ListenPeerID and ListenPeerSecure/Curve25519 conflict") return errors.New("options ListenPeerID and ListenPeerSecure/Curve25519 conflict")
} }
peerID := peer.PeerID(id) peerID := peer.PeerID(id)
@@ -48,14 +49,14 @@ func ListenPeerID(id string) Option {
func ListenPeerSecure() Option { func ListenPeerSecure() Option {
return func(cfg *Config) error { return func(cfg *Config) error {
if cfg.AES != nil { if cfg.SymmAlgo != nil {
return errors.New("repeat secure options") return errors.New("repeat secure options")
} }
priv, err := secure.GenerateCurve25519() priv, err := secure.GenerateCurve25519()
if err != nil { if err != nil {
return err return err
} }
cfg.AES = secure.NewAESCBC(priv) cfg.SymmAlgo = aescbc.NewAESCBC(priv.SharedKey)
cfg.PeerID = peer.PeerID(priv.PublicKey.String()) cfg.PeerID = peer.PeerID(priv.PublicKey.String())
return nil return nil
} }
@@ -63,14 +64,14 @@ func ListenPeerSecure() Option {
func ListenPeerCurve25519(privateKey string) Option { func ListenPeerCurve25519(privateKey string) Option {
return func(cfg *Config) error { return func(cfg *Config) error {
if cfg.AES != nil { if cfg.SymmAlgo != nil {
return errors.New("repeat secure options") return errors.New("repeat secure options")
} }
priv, err := secure.Curve25519PrivateKey(privateKey) priv, err := secure.Curve25519PrivateKey(privateKey)
if err != nil { if err != nil {
return err return err
} }
cfg.AES = secure.NewAESCBC(priv) cfg.SymmAlgo = aescbc.NewAESCBC(priv.SharedKey)
cfg.PeerID = peer.PeerID(priv.PublicKey.String()) cfg.PeerID = peer.PeerID(priv.PublicKey.String())
return nil return nil
} }

View File

@@ -54,11 +54,11 @@ func (c *PeerPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
return return
case datagram := <-c.wsConn.Datagrams(): case datagram := <-c.wsConn.Datagrams():
addr = datagram.PeerID addr = datagram.PeerID
n = copy(p, datagram.TryDecrypt(c.cfg.AES)) n = copy(p, datagram.TryDecrypt(c.cfg.SymmAlgo))
return return
case datagram := <-c.udpConn.Datagrams(): case datagram := <-c.udpConn.Datagrams():
addr = datagram.PeerID addr = datagram.PeerID
n = copy(p, datagram.TryDecrypt(c.cfg.AES)) n = copy(p, datagram.TryDecrypt(c.cfg.SymmAlgo))
return 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} 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) n, err = c.udpConn.WriteToUDP(p, datagram.PeerID)
if err != nil { if err != nil {

View File

@@ -7,7 +7,7 @@ import (
"errors" "errors"
"time" "time"
"github.com/rkonfj/peerguard/secure" "github.com/rkonfj/peerguard/secure/aescbc"
) )
var ( var (
@@ -42,7 +42,7 @@ func (auth *authenticator) GenerateSecret(networkID string, validDuration time.D
if err != nil { if err != nil {
return "", err return "", err
} }
chiperData, err := secure.AESCBCEncrypt(auth.key, b) chiperData, err := aescbc.Encrypt(auth.key, b)
return base64.URLEncoding.EncodeToString(chiperData), err return base64.URLEncoding.EncodeToString(chiperData), err
} }
@@ -51,7 +51,7 @@ func (auth *authenticator) ParseSecret(networkIDChiper string) (JSONSecret, erro
if err != nil { if err != nil {
return JSONSecret{}, ErrInvalidToken return JSONSecret{}, ErrInvalidToken
} }
plainData, err := secure.AESCBCDecrypt(auth.key, chiperData) plainData, err := aescbc.Decrypt(auth.key, chiperData)
if err != nil { if err != nil {
return JSONSecret{}, ErrInvalidToken return JSONSecret{}, ErrInvalidToken
} }

View File

@@ -1,4 +1,4 @@
package secure package aescbc
import ( import (
"bytes" "bytes"
@@ -11,7 +11,7 @@ import (
"sync" "sync"
"github.com/rkonfj/peerguard/lru" "github.com/rkonfj/peerguard/lru"
"github.com/rkonfj/peerguard/peer" "github.com/rkonfj/peerguard/secure"
) )
func PKCS7Padding(data []byte, blockSize int) []byte { func PKCS7Padding(data []byte, blockSize int) []byte {
@@ -35,7 +35,7 @@ func PKCS7UnPadding(data []byte) ([]byte, error) {
return data[:len(data)-int(padding)], nil 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) block, err := aes.NewCipher(key)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -55,7 +55,7 @@ func AESCBCEncrypt(key, data []byte) ([]byte, error) {
return cipherText, nil return cipherText, nil
} }
func AESCBCDecrypt(key, data []byte) ([]byte, error) { func Decrypt(key, data []byte) ([]byte, error) {
block, err := aes.NewCipher(key) block, err := aes.NewCipher(key)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -74,24 +74,26 @@ func AESCBCDecrypt(key, data []byte) ([]byte, error) {
return PKCS7UnPadding(data) return PKCS7UnPadding(data)
} }
var _ secure.SymmAlgo = (*AESCBC)(nil)
type AESCBC struct { type AESCBC struct {
mut sync.RWMutex mut sync.RWMutex
cipher *lru.Cache[peer.PeerID, cipher.Block] cipher *lru.Cache[string, cipher.Block]
priv *PrivateKey provideSecretKey secure.ProvideSecretKey
} }
func NewAESCBC(priv *PrivateKey) *AESCBC { func NewAESCBC(provideSecretKey secure.ProvideSecretKey) *AESCBC {
return &AESCBC{ return &AESCBC{
cipher: lru.New[peer.PeerID, cipher.Block](128), cipher: lru.New[string, cipher.Block](128),
priv: priv, 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 { if s == nil {
return nil, errors.New("aesCBC is nil") return nil, errors.New("aesCBC is nil")
} }
block, err := s.ensureChiperBlock(peerID) block, err := s.ensureChiperBlock(pubKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -108,11 +110,11 @@ func (s *AESCBC) Encrypt(b []byte, peerID peer.PeerID) ([]byte, error) {
return cipherText, nil 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 { if s == nil {
return nil, errors.New("aesCBC is nil") return nil, errors.New("aesCBC is nil")
} }
block, err := s.ensureChiperBlock(peerID) block, err := s.ensureChiperBlock(pubKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -129,12 +131,12 @@ func (s *AESCBC) Decrypt(b []byte, peerID peer.PeerID) ([]byte, error) {
return PKCS7UnPadding(plainBytes) 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() s.mut.RLock()
block, ok := s.cipher.Get(peerID) block, ok := s.cipher.Get(pubKey)
s.mut.RUnlock() s.mut.RUnlock()
if !ok { if !ok {
secretKey, err := s.priv.SharedKey(peerID.String()) secretKey, err := s.provideSecretKey(pubKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -144,7 +146,7 @@ func (s *AESCBC) ensureChiperBlock(peerID peer.PeerID) (cipher.Block, error) {
} }
block = b block = b
s.mut.Lock() s.mut.Lock()
s.cipher.Put(peerID, block) s.cipher.Put(pubKey, block)
s.mut.Unlock() s.mut.Unlock()
} }

8
secure/symm_algo.go Normal file
View File

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