mirror of
https://git.zx2c4.com/wireguard-go
synced 2025-10-14 04:43:45 +08:00
Beginning work noise handshake
This commit is contained in:
179
src/noise_protocol.go
Normal file
179
src/noise_protocol.go
Normal file
@@ -0,0 +1,179 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"golang.org/x/crypto/blake2s"
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
"golang.org/x/crypto/poly1305"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
HandshakeInitialCreated = iota
|
||||
HandshakeInitialConsumed
|
||||
HandshakeResponseCreated
|
||||
)
|
||||
|
||||
const (
|
||||
NoiseConstruction = "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s"
|
||||
WGIdentifier = "WireGuard v1 zx2c4 Jason@zx2c4.com"
|
||||
WGLabelMAC1 = "mac1----"
|
||||
WGLabelCookie = "cookie--"
|
||||
)
|
||||
|
||||
const (
|
||||
MessageInitalType = 1
|
||||
MessageResponseType = 2
|
||||
MessageCookieResponseType = 3
|
||||
MessageTransportType = 4
|
||||
)
|
||||
|
||||
type MessageInital struct {
|
||||
Type uint32
|
||||
Sender uint32
|
||||
Ephemeral NoisePublicKey
|
||||
Static [NoisePublicKeySize + poly1305.TagSize]byte
|
||||
Timestamp [TAI64NSize + poly1305.TagSize]byte
|
||||
Mac1 [blake2s.Size128]byte
|
||||
Mac2 [blake2s.Size128]byte
|
||||
}
|
||||
|
||||
type MessageResponse struct {
|
||||
Type uint32
|
||||
Sender uint32
|
||||
Reciever uint32
|
||||
Ephemeral NoisePublicKey
|
||||
Empty [poly1305.TagSize]byte
|
||||
Mac1 [blake2s.Size128]byte
|
||||
Mac2 [blake2s.Size128]byte
|
||||
}
|
||||
|
||||
type MessageTransport struct {
|
||||
Type uint32
|
||||
Reciever uint32
|
||||
Counter uint64
|
||||
Content []byte
|
||||
}
|
||||
|
||||
type Handshake struct {
|
||||
lock sync.Mutex
|
||||
state int
|
||||
chainKey [blake2s.Size]byte // chain key
|
||||
hash [blake2s.Size]byte // hash value
|
||||
staticStatic NoisePublicKey // precomputed DH(S_i, S_r)
|
||||
ephemeral NoisePrivateKey // ephemeral secret key
|
||||
remoteIndex uint32 // index for sending
|
||||
device *Device
|
||||
peer *Peer
|
||||
}
|
||||
|
||||
var (
|
||||
ZeroNonce [chacha20poly1305.NonceSize]byte
|
||||
InitalChainKey [blake2s.Size]byte
|
||||
InitalHash [blake2s.Size]byte
|
||||
)
|
||||
|
||||
func init() {
|
||||
InitalChainKey = blake2s.Sum256([]byte(NoiseConstruction))
|
||||
InitalHash = blake2s.Sum256(append(InitalChainKey[:], []byte(WGIdentifier)...))
|
||||
}
|
||||
|
||||
func (h *Handshake) Precompute() {
|
||||
h.staticStatic = h.device.privateKey.sharedSecret(h.peer.publicKey)
|
||||
}
|
||||
|
||||
func (h *Handshake) ConsumeMessageResponse(msg *MessageResponse) {
|
||||
|
||||
}
|
||||
|
||||
func (h *Handshake) addHash(data []byte) {
|
||||
h.hash = addToHash(h.hash, data)
|
||||
}
|
||||
|
||||
func (h *Handshake) addChain(data []byte) {
|
||||
h.chainKey = addToChainKey(h.chainKey, data)
|
||||
}
|
||||
|
||||
func (h *Handshake) CreateMessageInital() (*MessageInital, error) {
|
||||
h.lock.Lock()
|
||||
defer h.lock.Unlock()
|
||||
|
||||
// reset handshake
|
||||
|
||||
var err error
|
||||
h.ephemeral, err = newPrivateKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h.chainKey = InitalChainKey
|
||||
h.hash = addToHash(InitalHash, h.device.publicKey[:])
|
||||
|
||||
// create ephemeral key
|
||||
|
||||
var msg MessageInital
|
||||
msg.Type = MessageInitalType
|
||||
msg.Sender = h.device.NewID(h)
|
||||
msg.Ephemeral = h.ephemeral.publicKey()
|
||||
h.chainKey = addToChainKey(h.chainKey, msg.Ephemeral[:])
|
||||
h.hash = addToHash(h.hash, msg.Ephemeral[:])
|
||||
|
||||
// encrypt long-term "identity key"
|
||||
|
||||
func() {
|
||||
var key [chacha20poly1305.KeySize]byte
|
||||
ss := h.ephemeral.sharedSecret(h.peer.publicKey)
|
||||
h.chainKey, key = KDF2(h.chainKey[:], ss[:])
|
||||
aead, _ := chacha20poly1305.New(key[:])
|
||||
aead.Seal(msg.Static[:0], ZeroNonce[:], h.device.publicKey[:], nil)
|
||||
}()
|
||||
h.addHash(msg.Static[:])
|
||||
|
||||
// encrypt timestamp
|
||||
|
||||
timestamp := Timestamp()
|
||||
func() {
|
||||
var key [chacha20poly1305.KeySize]byte
|
||||
h.chainKey, key = KDF2(h.chainKey[:], h.staticStatic[:])
|
||||
aead, _ := chacha20poly1305.New(key[:])
|
||||
aead.Seal(msg.Timestamp[:0], ZeroNonce[:], timestamp[:], nil)
|
||||
}()
|
||||
h.addHash(msg.Timestamp[:])
|
||||
h.state = HandshakeInitialCreated
|
||||
return &msg, nil
|
||||
}
|
||||
|
||||
func (h *Handshake) ConsumeMessageInitial(msg *MessageInital) error {
|
||||
if msg.Type != MessageInitalType {
|
||||
panic(errors.New("bug: invalid inital message type"))
|
||||
}
|
||||
|
||||
hash := addToHash(InitalHash, h.device.publicKey[:])
|
||||
chainKey := addToChainKey(InitalChainKey, msg.Ephemeral[:])
|
||||
hash = addToHash(hash, msg.Ephemeral[:])
|
||||
|
||||
//
|
||||
|
||||
ephemeral, err := newPrivateKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// update handshake state
|
||||
|
||||
h.lock.Lock()
|
||||
defer h.lock.Unlock()
|
||||
|
||||
h.hash = hash
|
||||
h.chainKey = chainKey
|
||||
h.remoteIndex = msg.Sender
|
||||
h.ephemeral = ephemeral
|
||||
h.state = HandshakeInitialConsumed
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (h *Handshake) CreateMessageResponse() []byte {
|
||||
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user