Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Completing noise #9

Merged
merged 5 commits into from
Oct 30, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions ik/IK.noise.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,8 @@ func (mb *MessageBuffer) Encode1() []byte {

// Decodes initial message (stage 0) into MessageBuffer
func Decode0(in []byte) (*MessageBuffer, error) {
if len(in) < 32 {
return nil, errors.New("cannot decode stage 0 MessageBuffer: length less than 32 bytes")
if len(in) < 80 {
return nil, errors.New("cannot decode stage 0 MessageBuffer: length less than 80 bytes")
}

mb := new(MessageBuffer)
Expand All @@ -189,8 +189,8 @@ func Decode0(in []byte) (*MessageBuffer, error) {

// Decodes messages at stage 1 into MessageBuffer
func Decode1(in []byte) (*MessageBuffer, error) {
if len(in) < 80 {
return nil, errors.New("cannot decode stage 1 MessageBuffer: length less than 96 bytes")
if len(in) < 32 {
return nil, errors.New("cannot decode stage 1 MessageBuffer: length less than 32 bytes")
}

mb := new(MessageBuffer)
Expand Down
127 changes: 41 additions & 86 deletions ik_handshake.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,13 @@ package noise
import (
"context"
"fmt"
proto "github.com/gogo/protobuf/proto"

ik "github.com/ChainSafe/go-libp2p-noise/ik"
pb "github.com/ChainSafe/go-libp2p-noise/pb"
proto "github.com/gogo/protobuf/proto"
)

func (s *secureSession) ik_sendHandshakeMessage(payload []byte, initial_stage bool) error {
log.Debugf("ik_sendHandshakeMessage", "initiator", s.initiator, "payload", payload, "payload len", len(payload))

// create send message w payload
var msgbuf ik.MessageBuffer
s.ik_ns, msgbuf = ik.SendMessage(s.ik_ns, payload)
var encMsgBuf []byte
Expand All @@ -22,19 +19,19 @@ func (s *secureSession) ik_sendHandshakeMessage(payload []byte, initial_stage bo
encMsgBuf = msgbuf.Encode1()
}

log.Debugf("ik_sendHandshakeMessage", "initiator", s.initiator, "msgbuf", msgbuf)
log.Debugf("ik_sendHandshakeMessage initiator=%v msgbuf=%v", s.initiator, msgbuf)

err := s.writeLength(len(encMsgBuf))
if err != nil {
log.Error("xx_sendHandshakeMessage", "initiator", s.initiator, "error", err)
return fmt.Errorf("xx_sendHandshakeMessage write length fail: %s", err)
log.Error("ik_sendHandshakeMessage initiator=%v err=%s", s.initiator, err)
return fmt.Errorf("ik_sendHandshakeMessage write length err=%s", err)
}

// send message
_, err = s.insecure.Write(encMsgBuf)
if err != nil {
log.Error("ik_sendHandshakeMessage", "initiator", s.initiator, "error", err)
return fmt.Errorf("write to conn fail: %s", err)
log.Error("ik_sendHandshakeMessage initiator=%v err=%s", s.initiator, err)
return fmt.Errorf("ik_sendHandshakeMessage write to conn err=%s", err)
}

return nil
Expand All @@ -43,14 +40,14 @@ func (s *secureSession) ik_sendHandshakeMessage(payload []byte, initial_stage bo
func (s *secureSession) ik_recvHandshakeMessage(initial_stage bool) (buf []byte, plaintext []byte, valid bool, err error) {
l, err := s.readLength()
if err != nil {
return nil, nil, false, fmt.Errorf("read length fail: %s", err)
return nil, nil, false, fmt.Errorf("ik_recvHandshakeMessage read length err=%s", err)
}

buf = make([]byte, l)

_, err = s.insecure.Read(buf)
if err != nil {
return buf, nil, false, fmt.Errorf("read from conn fail: %s", err)
return buf, nil, false, fmt.Errorf("ik_recvHandshakeMessage read from conn err=%s", err)
}

var msgbuf *ik.MessageBuffer
Expand All @@ -60,171 +57,129 @@ func (s *secureSession) ik_recvHandshakeMessage(initial_stage bool) (buf []byte,
msgbuf, err = ik.Decode1(buf)
}

log.Debugf("ik_recvHandshakeMessage", "initiator", s.initiator, "msgbuf", msgbuf, "buf len", len(buf))
log.Debugf("ik_recvHandshakeMessage initiator=%v msgbuf=%v", s.initiator, msgbuf)

if err != nil {
log.Error("ik_recvHandshakeMessage decode", "initiator", s.initiator, "error", err)
return buf, nil, false, fmt.Errorf("decode msg fail: %s", err)
log.Error("ik_recvHandshakeMessage initiator=%v decode err=%s", s.initiator, err)
return buf, nil, false, fmt.Errorf("ik_recvHandshakeMessage decode msg fail: %s", err)
}

s.ik_ns, plaintext, valid = ik.RecvMessage(s.ik_ns, msgbuf)
if !valid {
log.Error("ik_recvHandshakeMessage", "initiator", s.initiator, "error", "validation fail")
return buf, nil, false, fmt.Errorf("validation fail")
log.Error("ik_recvHandshakeMessage initiator=%v err=%s", s.initiator, "validation fail")
return buf, nil, false, fmt.Errorf("ik_recvHandshakeMessage validation fail")
}

log.Debugf("recv handshake message", "initiator", s.initiator, "msgbuf", msgbuf, "payload len", len(plaintext))

return buf, plaintext, valid, nil
}

// IK:
// <- s
// ...
// -> e, es, s, ss
// <- e, ee, se
// returns last successful message upon error
func (s *secureSession) runHandshake_ik(ctx context.Context) ([]byte, error) {
var kp ik.Keypair

if s.noisePrivateKey == [32]byte{} {
// generate local static noise key
kp = ik.GenerateKeypair()
s.noisePrivateKey = kp.PrivKey()
log.Debugf("ik generate new noise kp", "initiator", s.initiator)
} else {
pub := ik.GeneratePublicKey(s.noisePrivateKey)
kp = ik.NewKeypair(pub, s.noisePrivateKey)
}

s.local.noiseKey = kp.PubKey()

log.Debugf("ik handshake", "noise pubkey", kp.PubKey())
func (s *secureSession) runHandshake_ik(ctx context.Context, payload []byte) ([]byte, error) {
kp := ik.NewKeypair(s.noiseKeypair.public_key, s.noiseKeypair.private_key)

// setup libp2p keys
localKeyRaw, err := s.LocalPublicKey().Bytes()
if err != nil {
return nil, fmt.Errorf("err getting raw pubkey: %s", err)
}

log.Debugf("ik handshake", "local libp2p key", localKeyRaw, "len", len(localKeyRaw))

// sign noise data for payload
noise_pub := kp.PubKey()
signedPayload, err := s.localKey.Sign(append([]byte(payload_string), noise_pub[:]...))
if err != nil {
return nil, fmt.Errorf("err signing payload: %s", err)
}

// create payload
payload := new(pb.NoiseHandshakePayload)
payload.Libp2PKey = localKeyRaw
payload.NoiseStaticKeySignature = signedPayload
payloadEnc, err := proto.Marshal(payload)
if err != nil {
return nil, fmt.Errorf("proto marshal payload fail: %s", err)
}
log.Debugf("runHandshake_ik initiator=%v pubkey=%x", kp.PubKey(), s.initiator)

// new XX noise session
s.ik_ns = ik.InitSession(s.initiator, s.prologue, kp, s.noiseStaticKeyCache[s.remotePeer])
log.Debugf("ik initiator init session", "remotePeer", s.noiseStaticKeyCache[s.remotePeer])

if s.initiator {
// stage 0 //
err := s.ik_sendHandshakeMessage(payloadEnc, true)
err := s.ik_sendHandshakeMessage(payload, true)
if err != nil {
log.Error("stage 0 initiator send", "err", err)
return nil, fmt.Errorf("stage 0 initiator fail: %s", err)
log.Errorf("runHandshake_ik stage=0 initiator=true send err=%s", err)
return nil, fmt.Errorf("runHandshake_ik stage=0 initiator=true err=%s", err)
}

// stage 1 //

// read message
buf, plaintext, valid, err := s.ik_recvHandshakeMessage(false)
if err != nil {
return buf, fmt.Errorf("stage 1 initiator fail: %s", err)
return buf, fmt.Errorf("runHandshake_ik stage=1 initiator=true err=%s", err)
}

if !valid {
return buf, fmt.Errorf("stage 1 initiator validation fail")
return buf, fmt.Errorf("runHandshake_ik stage=1 initiator=true err=validation fail")
}

// unmarshal payload
nhp := new(pb.NoiseHandshakePayload)
err = proto.Unmarshal(plaintext, nhp)
if err != nil {
return buf, fmt.Errorf("stage 1 initiator validation fail: cannot unmarshal payload")
return buf, fmt.Errorf("runHandshake_ik stage=1 initiator=true err=validation fail: cannot unmarshal payload")
}

// set remote libp2p public key
err = s.setRemotePeerInfo(nhp.GetLibp2PKey())
if err != nil {
log.Error("stage 1 initiator set remote peer info", "err", err)
return buf, fmt.Errorf("stage 1 initiator read remote libp2p key fail")
log.Errorf("runHandshake_ik stage=1 initiator=true set remote peer info err=%s", err)
return buf, fmt.Errorf("runHandshake_ik stage=1 initiator=true err=read remote libp2p key fail")
}

// assert that remote peer ID matches libp2p key
err = s.setRemotePeerID(s.RemotePublicKey())
if err != nil {
log.Error("stage 1 initiator set remote peer id", "err", err)
log.Errorf("runHandshake_ik stage=1 initiator=true set remote peer id err=%s", err)
}

// verify payload is signed by libp2p key
err = s.verifyPayload(nhp, s.noiseStaticKeyCache[s.remotePeer])
if err != nil {
log.Error("stage 1 initiator verify payload", "err", err)
log.Errorf("runHandshake_ik stage=1 initiator=true verify payload err=%s", err)
}

} else {
// stage 0 //

log.Debugf("ik responder", "noiseKey", kp.PubKey())
var buf, plaintext []byte
var valid bool

// read message
buf, plaintext, valid, err = s.ik_recvHandshakeMessage(true)
buf, plaintext, valid, err := s.ik_recvHandshakeMessage(true)
if err != nil {
return buf, fmt.Errorf("stage 0 responder fail: %s", err)
return buf, fmt.Errorf("runHandshake_ik stage=0 initiator=false err=%s", err)
}

if !valid {
return buf, fmt.Errorf("stage 0 responder validation fail")
return buf, fmt.Errorf("runHandshake_ik stage=0 initiator=false err: validation fail")
}

log.Debugf("stage 0 responder", "plaintext", plaintext, "plaintext len", len(plaintext))

// unmarshal payload
nhp := new(pb.NoiseHandshakePayload)
err = proto.Unmarshal(plaintext, nhp)
if err != nil {
return buf, fmt.Errorf("stage 0 responder validation fail: cannot unmarshal payload")
return buf, fmt.Errorf("runHandshake_ik stage=0 initiator=false err=validation fail: cannot unmarshal payload")
}

// set remote libp2p public key
err = s.setRemotePeerInfo(nhp.GetLibp2PKey())
if err != nil {
log.Error("stage 0 responder set remote peer info", "err", err)
return buf, fmt.Errorf("stage 0 responder read remote libp2p key fail")
return buf, fmt.Errorf("runHandshake_ik stage=0 initiator=false err=read remote libp2p key fail")
}

// assert that remote peer ID matches libp2p key
err = s.setRemotePeerID(s.RemotePublicKey())
if err != nil {
log.Error("stage 0 responder set remote peer id", "err", err)
return buf, fmt.Errorf("runHandshake_ik stage=0 initiator=false set remote peer id err=%s:", err)
}

// verify payload is signed by libp2p key
err = s.verifyPayload(nhp, s.ik_ns.RemoteKey())
if err != nil {
log.Error("stage 1 responder verify payload", "err", err)
return buf, fmt.Errorf("runHandshake_ik stage=0 initiator=false verify payload err=%s", err)
}

// stage 1 //

err := s.ik_sendHandshakeMessage(payloadEnc, false)
err = s.ik_sendHandshakeMessage(payload, false)
if err != nil {
log.Error("stage 1 responder send", "err", err)
return nil, fmt.Errorf("stage 1 responder fail: %s", err)
return nil, fmt.Errorf("runHandshake_ik stage=1 initiator=false send err=%s", err)
}

}

log.Debugf("ik_handshake done", "initiator", s.initiator)
log.Debugf("runHandshake_ik done initiator=%v", s.initiator)
return nil, nil
}
Loading