Skip to content
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
4 changes: 3 additions & 1 deletion whisper/whisperv6/benchmarks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@
package whisperv6

import (
"crypto/sha256"
"testing"

"github.com/ethereum/go-ethereum/crypto"
"golang.org/x/crypto/pbkdf2"
)

func BenchmarkDeriveKeyMaterial(b *testing.B) {
for i := 0; i < b.N; i++ {
deriveKeyMaterial([]byte("test"), 0)
pbkdf2.Key([]byte("test"), nil, 65356, aesKeyLength, sha256.New)
}
}

Expand Down
37 changes: 12 additions & 25 deletions whisper/whisperv6/envelope.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,11 @@ import (
// Envelope represents a clear-text data packet to transmit through the Whisper
// network. Its contents may or may not be encrypted and signed.
type Envelope struct {
Version []byte
Expiry uint32
TTL uint32
Topic TopicType
Data []byte
Nonce uint64
Expiry uint32
TTL uint32
Topic TopicType
Data []byte
Nonce uint64

pow float64 // Message-specific PoW as described in the Whisper specification.
hash common.Hash // Cached hash of the envelope to avoid rehashing every time.
Expand All @@ -50,40 +49,29 @@ type Envelope struct {

// size returns the size of envelope as it is sent (i.e. public fields only)
func (e *Envelope) size() int {
return EnvelopeHeaderLength + len(e.Version) + len(e.Data)
return EnvelopeHeaderLength + len(e.Data)
}

// rlpWithoutNonce returns the RLP encoded envelope contents, except the nonce.
func (e *Envelope) rlpWithoutNonce() []byte {
res, _ := rlp.EncodeToBytes([]interface{}{e.Version, e.Expiry, e.TTL, e.Topic, e.Data})
res, _ := rlp.EncodeToBytes([]interface{}{e.Expiry, e.TTL, e.Topic, e.Data})
return res
}

// NewEnvelope wraps a Whisper message with expiration and destination data
// included into an envelope for network forwarding.
func NewEnvelope(ttl uint32, topic TopicType, msg *sentMessage) *Envelope {
env := Envelope{
Version: make([]byte, 1),
Expiry: uint32(time.Now().Add(time.Second * time.Duration(ttl)).Unix()),
TTL: ttl,
Topic: topic,
Data: msg.Raw,
Nonce: 0,
}

if EnvelopeVersion < 256 {
env.Version[0] = byte(EnvelopeVersion)
} else {
panic("please increase the size of Envelope.Version before releasing this version")
Expiry: uint32(time.Now().Add(time.Second * time.Duration(ttl)).Unix()),
TTL: ttl,
Topic: topic,
Data: msg.Raw,
Nonce: 0,
}

return &env
}

func (e *Envelope) Ver() uint64 {
return bytesToUintLittleEndian(e.Version)
}

// Seal closes the envelope by spending the requested amount of time as a proof
// of work on hashing the data.
func (e *Envelope) Seal(options *MessageParams) error {
Expand Down Expand Up @@ -236,7 +224,6 @@ func (e *Envelope) Open(watcher *Filter) (msg *ReceivedMessage) {
msg.TTL = e.TTL
msg.Sent = e.Expiry - e.TTL
msg.EnvelopeHash = e.Hash()
msg.EnvelopeVersion = e.Ver()
}
return msg
}
5 changes: 2 additions & 3 deletions whisper/whisperv6/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,8 @@ type ReceivedMessage struct {
Dst *ecdsa.PublicKey // Message recipient (identity used to decode the message)
Topic TopicType

SymKeyHash common.Hash // The Keccak256Hash of the key, associated with the Topic
EnvelopeHash common.Hash // Message envelope hash to act as a unique id
EnvelopeVersion uint64
SymKeyHash common.Hash // The Keccak256Hash of the key, associated with the Topic
EnvelopeHash common.Hash // Message envelope hash to act as a unique id
}

func isMessageSigned(flags byte) bool {
Expand Down
36 changes: 8 additions & 28 deletions whisper/whisperv6/whisper.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,9 @@ func (w *Whisper) AddSymKeyFromPassword(password string) (string, error) {
return "", fmt.Errorf("failed to generate unique ID")
}

derived, err := deriveKeyMaterial([]byte(password), EnvelopeVersion)
// kdf should run no less than 0.1 seconds on an average computer,
// because it's an once in a session experience
derived := pbkdf2.Key([]byte(password), nil, 65356, aesKeyLength, sha256.New)
if err != nil {
return "", err
}
Expand Down Expand Up @@ -587,10 +589,6 @@ func (wh *Whisper) add(envelope *Envelope) (bool, error) {
return false, fmt.Errorf("huge messages are not allowed [%x]", envelope.Hash())
}

if len(envelope.Version) > 4 {
return false, fmt.Errorf("oversized version [%x]", envelope.Hash())
}

if envelope.PoW() < wh.MinPow() {
log.Debug("envelope with low PoW dropped", "PoW", envelope.PoW(), "hash", envelope.Hash().Hex())
return false, nil // drop envelope without error
Expand Down Expand Up @@ -628,16 +626,11 @@ func (wh *Whisper) add(envelope *Envelope) (bool, error) {

// postEvent queues the message for further processing.
func (w *Whisper) postEvent(envelope *Envelope, isP2P bool) {
// if the version of incoming message is higher than
// currently supported version, we can not decrypt it,
// and therefore just ignore this message
if envelope.Ver() <= EnvelopeVersion {
if isP2P {
w.p2pMsgQueue <- envelope
} else {
w.checkOverflow()
w.messageQueue <- envelope
}
if isP2P {
w.p2pMsgQueue <- envelope
} else {
w.checkOverflow()
w.messageQueue <- envelope
}
}

Expand Down Expand Up @@ -823,19 +816,6 @@ func BytesToUintBigEndian(b []byte) (res uint64) {
return res
}

// deriveKeyMaterial derives symmetric key material from the key or password.
// pbkdf2 is used for security, in case people use password instead of randomly generated keys.
func deriveKeyMaterial(key []byte, version uint64) (derivedKey []byte, err error) {
if version == 0 {
// kdf should run no less than 0.1 seconds on average compute,
// because it's a once in a session experience
derivedKey := pbkdf2.Key(key, nil, 65356, aesKeyLength, sha256.New)
return derivedKey, nil
} else {
return nil, unknownVersionError(version)
}
}

// GenerateRandomID generates a random string, which is then returned to be used as a key id
func GenerateRandomID() (id string, err error) {
buf := make([]byte, keyIdSize)
Expand Down
11 changes: 3 additions & 8 deletions whisper/whisperv6/whisper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ package whisperv6
import (
"bytes"
"crypto/ecdsa"
"crypto/sha256"
mrand "math/rand"
"testing"
"time"

"github.com/ethereum/go-ethereum/common"
"golang.org/x/crypto/pbkdf2"
)

func TestWhisperBasic(t *testing.T) {
Expand Down Expand Up @@ -79,14 +81,7 @@ func TestWhisperBasic(t *testing.T) {
}

var derived []byte
ver := uint64(0xDEADBEEF)
if _, err := deriveKeyMaterial(peerID, ver); err != unknownVersionError(ver) {
t.Fatalf("failed deriveKeyMaterial with param = %v: %s.", peerID, err)
}
derived, err = deriveKeyMaterial(peerID, 0)
if err != nil {
t.Fatalf("failed second deriveKeyMaterial with param = %v: %s.", peerID, err)
}
derived = pbkdf2.Key([]byte(peerID), nil, 65356, aesKeyLength, sha256.New)
if !validateSymmetricKey(derived) {
t.Fatalf("failed validateSymmetricKey with param = %v.", derived)
}
Expand Down