Commit 9cd71355 authored by gluk256's avatar gluk256 Committed by Felix Lange

whisper: big refactoring (#13852)

* whisper: GetMessages fixed; size restriction updated
* whisper: made PoW and MaxMsgSize customizable
* whisper: test added
* whisper: sym key management changed
* whisper: identity management refactored
* whisper: API refactoring (Post and Filter)
* whisper: big refactoring complete
* whisper: spelling fix
* whisper: variable topic size allowed for a filter
* whisper: final update
* whisper: formatting
* whisper: file exchange introduced in wnode
* whisper: bugfix
* whisper: API updated + new tests
* whisper: statistics updated
* whisper: wnode server updated
* whisper: allowed filtering for variable topic size
* whisper: tests added
* whisper: resolving merge conflicts
* whisper: refactoring (documenting mostly)
* whsiper: tests fixed
* whisper: down cased error messages
* whisper: documenting the API functions
* whisper: logging fixed
* whisper: fixed wnode parameters
* whisper: logs fixed (typos)
parent 8570ef19
This diff is collapsed.
...@@ -31,8 +31,6 @@ import ( ...@@ -31,8 +31,6 @@ import (
"github.com/syndtr/goleveldb/leveldb/util" "github.com/syndtr/goleveldb/leveldb/util"
) )
const MailServerKeyName = "958e04ab302fb36ad2616a352cbac79d"
type WMailServer struct { type WMailServer struct {
db *leveldb.DB db *leveldb.DB
w *whisper.Whisper w *whisper.Whisper
...@@ -75,11 +73,14 @@ func (s *WMailServer) Init(shh *whisper.Whisper, path string, password string, p ...@@ -75,11 +73,14 @@ func (s *WMailServer) Init(shh *whisper.Whisper, path string, password string, p
s.w = shh s.w = shh
s.pow = pow s.pow = pow
err = s.w.AddSymKey(MailServerKeyName, []byte(password)) MailServerKeyID, err := s.w.AddSymKeyFromPassword(password)
if err != nil { if err != nil {
utils.Fatalf("Failed to create symmetric key for MailServer: %s", err) utils.Fatalf("Failed to create symmetric key for MailServer: %s", err)
} }
s.key = s.w.GetSymKey(MailServerKeyName) s.key, err = s.w.GetSymKey(MailServerKeyID)
if err != nil {
utils.Fatalf("Failed to save symmetric key for MailServer")
}
} }
func (s *WMailServer) Close() { func (s *WMailServer) Close() {
......
...@@ -30,8 +30,8 @@ import ( ...@@ -30,8 +30,8 @@ import (
) )
const powRequirement = 0.00001 const powRequirement = 0.00001
const keyName = "6d604bac5401ce9a6b995f1b45a4ab"
var keyID string
var shh *whisper.Whisper var shh *whisper.Whisper
var seed = time.Now().Unix() var seed = time.Now().Unix()
...@@ -90,7 +90,7 @@ func TestMailServer(t *testing.T) { ...@@ -90,7 +90,7 @@ func TestMailServer(t *testing.T) {
server.Init(shh, dir, password, powRequirement) server.Init(shh, dir, password, powRequirement)
defer server.Close() defer server.Close()
err = shh.AddSymKey(keyName, []byte(password)) keyID, err = shh.AddSymKeyFromPassword(password)
if err != nil { if err != nil {
t.Fatalf("Failed to create symmetric key for mail request: %s", err) t.Fatalf("Failed to create symmetric key for mail request: %s", err)
} }
...@@ -102,7 +102,14 @@ func TestMailServer(t *testing.T) { ...@@ -102,7 +102,14 @@ func TestMailServer(t *testing.T) {
} }
func deliverTest(t *testing.T, server *WMailServer, env *whisper.Envelope) { func deliverTest(t *testing.T, server *WMailServer, env *whisper.Envelope) {
testPeerID := shh.NewIdentity() id, err := shh.NewKeyPair()
if err != nil {
t.Fatalf("failed to generate new key pair with seed %d: %s.", seed, err)
}
testPeerID, err := shh.GetPrivateKey(id)
if err != nil {
t.Fatalf("failed to retrieve new key pair with seed %d: %s.", seed, err)
}
birth := env.Expiry - env.TTL birth := env.Expiry - env.TTL
p := &ServerTestParams{ p := &ServerTestParams{
topic: env.Topic, topic: env.Topic,
...@@ -167,8 +174,13 @@ func createRequest(t *testing.T, p *ServerTestParams) *whisper.Envelope { ...@@ -167,8 +174,13 @@ func createRequest(t *testing.T, p *ServerTestParams) *whisper.Envelope {
binary.BigEndian.PutUint32(data[4:], p.upp) binary.BigEndian.PutUint32(data[4:], p.upp)
copy(data[8:], p.topic[:]) copy(data[8:], p.topic[:])
key, err := shh.GetSymKey(keyID)
if err != nil {
t.Fatalf("failed to retrieve sym key with seed %d: %s.", seed, err)
}
params := &whisper.MessageParams{ params := &whisper.MessageParams{
KeySym: shh.GetSymKey(keyName), KeySym: key,
Topic: p.topic, Topic: p.topic,
Payload: data, Payload: data,
PoW: powRequirement * 2, PoW: powRequirement * 2,
......
This diff is collapsed.
This diff is collapsed.
...@@ -54,9 +54,10 @@ const ( ...@@ -54,9 +54,10 @@ const (
aesKeyLength = 32 aesKeyLength = 32
saltLength = 12 saltLength = 12
AESNonceMaxLength = 12 AESNonceMaxLength = 12
keyIdSize = 32
MaxMessageLength = 0x0FFFFF // todo: remove this restriction after testing. this should be regulated by PoW. DefaultMaxMessageLength = 1024 * 1024
MinimumPoW = 10.0 // todo: review after testing. DefaultMinimumPoW = 1.0 // todo: review after testing.
padSizeLimitLower = 128 // it can not be less - we don't want to reveal the absence of signature padSizeLimitLower = 128 // it can not be less - we don't want to reveal the absence of signature
padSizeLimitUpper = 256 // just an arbitrary number, could be changed without losing compatibility padSizeLimitUpper = 256 // just an arbitrary number, could be changed without losing compatibility
......
...@@ -21,7 +21,6 @@ package whisperv5 ...@@ -21,7 +21,6 @@ package whisperv5
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"encoding/binary" "encoding/binary"
"errors"
"fmt" "fmt"
gmath "math" gmath "math"
"math/big" "math/big"
...@@ -83,7 +82,7 @@ func (e *Envelope) isAsymmetric() bool { ...@@ -83,7 +82,7 @@ func (e *Envelope) isAsymmetric() bool {
} }
func (e *Envelope) Ver() uint64 { func (e *Envelope) Ver() uint64 {
return bytesToIntLittleEndian(e.Version) return bytesToUintLittleEndian(e.Version)
} }
// Seal closes the envelope by spending the requested amount of time as a proof // Seal closes the envelope by spending the requested amount of time as a proof
...@@ -95,6 +94,9 @@ func (e *Envelope) Seal(options *MessageParams) error { ...@@ -95,6 +94,9 @@ func (e *Envelope) Seal(options *MessageParams) error {
e.Expiry += options.WorkTime e.Expiry += options.WorkTime
} else { } else {
target = e.powToFirstBit(options.PoW) target = e.powToFirstBit(options.PoW)
if target < 1 {
target = 1
}
} }
buf := make([]byte, 64) buf := make([]byte, 64)
...@@ -118,7 +120,7 @@ func (e *Envelope) Seal(options *MessageParams) error { ...@@ -118,7 +120,7 @@ func (e *Envelope) Seal(options *MessageParams) error {
} }
if target > 0 && bestBit < target { if target > 0 && bestBit < target {
return errors.New("Failed to reach the PoW target, insufficient work time") return fmt.Errorf("failed to reach the PoW target, specified pow time (%d seconds) was insufficient", options.WorkTime)
} }
return nil return nil
......
...@@ -18,7 +18,6 @@ package whisperv5 ...@@ -18,7 +18,6 @@ package whisperv5
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
crand "crypto/rand"
"fmt" "fmt"
"sync" "sync"
...@@ -30,9 +29,9 @@ type Filter struct { ...@@ -30,9 +29,9 @@ type Filter struct {
Src *ecdsa.PublicKey // Sender of the message Src *ecdsa.PublicKey // Sender of the message
KeyAsym *ecdsa.PrivateKey // Private Key of recipient KeyAsym *ecdsa.PrivateKey // Private Key of recipient
KeySym []byte // Key associated with the Topic KeySym []byte // Key associated with the Topic
Topics []TopicType // Topics to filter messages with Topics [][]byte // Topics to filter messages with
PoW float64 // Proof of work as described in the Whisper spec PoW float64 // Proof of work as described in the Whisper spec
AcceptP2P bool // Indicates whether this filter is interested in direct peer-to-peer messages AllowP2P bool // Indicates whether this filter is interested in direct peer-to-peer messages
SymKeyHash common.Hash // The Keccak256Hash of the symmetric key, needed for optimization SymKeyHash common.Hash // The Keccak256Hash of the symmetric key, needed for optimization
Messages map[common.Hash]*ReceivedMessage Messages map[common.Hash]*ReceivedMessage
...@@ -52,47 +51,35 @@ func NewFilters(w *Whisper) *Filters { ...@@ -52,47 +51,35 @@ func NewFilters(w *Whisper) *Filters {
} }
} }
func (fs *Filters) generateRandomID() (id string, err error) {
buf := make([]byte, 20)
for i := 0; i < 3; i++ {
_, err = crand.Read(buf)
if err != nil {
continue
}
if !validateSymmetricKey(buf) {
err = fmt.Errorf("error in generateRandomID: crypto/rand failed to generate random data")
continue
}
id = common.Bytes2Hex(buf)
if fs.watchers[id] != nil {
err = fmt.Errorf("error in generateRandomID: generated same ID twice")
continue
}
return id, err
}
return "", err
}
func (fs *Filters) Install(watcher *Filter) (string, error) { func (fs *Filters) Install(watcher *Filter) (string, error) {
if watcher.Messages == nil { if watcher.Messages == nil {
watcher.Messages = make(map[common.Hash]*ReceivedMessage) watcher.Messages = make(map[common.Hash]*ReceivedMessage)
} }
id, err := GenerateRandomID()
if err != nil {
return "", err
}
fs.mutex.Lock() fs.mutex.Lock()
defer fs.mutex.Unlock() defer fs.mutex.Unlock()
id, err := fs.generateRandomID() if fs.watchers[id] != nil {
if err == nil { return "", fmt.Errorf("failed to generate unique ID")
fs.watchers[id] = watcher
} }
fs.watchers[id] = watcher
return id, err return id, err
} }
func (fs *Filters) Uninstall(id string) { func (fs *Filters) Uninstall(id string) bool {
fs.mutex.Lock() fs.mutex.Lock()
defer fs.mutex.Unlock() defer fs.mutex.Unlock()
delete(fs.watchers, id) if fs.watchers[id] != nil {
delete(fs.watchers, id)
return true
}
return false
} }
func (fs *Filters) Get(id string) *Filter { func (fs *Filters) Get(id string) *Filter {
...@@ -102,11 +89,16 @@ func (fs *Filters) Get(id string) *Filter { ...@@ -102,11 +89,16 @@ func (fs *Filters) Get(id string) *Filter {
} }
func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) { func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) {
fs.mutex.RLock()
var msg *ReceivedMessage var msg *ReceivedMessage
for j, watcher := range fs.watchers {
if p2pMessage && !watcher.AcceptP2P { fs.mutex.RLock()
log.Trace(fmt.Sprintf("msg [%x], filter [%s]: p2p messages are not allowed", env.Hash(), j)) defer fs.mutex.RUnlock()
i := -1 // only used for logging info
for _, watcher := range fs.watchers {
i++
if p2pMessage && !watcher.AllowP2P {
log.Trace(fmt.Sprintf("msg [%x], filter [%d]: p2p messages are not allowed", env.Hash(), i))
continue continue
} }
...@@ -118,22 +110,32 @@ func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) { ...@@ -118,22 +110,32 @@ func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) {
if match { if match {
msg = env.Open(watcher) msg = env.Open(watcher)
if msg == nil { if msg == nil {
log.Trace(fmt.Sprintf("msg [%x], filter [%s]: failed to open", env.Hash(), j)) log.Trace("processing message: failed to open", "message", env.Hash().Hex(), "filter", i)
} }
} else { } else {
log.Trace(fmt.Sprintf("msg [%x], filter [%s]: does not match", env.Hash(), j)) log.Trace("processing message: does not match", "message", env.Hash().Hex(), "filter", i)
} }
} }
if match && msg != nil { if match && msg != nil {
log.Trace("processing message: decrypted", "hash", env.Hash().Hex())
watcher.Trigger(msg) watcher.Trigger(msg)
} }
} }
fs.mutex.RUnlock() // we need to unlock before calling addDecryptedMessage }
if msg != nil { func (f *Filter) processEnvelope(env *Envelope) *ReceivedMessage {
fs.whisper.addDecryptedMessage(msg) if f.MatchEnvelope(env) {
msg := env.Open(f)
if msg != nil {
return msg
} else {
log.Trace("processing envelope: failed to open", "hash", env.Hash().Hex())
}
} else {
log.Trace("processing envelope: does not match", "hash", env.Hash().Hex())
} }
return nil
} }
func (f *Filter) expectsAsymmetricEncryption() bool { func (f *Filter) expectsAsymmetricEncryption() bool {
...@@ -200,20 +202,33 @@ func (f *Filter) MatchTopic(topic TopicType) bool { ...@@ -200,20 +202,33 @@ func (f *Filter) MatchTopic(topic TopicType) bool {
return true return true
} }
for _, t := range f.Topics { for _, bt := range f.Topics {
if t == topic { if matchSingleTopic(topic, bt) {
return true return true
} }
} }
return false return false
} }
func matchSingleTopic(topic TopicType, bt []byte) bool {
if len(bt) > 4 {
bt = bt[:4]
}
for j, b := range bt {
if topic[j] != b {
return false
}
}
return true
}
func IsPubKeyEqual(a, b *ecdsa.PublicKey) bool { func IsPubKeyEqual(a, b *ecdsa.PublicKey) bool {
if !ValidatePublicKey(a) { if !ValidatePublicKey(a) {
return false return false
} else if !ValidatePublicKey(b) { } else if !ValidatePublicKey(b) {
return false return false
} }
// the Curve is always the same, just compare the points // the curve is always the same, just compare the points
return a.X.Cmp(b.X) == 0 && a.Y.Cmp(b.Y) == 0 return a.X.Cmp(b.X) == 0 && a.Y.Cmp(b.Y) == 0
} }
...@@ -53,8 +53,9 @@ func generateFilter(t *testing.T, symmetric bool) (*Filter, error) { ...@@ -53,8 +53,9 @@ func generateFilter(t *testing.T, symmetric bool) (*Filter, error) {
f.Messages = make(map[common.Hash]*ReceivedMessage) f.Messages = make(map[common.Hash]*ReceivedMessage)
const topicNum = 8 const topicNum = 8
f.Topics = make([]TopicType, topicNum) f.Topics = make([][]byte, topicNum)
for i := 0; i < topicNum; i++ { for i := 0; i < topicNum; i++ {
f.Topics[i] = make([]byte, 4)
mrand.Read(f.Topics[i][:]) mrand.Read(f.Topics[i][:])
f.Topics[i][0] = 0x01 f.Topics[i][0] = 0x01
} }
...@@ -108,7 +109,7 @@ func TestInstallFilters(t *testing.T) { ...@@ -108,7 +109,7 @@ func TestInstallFilters(t *testing.T) {
t.Fatalf("seed %d: failed to install filter: %s", seed, err) t.Fatalf("seed %d: failed to install filter: %s", seed, err)
} }
tst[i].id = j tst[i].id = j
if len(j) != 40 { if len(j) != keyIdSize*2 {
t.Fatalf("seed %d: wrong filter id size [%d]", seed, len(j)) t.Fatalf("seed %d: wrong filter id size [%d]", seed, len(j))
} }
} }
...@@ -194,8 +195,8 @@ func TestMatchEnvelope(t *testing.T) { ...@@ -194,8 +195,8 @@ func TestMatchEnvelope(t *testing.T) {
// encrypt symmetrically // encrypt symmetrically
i := mrand.Int() % 4 i := mrand.Int() % 4
fsym.Topics[i] = params.Topic fsym.Topics[i] = params.Topic[:]
fasym.Topics[i] = params.Topic fasym.Topics[i] = params.Topic[:]
msg = NewSentMessage(params) msg = NewSentMessage(params)
env, err = msg.Wrap(params) env, err = msg.Wrap(params)
if err != nil { if err != nil {
...@@ -320,7 +321,7 @@ func TestMatchMessageSym(t *testing.T) { ...@@ -320,7 +321,7 @@ func TestMatchMessageSym(t *testing.T) {
const index = 1 const index = 1
params.KeySym = f.KeySym params.KeySym = f.KeySym
params.Topic = f.Topics[index] params.Topic = BytesToTopic(f.Topics[index])
sentMessage := NewSentMessage(params) sentMessage := NewSentMessage(params)
env, err := sentMessage.Wrap(params) env, err := sentMessage.Wrap(params)
...@@ -413,7 +414,7 @@ func TestMatchMessageAsym(t *testing.T) { ...@@ -413,7 +414,7 @@ func TestMatchMessageAsym(t *testing.T) {
} }
const index = 1 const index = 1
params.Topic = f.Topics[index] params.Topic = BytesToTopic(f.Topics[index])
params.Dst = &f.KeyAsym.PublicKey params.Dst = &f.KeyAsym.PublicKey
keySymOrig := params.KeySym keySymOrig := params.KeySym
params.KeySym = nil params.KeySym = nil
...@@ -491,7 +492,7 @@ func cloneFilter(orig *Filter) *Filter { ...@@ -491,7 +492,7 @@ func cloneFilter(orig *Filter) *Filter {
clone.KeySym = orig.KeySym clone.KeySym = orig.KeySym
clone.Topics = orig.Topics clone.Topics = orig.Topics
clone.PoW = orig.PoW clone.PoW = orig.PoW
clone.AcceptP2P = orig.AcceptP2P clone.AllowP2P = orig.AllowP2P
clone.SymKeyHash = orig.SymKeyHash clone.SymKeyHash = orig.SymKeyHash
return &clone return &clone
} }
...@@ -504,7 +505,7 @@ func generateCompatibeEnvelope(t *testing.T, f *Filter) *Envelope { ...@@ -504,7 +505,7 @@ func generateCompatibeEnvelope(t *testing.T, f *Filter) *Envelope {
} }
params.KeySym = f.KeySym params.KeySym = f.KeySym
params.Topic = f.Topics[2] params.Topic = BytesToTopic(f.Topics[2])
sentMessage := NewSentMessage(params) sentMessage := NewSentMessage(params)
env, err := sentMessage.Wrap(params) env, err := sentMessage.Wrap(params)
if err != nil { if err != nil {
...@@ -655,7 +656,7 @@ func TestWatchers(t *testing.T) { ...@@ -655,7 +656,7 @@ func TestWatchers(t *testing.T) {
if f == nil { if f == nil {
t.Fatalf("failed to get the filter with seed %d.", seed) t.Fatalf("failed to get the filter with seed %d.", seed)
} }
f.AcceptP2P = true f.AllowP2P = true
total = 0 total = 0
filters.NotifyWatchers(envelopes[0], true) filters.NotifyWatchers(envelopes[0], true)
...@@ -668,3 +669,40 @@ func TestWatchers(t *testing.T) { ...@@ -668,3 +669,40 @@ func TestWatchers(t *testing.T) {
t.Fatalf("failed with seed %d: total: got %d, want 1.", seed, total) t.Fatalf("failed with seed %d: total: got %d, want 1.", seed, total)
} }
} }
func TestVariableTopics(t *testing.T) {
InitSingleTest()
var match bool
params, err := generateMessageParams()
if err != nil {
t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
}
msg := NewSentMessage(params)
env, err := msg.Wrap(params)
if err != nil {
t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
}
f, err := generateFilter(t, true)
if err != nil {
t.Fatalf("failed generateFilter with seed %d: %s.", seed, err)
}
for i := 0; i < 4; i++ {
arr := make([]byte, i+1, 4)
copy(arr, env.Topic[:i+1])
f.Topics[4] = arr
match = f.MatchEnvelope(env)
if !match {
t.Fatalf("failed MatchEnvelope symmetric with seed %d, step %d.", seed, i)
}
f.Topics[4][i]++
match = f.MatchEnvelope(env)
if match {
t.Fatalf("MatchEnvelope symmetric with seed %d, step %d: false positive.", seed, i)
}
}
}
...@@ -25,8 +25,6 @@ import ( ...@@ -25,8 +25,6 @@ import (
crand "crypto/rand" crand "crypto/rand"
"crypto/sha256" "crypto/sha256"
"errors" "errors"
"fmt"
mrand "math/rand"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
...@@ -102,14 +100,18 @@ func NewSentMessage(params *MessageParams) *SentMessage { ...@@ -102,14 +100,18 @@ func NewSentMessage(params *MessageParams) *SentMessage {
msg := SentMessage{} msg := SentMessage{}
msg.Raw = make([]byte, 1, len(params.Payload)+len(params.Payload)+signatureLength+padSizeLimitUpper) msg.Raw = make([]byte, 1, len(params.Payload)+len(params.Payload)+signatureLength+padSizeLimitUpper)
msg.Raw[0] = 0 // set all the flags to zero msg.Raw[0] = 0 // set all the flags to zero
msg.appendPadding(params) err := msg.appendPadding(params)
if err != nil {
log.Error("failed to create NewSentMessage", "err", err)
return nil
}
msg.Raw = append(msg.Raw, params.Payload...) msg.Raw = append(msg.Raw, params.Payload...)
return &msg return &msg
} }
// appendPadding appends the pseudorandom padding bytes and sets the padding flag. // appendPadding appends the pseudorandom padding bytes and sets the padding flag.
// The last byte contains the size of padding (thus, its size must not exceed 256). // The last byte contains the size of padding (thus, its size must not exceed 256).
func (msg *SentMessage) appendPadding(params *MessageParams) { func (msg *SentMessage) appendPadding(params *MessageParams) error {
total := len(params.Payload) + 1 total := len(params.Payload) + 1
if params.Src != nil { if params.Src != nil {
total += signatureLength total += signatureLength
...@@ -128,7 +130,10 @@ func (msg *SentMessage) appendPadding(params *MessageParams) { ...@@ -128,7 +130,10 @@ func (msg *SentMessage) appendPadding(params *MessageParams) {
panic("please fix the padding algorithm before releasing new version") panic("please fix the padding algorithm before releasing new version")
} }
buf := make([]byte, padSize) buf := make([]byte, padSize)
mrand.Read(buf[1:]) _, err := crand.Read(buf[1:])
if err != nil {
return err
}
buf[0] = byte(padSize) buf[0] = byte(padSize)
if params.Padding != nil { if params.Padding != nil {
copy(buf[1:], params.Padding) copy(buf[1:], params.Padding)
...@@ -136,6 +141,7 @@ func (msg *SentMessage) appendPadding(params *MessageParams) { ...@@ -136,6 +141,7 @@ func (msg *SentMessage) appendPadding(params *MessageParams) {
msg.Raw = append(msg.Raw, buf...) msg.Raw = append(msg.Raw, buf...)
msg.Raw[0] |= byte(0x1) // number of bytes indicating the padding size msg.Raw[0] |= byte(0x1) // number of bytes indicating the padding size
} }
return nil
} }
// sign calculates and sets the cryptographic signature for the message, // sign calculates and sets the cryptographic signature for the message,
...@@ -143,7 +149,7 @@ func (msg *SentMessage) appendPadding(params *MessageParams) { ...@@ -143,7 +149,7 @@ func (msg *SentMessage) appendPadding(params *MessageParams) {
func (msg *SentMessage) sign(key *ecdsa.PrivateKey) error { func (msg *SentMessage) sign(key *ecdsa.PrivateKey) error {
if isMessageSigned(msg.Raw[0]) { if isMessageSigned(msg.Raw[0]) {
// this should not happen, but no reason to panic // this should not happen, but no reason to panic
log.Error(fmt.Sprintf("Trying to sign a message which was already signed")) log.Error("failed to sign the message: already signed")
return nil return nil
} }
...@@ -161,7 +167,7 @@ func (msg *SentMessage) sign(key *ecdsa.PrivateKey) error { ...@@ -161,7 +167,7 @@ func (msg *SentMessage) sign(key *ecdsa.PrivateKey) error {
// encryptAsymmetric encrypts a message with a public key. // encryptAsymmetric encrypts a message with a public key.
func (msg *SentMessage) encryptAsymmetric(key *ecdsa.PublicKey) error { func (msg *SentMessage) encryptAsymmetric(key *ecdsa.PublicKey) error {
if !ValidatePublicKey(key) { if !ValidatePublicKey(key) {
return fmt.Errorf("Invalid public key provided for asymmetric encryption") return errors.New("invalid public key provided for asymmetric encryption")
} }
encrypted, err := ecies.Encrypt(crand.Reader, ecies.ImportECDSAPublic(key), msg.Raw, nil, nil) encrypted, err := ecies.Encrypt(crand.Reader, ecies.ImportECDSAPublic(key), msg.Raw, nil, nil)
if err == nil { if err == nil {
...@@ -215,17 +221,6 @@ func (msg *SentMessage) encryptSymmetric(key []byte) (salt []byte, nonce []byte, ...@@ -215,17 +221,6 @@ func (msg *SentMessage) encryptSymmetric(key []byte) (salt []byte, nonce []byte,
} }
// Wrap bundles the message into an Envelope to transmit over the network. // Wrap bundles the message into an Envelope to transmit over the network.
//
// pow (Proof Of Work) controls how much time to spend on hashing the message,
// inherently controlling its priority through the network (smaller hash, bigger
// priority).
//
// The user can control the amount of identity, privacy and encryption through
// the options parameter as follows:
// - options.From == nil && options.To == nil: anonymous broadcast
// - options.From != nil && options.To == nil: signed broadcast (known sender)
// - options.From == nil && options.To != nil: encrypted anonymous message
// - options.From != nil && options.To != nil: encrypted signed message
func (msg *SentMessage) Wrap(options *MessageParams) (envelope *Envelope, err error) { func (msg *SentMessage) Wrap(options *MessageParams) (envelope *Envelope, err error) {
if options.TTL == 0 { if options.TTL == 0 {
options.TTL = DefaultTTL options.TTL = DefaultTTL
...@@ -236,17 +231,13 @@ func (msg *SentMessage) Wrap(options *MessageParams) (envelope *Envelope, err er ...@@ -236,17 +231,13 @@ func (msg *SentMessage) Wrap(options *MessageParams) (envelope *Envelope, err er
return nil, err return nil, err
} }
} }
if len(msg.Raw) > MaxMessageLength {
log.Error(fmt.Sprintf("Message size must not exceed %d bytes", MaxMessageLength))
return nil, errors.New("Oversized message")
}
var salt, nonce []byte var salt, nonce []byte
if options.Dst != nil { if options.Dst != nil {
err = msg.encryptAsymmetric(options.Dst) err = msg.encryptAsymmetric(options.Dst)
} else if options.KeySym != nil { } else if options.KeySym != nil {
salt, nonce, err = msg.encryptSymmetric(options.KeySym) salt, nonce, err = msg.encryptSymmetric(options.KeySym)
} else { } else {
err = errors.New("Unable to encrypt the message: neither Dst nor Key") err = errors.New("unable to encrypt the message: neither symmetric nor assymmetric key provided")
} }
if err != nil { if err != nil {
...@@ -258,7 +249,6 @@ func (msg *SentMessage) Wrap(options *MessageParams) (envelope *Envelope, err er ...@@ -258,7 +249,6 @@ func (msg *SentMessage) Wrap(options *MessageParams) (envelope *Envelope, err er
if err != nil { if err != nil {
return nil, err return nil, err
} }
return envelope, nil return envelope, nil
} }
...@@ -279,9 +269,8 @@ func (msg *ReceivedMessage) decryptSymmetric(key []byte, salt []byte, nonce []by ...@@ -279,9 +269,8 @@ func (msg *ReceivedMessage) decryptSymmetric(key []byte, salt []byte, nonce []by
return err return err
} }
if len(nonce) != aesgcm.NonceSize() { if len(nonce) != aesgcm.NonceSize() {
info := fmt.Sprintf("Wrong AES nonce size - want: %d, got: %d", len(nonce), aesgcm.NonceSize()) log.Error("decrypting the message", "AES nonce size", len(nonce))
log.Error(fmt.Sprintf(info)) return errors.New("wrong AES nonce size")
return errors.New(info)
} }
decrypted, err := aesgcm.Open(nil, nonce, msg.Raw, nil) decrypted, err := aesgcm.Open(nil, nonce, msg.Raw, nil)
if err != nil { if err != nil {
...@@ -336,7 +325,7 @@ func (msg *ReceivedMessage) extractPadding(end int) (int, bool) { ...@@ -336,7 +325,7 @@ func (msg *ReceivedMessage) extractPadding(end int) (int, bool) {
paddingSize := 0 paddingSize := 0
sz := int(msg.Raw[0] & paddingMask) // number of bytes containing the entire size of padding, could be zero sz := int(msg.Raw[0] & paddingMask) // number of bytes containing the entire size of padding, could be zero
if sz != 0 { if sz != 0 {
paddingSize = int(bytesToIntLittleEndian(msg.Raw[1 : 1+sz])) paddingSize = int(bytesToUintLittleEndian(msg.Raw[1 : 1+sz]))
if paddingSize < sz || paddingSize+1 > end { if paddingSize < sz || paddingSize+1 > end {
return 0, false return 0, false
} }
...@@ -351,7 +340,7 @@ func (msg *ReceivedMessage) SigToPubKey() *ecdsa.PublicKey { ...@@ -351,7 +340,7 @@ func (msg *ReceivedMessage) SigToPubKey() *ecdsa.PublicKey {
pub, err := crypto.SigToPub(msg.hash(), msg.Signature) pub, err := crypto.SigToPub(msg.hash(), msg.Signature)
if err != nil { if err != nil {
log.Error(fmt.Sprintf("Could not get public key from signature: %v", err)) log.Error("failed to recover public key from signature", "err", err)
return nil return nil
} }
return pub return pub
......
...@@ -55,13 +55,13 @@ func newPeer(host *Whisper, remote *p2p.Peer, rw p2p.MsgReadWriter) *Peer { ...@@ -55,13 +55,13 @@ func newPeer(host *Whisper, remote *p2p.Peer, rw p2p.MsgReadWriter) *Peer {
// into the network. // into the network.
func (p *Peer) start() { func (p *Peer) start() {
go p.update() go p.update()
log.Debug(fmt.Sprintf("%v: whisper started", p.peer)) log.Trace("start", "peer", p.ID())
} }
// stop terminates the peer updater, stopping message forwarding to it. // stop terminates the peer updater, stopping message forwarding to it.
func (p *Peer) stop() { func (p *Peer) stop() {
close(p.quit) close(p.quit)
log.Debug(fmt.Sprintf("%v: whisper stopped", p.peer)) log.Trace("stop", "peer", p.ID())
} }
// handshake sends the protocol initiation status message to the remote peer and // handshake sends the protocol initiation status message to the remote peer and
...@@ -78,19 +78,19 @@ func (p *Peer) handshake() error { ...@@ -78,19 +78,19 @@ func (p *Peer) handshake() error {
return err return err
} }
if packet.Code != statusCode { if packet.Code != statusCode {
return fmt.Errorf("peer sent %x before status packet", packet.Code) return fmt.Errorf("peer [%x] sent packet %x before status packet", p.ID(), packet.Code)
} }
s := rlp.NewStream(packet.Payload, uint64(packet.Size)) s := rlp.NewStream(packet.Payload, uint64(packet.Size))
peerVersion, err := s.Uint() peerVersion, err := s.Uint()
if err != nil { if err != nil {
return fmt.Errorf("bad status message: %v", err) return fmt.Errorf("peer [%x] sent bad status message: %v", p.ID(), err)
} }
if peerVersion != ProtocolVersion { if peerVersion != ProtocolVersion {
return fmt.Errorf("protocol version mismatch %d != %d", peerVersion, ProtocolVersion) return fmt.Errorf("peer [%x]: protocol version mismatch %d != %d", p.ID(), peerVersion, ProtocolVersion)
} }
// Wait until out own status is consumed too // Wait until out own status is consumed too
if err := <-errc; err != nil { if err := <-errc; err != nil {
return fmt.Errorf("failed to send status packet: %v", err) return fmt.Errorf("peer [%x] failed to send status packet: %v", p.ID(), err)
} }
return nil return nil
} }
...@@ -110,7 +110,7 @@ func (p *Peer) update() { ...@@ -110,7 +110,7 @@ func (p *Peer) update() {
case <-transmit.C: case <-transmit.C:
if err := p.broadcast(); err != nil { if err := p.broadcast(); err != nil {
log.Info(fmt.Sprintf("%v: broadcast failed: %v", p.peer, err)) log.Trace("broadcast failed", "reason", err, "peer", p.ID())
return return
} }
...@@ -165,7 +165,7 @@ func (p *Peer) broadcast() error { ...@@ -165,7 +165,7 @@ func (p *Peer) broadcast() error {
if err := p2p.Send(p.ws, messagesCode, transmit); err != nil { if err := p2p.Send(p.ws, messagesCode, transmit); err != nil {
return err return err
} }
log.Trace(fmt.Sprint(p.peer, "broadcasted", len(transmit), "message(s)")) log.Trace("broadcast", "num. messages", len(transmit))
return nil return nil
} }
......
...@@ -114,12 +114,13 @@ func initialize(t *testing.T) { ...@@ -114,12 +114,13 @@ func initialize(t *testing.T) {
for i := 0; i < NumNodes; i++ { for i := 0; i < NumNodes; i++ {
var node TestNode var node TestNode
node.shh = New() node.shh = New()
node.shh.test = true node.shh.SetMinimumPoW(0.00000001)
node.shh.Start(nil) node.shh.Start(nil)
topics := make([]TopicType, 0) topics := make([]TopicType, 0)
topics = append(topics, sharedTopic) topics = append(topics, sharedTopic)
f := Filter{KeySym: sharedKey, Topics: topics} f := Filter{KeySym: sharedKey}
node.filerId, err = node.shh.Watch(&f) f.Topics = [][]byte{topics[0][:]}
node.filerId, err = node.shh.Subscribe(&f)
if err != nil { if err != nil {
t.Fatalf("failed to install the filter: %s.", err) t.Fatalf("failed to install the filter: %s.", err)
} }
...@@ -166,7 +167,7 @@ func stopServers() { ...@@ -166,7 +167,7 @@ func stopServers() {
for i := 0; i < NumNodes; i++ { for i := 0; i < NumNodes; i++ {
n := nodes[i] n := nodes[i]
if n != nil { if n != nil {
n.shh.Unwatch(n.filerId) n.shh.Unsubscribe(n.filerId)
n.shh.Stop() n.shh.Stop()
n.server.Stop() n.server.Stop()
} }
...@@ -257,7 +258,7 @@ func sendMsg(t *testing.T, expected bool, id int) { ...@@ -257,7 +258,7 @@ func sendMsg(t *testing.T, expected bool, id int) {
return return
} }
opt := MessageParams{KeySym: sharedKey, Topic: sharedTopic, Payload: expectedMessage, PoW: 0.00000001} opt := MessageParams{KeySym: sharedKey, Topic: sharedTopic, Payload: expectedMessage, PoW: 0.00000001, WorkTime: 1}
if !expected { if !expected {
opt.KeySym[0]++ opt.KeySym[0]++
opt.Topic[0]++ opt.Topic[0]++
...@@ -267,12 +268,12 @@ func sendMsg(t *testing.T, expected bool, id int) { ...@@ -267,12 +268,12 @@ func sendMsg(t *testing.T, expected bool, id int) {
msg := NewSentMessage(&opt) msg := NewSentMessage(&opt)
envelope, err := msg.Wrap(&opt) envelope, err := msg.Wrap(&opt)
if err != nil { if err != nil {
t.Fatalf("failed to seal message.") t.Fatalf("failed to seal message: %s", err)
} }
err = nodes[id].shh.Send(envelope) err = nodes[id].shh.Send(envelope)
if err != nil { if err != nil {
t.Fatalf("failed to send message.") t.Fatalf("failed to send message: %s", err)
} }
} }
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment