whisper/whisperv6: remove Version from the envelope (#15621)

pull/15634/head
Guillaume Ballet 7 years ago committed by Felix Lange
parent 586198ccea
commit bf62acf033
  1. 4
      whisper/whisperv6/benchmarks_test.go
  2. 37
      whisper/whisperv6/envelope.go
  3. 5
      whisper/whisperv6/message.go
  4. 36
      whisper/whisperv6/whisper.go
  5. 11
      whisper/whisperv6/whisper_test.go

@ -17,14 +17,16 @@
package whisperv6 package whisperv6
import ( import (
"crypto/sha256"
"testing" "testing"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"golang.org/x/crypto/pbkdf2"
) )
func BenchmarkDeriveKeyMaterial(b *testing.B) { func BenchmarkDeriveKeyMaterial(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
deriveKeyMaterial([]byte("test"), 0) pbkdf2.Key([]byte("test"), nil, 65356, aesKeyLength, sha256.New)
} }
} }

@ -36,12 +36,11 @@ import (
// Envelope represents a clear-text data packet to transmit through the Whisper // Envelope represents a clear-text data packet to transmit through the Whisper
// network. Its contents may or may not be encrypted and signed. // network. Its contents may or may not be encrypted and signed.
type Envelope struct { type Envelope struct {
Version []byte Expiry uint32
Expiry uint32 TTL uint32
TTL uint32 Topic TopicType
Topic TopicType Data []byte
Data []byte Nonce uint64
Nonce uint64
pow float64 // Message-specific PoW as described in the Whisper specification. pow float64 // Message-specific PoW as described in the Whisper specification.
hash common.Hash // Cached hash of the envelope to avoid rehashing every time. hash common.Hash // Cached hash of the envelope to avoid rehashing every time.
@ -50,12 +49,12 @@ type Envelope struct {
// size returns the size of envelope as it is sent (i.e. public fields only) // size returns the size of envelope as it is sent (i.e. public fields only)
func (e *Envelope) size() int { 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. // rlpWithoutNonce returns the RLP encoded envelope contents, except the nonce.
func (e *Envelope) rlpWithoutNonce() []byte { 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 return res
} }
@ -63,27 +62,16 @@ func (e *Envelope) rlpWithoutNonce() []byte {
// included into an envelope for network forwarding. // included into an envelope for network forwarding.
func NewEnvelope(ttl uint32, topic TopicType, msg *sentMessage) *Envelope { func NewEnvelope(ttl uint32, topic TopicType, msg *sentMessage) *Envelope {
env := Envelope{ env := Envelope{
Version: make([]byte, 1), Expiry: uint32(time.Now().Add(time.Second * time.Duration(ttl)).Unix()),
Expiry: uint32(time.Now().Add(time.Second * time.Duration(ttl)).Unix()), TTL: ttl,
TTL: ttl, Topic: topic,
Topic: topic, Data: msg.Raw,
Data: msg.Raw, Nonce: 0,
Nonce: 0,
}
if EnvelopeVersion < 256 {
env.Version[0] = byte(EnvelopeVersion)
} else {
panic("please increase the size of Envelope.Version before releasing this version")
} }
return &env 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 // Seal closes the envelope by spending the requested amount of time as a proof
// of work on hashing the data. // of work on hashing the data.
func (e *Envelope) Seal(options *MessageParams) error { func (e *Envelope) Seal(options *MessageParams) error {
@ -236,7 +224,6 @@ func (e *Envelope) Open(watcher *Filter) (msg *ReceivedMessage) {
msg.TTL = e.TTL msg.TTL = e.TTL
msg.Sent = e.Expiry - e.TTL msg.Sent = e.Expiry - e.TTL
msg.EnvelopeHash = e.Hash() msg.EnvelopeHash = e.Hash()
msg.EnvelopeVersion = e.Ver()
} }
return msg return msg
} }

@ -70,9 +70,8 @@ type ReceivedMessage struct {
Dst *ecdsa.PublicKey // Message recipient (identity used to decode the message) Dst *ecdsa.PublicKey // Message recipient (identity used to decode the message)
Topic TopicType Topic TopicType
SymKeyHash common.Hash // The Keccak256Hash of the key, associated with the Topic SymKeyHash common.Hash // The Keccak256Hash of the key, associated with the Topic
EnvelopeHash common.Hash // Message envelope hash to act as a unique id EnvelopeHash common.Hash // Message envelope hash to act as a unique id
EnvelopeVersion uint64
} }
func isMessageSigned(flags byte) bool { func isMessageSigned(flags byte) bool {

@ -367,7 +367,9 @@ func (w *Whisper) AddSymKeyFromPassword(password string) (string, error) {
return "", fmt.Errorf("failed to generate unique ID") 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 { if err != nil {
return "", err return "", err
} }
@ -587,10 +589,6 @@ func (wh *Whisper) add(envelope *Envelope) (bool, error) {
return false, fmt.Errorf("huge messages are not allowed [%x]", envelope.Hash()) 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() { if envelope.PoW() < wh.MinPow() {
log.Debug("envelope with low PoW dropped", "PoW", envelope.PoW(), "hash", envelope.Hash().Hex()) log.Debug("envelope with low PoW dropped", "PoW", envelope.PoW(), "hash", envelope.Hash().Hex())
return false, nil // drop envelope without error return false, nil // drop envelope without error
@ -628,16 +626,11 @@ func (wh *Whisper) add(envelope *Envelope) (bool, error) {
// postEvent queues the message for further processing. // postEvent queues the message for further processing.
func (w *Whisper) postEvent(envelope *Envelope, isP2P bool) { func (w *Whisper) postEvent(envelope *Envelope, isP2P bool) {
// if the version of incoming message is higher than if isP2P {
// currently supported version, we can not decrypt it, w.p2pMsgQueue <- envelope
// and therefore just ignore this message } else {
if envelope.Ver() <= EnvelopeVersion { w.checkOverflow()
if isP2P { w.messageQueue <- envelope
w.p2pMsgQueue <- envelope
} else {
w.checkOverflow()
w.messageQueue <- envelope
}
} }
} }
@ -823,19 +816,6 @@ func BytesToUintBigEndian(b []byte) (res uint64) {
return res 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 // GenerateRandomID generates a random string, which is then returned to be used as a key id
func GenerateRandomID() (id string, err error) { func GenerateRandomID() (id string, err error) {
buf := make([]byte, keyIdSize) buf := make([]byte, keyIdSize)

@ -19,11 +19,13 @@ package whisperv6
import ( import (
"bytes" "bytes"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/sha256"
mrand "math/rand" mrand "math/rand"
"testing" "testing"
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"golang.org/x/crypto/pbkdf2"
) )
func TestWhisperBasic(t *testing.T) { func TestWhisperBasic(t *testing.T) {
@ -79,14 +81,7 @@ func TestWhisperBasic(t *testing.T) {
} }
var derived []byte var derived []byte
ver := uint64(0xDEADBEEF) derived = pbkdf2.Key([]byte(peerID), nil, 65356, aesKeyLength, sha256.New)
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)
}
if !validateSymmetricKey(derived) { if !validateSymmetricKey(derived) {
t.Fatalf("failed validateSymmetricKey with param = %v.", derived) t.Fatalf("failed validateSymmetricKey with param = %v.", derived)
} }

Loading…
Cancel
Save