Files
Singbox-For-SBPanel/protocol/sbproxy/encryption.go
2026-04-21 21:11:20 +08:00

60 lines
1.3 KiB
Go

package sbproxy
import (
"crypto/aes"
"crypto/cipher"
"crypto/sha256"
)
type cfb8 struct {
block cipher.Block
iv []byte
tmp []byte
decrypt bool
}
func NewCFB8(block cipher.Block, iv []byte, decrypt bool) cipher.Stream {
bs := block.BlockSize()
if len(iv) != bs {
panic("cfb8: IV length must equal block size")
}
return &cfb8{
block: block,
iv: append([]byte(nil), iv...),
tmp: make([]byte, bs),
decrypt: decrypt,
}
}
func (x *cfb8) XORKeyStream(dst, src []byte) {
for i := range src {
x.block.Encrypt(x.tmp, x.iv)
val := src[i]
dst[i] = val ^ x.tmp[0]
if x.decrypt {
copy(x.iv, x.iv[1:])
x.iv[len(x.iv)-1] = val
} else {
copy(x.iv, x.iv[1:])
x.iv[len(x.iv)-1] = dst[i]
}
}
}
// NewCipherStream now takes a session salt (IV) to prevent IV reuse attacks.
func NewCipherStream(password string, salt []byte, decrypt bool) (cipher.Stream, error) {
// Derive session key and IV from password and per-session salt
h := sha256.New()
h.Write([]byte(password))
h.Write(salt)
sessionMaterial := h.Sum(nil)
block, err := aes.NewCipher(sessionMaterial)
if err != nil {
return nil, err
}
// Use the first 16 bytes of the derived material as IV
return NewCFB8(block, sessionMaterial[:16], decrypt), nil
}