Files
zeromesh/internal/vl1/noise.go
xieyao 196ec09e55 fix: resolve P2P data plane decrypt failure and improve test environment
- Fix key derivation in both sdk/agent.go and internal/vl1/noise.go:
  sort public keys before hashing, use shared key for send/recv
- Adjust docker-compose port mappings to 7150-7153 range (within 7000-7200)
- Add GOPROXY env to Dockerfiles for Go module download in restricted networks
- Verified: all 3 clients connect with 2 peers each, zero decrypt errors
2026-06-17 15:19:54 +08:00

100 lines
2.2 KiB
Go

package vl1
import (
"bytes"
"crypto/cipher"
"crypto/rand"
"encoding/binary"
"fmt"
"io"
"golang.org/x/crypto/chacha20poly1305"
"golang.org/x/crypto/sha3"
)
type NoiseCipher struct {
sendCipher cipher.AEAD
recvCipher cipher.AEAD
sendNonce uint64
recvNonce uint64
}
func NewNoiseCipher(sendKey, recvKey [32]byte) *NoiseCipher {
send, err := chacha20poly1305.New(sendKey[:])
if err != nil {
panic(err)
}
recv, err := chacha20poly1305.New(recvKey[:])
if err != nil {
panic(err)
}
return &NoiseCipher{
sendCipher: send,
recvCipher: recv,
}
}
func DeriveKeysFromPSK(psk string, localPub, remotePub []byte) ([32]byte, [32]byte) {
first, second := localPub, remotePub
if bytes.Compare(localPub, remotePub) > 0 {
first, second = remotePub, localPub
}
h := sha3.New256()
h.Write([]byte(psk))
h.Write(first)
h.Write(second)
var key [32]byte
copy(key[:], h.Sum(nil))
return key, key
}
func (nc *NoiseCipher) Encrypt(plaintext []byte) ([]byte, error) {
nonce := make([]byte, 12)
binary.BigEndian.PutUint64(nonce[4:], nc.sendNonce)
nc.sendNonce++
ciphertext := nc.sendCipher.Seal(nil, nonce, plaintext, nil)
return ciphertext, nil
}
func (nc *NoiseCipher) Decrypt(ciphertext []byte) ([]byte, error) {
nonce := make([]byte, 12)
binary.BigEndian.PutUint64(nonce[4:], nc.recvNonce)
nc.recvNonce++
plaintext, err := nc.recvCipher.Open(nil, nonce, ciphertext, nil)
if err != nil {
return nil, fmt.Errorf("decrypt: %w", err)
}
return plaintext, nil
}
func (nc *NoiseCipher) EncryptTo(buf []byte, plaintext []byte) (int, error) {
nonce := make([]byte, 12)
binary.BigEndian.PutUint64(nonce[4:], nc.sendNonce)
nc.sendNonce++
ciphertext := nc.sendCipher.Seal(buf[:0], nonce, plaintext, nil)
return len(ciphertext), nil
}
func (nc *NoiseCipher) DecryptTo(buf []byte, ciphertext []byte) ([]byte, error) {
nonce := make([]byte, 12)
binary.BigEndian.PutUint64(nonce[4:], nc.recvNonce)
nc.recvNonce++
plaintext, err := nc.recvCipher.Open(buf[:0], nonce, ciphertext, nil)
if err != nil {
return nil, fmt.Errorf("decrypt: %w", err)
}
return plaintext, nil
}
func generateSessionKey() [32]byte {
var key [32]byte
if _, err := io.ReadFull(rand.Reader, key[:]); err != nil {
panic(err)
}
return key
}