mirror of
https://github.com/sigcn/pg.git
synced 2025-10-25 00:00:34 +08:00
abstract symmetric encryption algorithm
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
8
secure/symm_algo.go
Normal 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)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user