github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/whisper/whisperv5/message_test.go (about)

     1  // Copyright 2016 The Spectrum Authors
     2  // This file is part of the Spectrum library.
     3  //
     4  // The Spectrum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The Spectrum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the Spectrum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package whisperv5
    18  
    19  import (
    20  	"bytes"
    21  	mrand "math/rand"
    22  	"testing"
    23  
    24  	"github.com/SmartMeshFoundation/Spectrum/crypto"
    25  	"github.com/SmartMeshFoundation/Spectrum/rlp"
    26  )
    27  
    28  func generateMessageParams() (*MessageParams, error) {
    29  	// set all the parameters except p.Dst and p.Padding
    30  
    31  	buf := make([]byte, 4)
    32  	mrand.Read(buf)
    33  	sz := mrand.Intn(400)
    34  
    35  	var p MessageParams
    36  	p.PoW = 0.01
    37  	p.WorkTime = 1
    38  	p.TTL = uint32(mrand.Intn(1024))
    39  	p.Payload = make([]byte, sz)
    40  	p.KeySym = make([]byte, aesKeyLength)
    41  	mrand.Read(p.Payload)
    42  	mrand.Read(p.KeySym)
    43  	p.Topic = BytesToTopic(buf)
    44  
    45  	var err error
    46  	p.Src, err = crypto.GenerateKey()
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	return &p, nil
    52  }
    53  
    54  func singleMessageTest(t *testing.T, symmetric bool) {
    55  	params, err := generateMessageParams()
    56  	if err != nil {
    57  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
    58  	}
    59  
    60  	key, err := crypto.GenerateKey()
    61  	if err != nil {
    62  		t.Fatalf("failed GenerateKey with seed %d: %s.", seed, err)
    63  	}
    64  
    65  	if !symmetric {
    66  		params.KeySym = nil
    67  		params.Dst = &key.PublicKey
    68  	}
    69  
    70  	text := make([]byte, 0, 512)
    71  	text = append(text, params.Payload...)
    72  
    73  	msg, err := NewSentMessage(params)
    74  	if err != nil {
    75  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
    76  	}
    77  	env, err := msg.Wrap(params)
    78  	if err != nil {
    79  		t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
    80  	}
    81  
    82  	var decrypted *ReceivedMessage
    83  	if symmetric {
    84  		decrypted, err = env.OpenSymmetric(params.KeySym)
    85  	} else {
    86  		decrypted, err = env.OpenAsymmetric(key)
    87  	}
    88  
    89  	if err != nil {
    90  		t.Fatalf("failed to encrypt with seed %d: %s.", seed, err)
    91  	}
    92  
    93  	if !decrypted.Validate() {
    94  		t.Fatalf("failed to validate with seed %d.", seed)
    95  	}
    96  
    97  	if !bytes.Equal(text, decrypted.Payload) {
    98  		t.Fatalf("failed with seed %d: compare payload.", seed)
    99  	}
   100  	if !isMessageSigned(decrypted.Raw[0]) {
   101  		t.Fatalf("failed with seed %d: unsigned.", seed)
   102  	}
   103  	if len(decrypted.Signature) != signatureLength {
   104  		t.Fatalf("failed with seed %d: signature len %d.", seed, len(decrypted.Signature))
   105  	}
   106  	if !IsPubKeyEqual(decrypted.Src, &params.Src.PublicKey) {
   107  		t.Fatalf("failed with seed %d: signature mismatch.", seed)
   108  	}
   109  }
   110  
   111  func TestMessageEncryption(t *testing.T) {
   112  	InitSingleTest()
   113  
   114  	var symmetric bool
   115  	for i := 0; i < 256; i++ {
   116  		singleMessageTest(t, symmetric)
   117  		symmetric = !symmetric
   118  	}
   119  }
   120  
   121  func TestMessageWrap(t *testing.T) {
   122  	seed = int64(1777444222)
   123  	mrand.Seed(seed)
   124  	target := 128.0
   125  
   126  	params, err := generateMessageParams()
   127  	if err != nil {
   128  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
   129  	}
   130  
   131  	msg, err := NewSentMessage(params)
   132  	if err != nil {
   133  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   134  	}
   135  	params.TTL = 1
   136  	params.WorkTime = 12
   137  	params.PoW = target
   138  	env, err := msg.Wrap(params)
   139  	if err != nil {
   140  		t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
   141  	}
   142  
   143  	pow := env.PoW()
   144  	if pow < target {
   145  		t.Fatalf("failed Wrap with seed %d: pow < target (%f vs. %f).", seed, pow, target)
   146  	}
   147  
   148  	// set PoW target too high, expect error
   149  	msg2, err := NewSentMessage(params)
   150  	if err != nil {
   151  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   152  	}
   153  	params.TTL = 1000000
   154  	params.WorkTime = 1
   155  	params.PoW = 10000000.0
   156  	_, err = msg2.Wrap(params)
   157  	if err == nil {
   158  		t.Fatalf("unexpectedly reached the PoW target with seed %d.", seed)
   159  	}
   160  }
   161  
   162  func TestMessageSeal(t *testing.T) {
   163  	// this test depends on deterministic choice of seed (1976726903)
   164  	seed = int64(1976726903)
   165  	mrand.Seed(seed)
   166  
   167  	params, err := generateMessageParams()
   168  	if err != nil {
   169  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
   170  	}
   171  
   172  	msg, err := NewSentMessage(params)
   173  	if err != nil {
   174  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   175  	}
   176  	params.TTL = 1
   177  	aesnonce := make([]byte, 12)
   178  	mrand.Read(aesnonce)
   179  
   180  	env := NewEnvelope(params.TTL, params.Topic, aesnonce, msg)
   181  	if err != nil {
   182  		t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
   183  	}
   184  
   185  	env.Expiry = uint32(seed) // make it deterministic
   186  	target := 32.0
   187  	params.WorkTime = 4
   188  	params.PoW = target
   189  	env.Seal(params)
   190  
   191  	env.calculatePoW(0)
   192  	pow := env.PoW()
   193  	if pow < target {
   194  		t.Fatalf("failed Wrap with seed %d: pow < target (%f vs. %f).", seed, pow, target)
   195  	}
   196  
   197  	params.WorkTime = 1
   198  	params.PoW = 1000000000.0
   199  	env.Seal(params)
   200  	env.calculatePoW(0)
   201  	pow = env.PoW()
   202  	if pow < 2*target {
   203  		t.Fatalf("failed Wrap with seed %d: pow too small %f.", seed, pow)
   204  	}
   205  }
   206  
   207  func TestEnvelopeOpen(t *testing.T) {
   208  	InitSingleTest()
   209  
   210  	var symmetric bool
   211  	for i := 0; i < 256; i++ {
   212  		singleEnvelopeOpenTest(t, symmetric)
   213  		symmetric = !symmetric
   214  	}
   215  }
   216  
   217  func singleEnvelopeOpenTest(t *testing.T, symmetric bool) {
   218  	params, err := generateMessageParams()
   219  	if err != nil {
   220  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
   221  	}
   222  
   223  	key, err := crypto.GenerateKey()
   224  	if err != nil {
   225  		t.Fatalf("failed GenerateKey with seed %d: %s.", seed, err)
   226  	}
   227  
   228  	if !symmetric {
   229  		params.KeySym = nil
   230  		params.Dst = &key.PublicKey
   231  	}
   232  
   233  	text := make([]byte, 0, 512)
   234  	text = append(text, params.Payload...)
   235  
   236  	msg, err := NewSentMessage(params)
   237  	if err != nil {
   238  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   239  	}
   240  	env, err := msg.Wrap(params)
   241  	if err != nil {
   242  		t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
   243  	}
   244  
   245  	f := Filter{KeyAsym: key, KeySym: params.KeySym}
   246  	decrypted := env.Open(&f)
   247  	if decrypted == nil {
   248  		t.Fatalf("failed to open with seed %d.", seed)
   249  	}
   250  
   251  	if !bytes.Equal(text, decrypted.Payload) {
   252  		t.Fatalf("failed with seed %d: compare payload.", seed)
   253  	}
   254  	if !isMessageSigned(decrypted.Raw[0]) {
   255  		t.Fatalf("failed with seed %d: unsigned.", seed)
   256  	}
   257  	if len(decrypted.Signature) != signatureLength {
   258  		t.Fatalf("failed with seed %d: signature len %d.", seed, len(decrypted.Signature))
   259  	}
   260  	if !IsPubKeyEqual(decrypted.Src, &params.Src.PublicKey) {
   261  		t.Fatalf("failed with seed %d: signature mismatch.", seed)
   262  	}
   263  	if decrypted.isAsymmetricEncryption() == symmetric {
   264  		t.Fatalf("failed with seed %d: asymmetric %v vs. %v.", seed, decrypted.isAsymmetricEncryption(), symmetric)
   265  	}
   266  	if decrypted.isSymmetricEncryption() != symmetric {
   267  		t.Fatalf("failed with seed %d: symmetric %v vs. %v.", seed, decrypted.isSymmetricEncryption(), symmetric)
   268  	}
   269  	if !symmetric {
   270  		if decrypted.Dst == nil {
   271  			t.Fatalf("failed with seed %d: dst is nil.", seed)
   272  		}
   273  		if !IsPubKeyEqual(decrypted.Dst, &key.PublicKey) {
   274  			t.Fatalf("failed with seed %d: Dst.", seed)
   275  		}
   276  	}
   277  }
   278  
   279  func TestEncryptWithZeroKey(t *testing.T) {
   280  	InitSingleTest()
   281  
   282  	params, err := generateMessageParams()
   283  	if err != nil {
   284  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
   285  	}
   286  	msg, err := NewSentMessage(params)
   287  	if err != nil {
   288  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   289  	}
   290  	params.KeySym = make([]byte, aesKeyLength)
   291  	_, err = msg.Wrap(params)
   292  	if err == nil {
   293  		t.Fatalf("wrapped with zero key, seed: %d.", seed)
   294  	}
   295  
   296  	params, err = generateMessageParams()
   297  	if err != nil {
   298  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
   299  	}
   300  	msg, err = NewSentMessage(params)
   301  	if err != nil {
   302  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   303  	}
   304  	params.KeySym = make([]byte, 0)
   305  	_, err = msg.Wrap(params)
   306  	if err == nil {
   307  		t.Fatalf("wrapped with empty key, seed: %d.", seed)
   308  	}
   309  
   310  	params, err = generateMessageParams()
   311  	if err != nil {
   312  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
   313  	}
   314  	msg, err = NewSentMessage(params)
   315  	if err != nil {
   316  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   317  	}
   318  	params.KeySym = nil
   319  	_, err = msg.Wrap(params)
   320  	if err == nil {
   321  		t.Fatalf("wrapped with nil key, seed: %d.", seed)
   322  	}
   323  }
   324  
   325  func TestRlpEncode(t *testing.T) {
   326  	InitSingleTest()
   327  
   328  	params, err := generateMessageParams()
   329  	if err != nil {
   330  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
   331  	}
   332  	msg, err := NewSentMessage(params)
   333  	if err != nil {
   334  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   335  	}
   336  	env, err := msg.Wrap(params)
   337  	if err != nil {
   338  		t.Fatalf("wrapped with zero key, seed: %d.", seed)
   339  	}
   340  
   341  	raw, err := rlp.EncodeToBytes(env)
   342  	if err != nil {
   343  		t.Fatalf("RLP encode failed: %s.", err)
   344  	}
   345  
   346  	var decoded Envelope
   347  	rlp.DecodeBytes(raw, &decoded)
   348  	if err != nil {
   349  		t.Fatalf("RLP decode failed: %s.", err)
   350  	}
   351  
   352  	he := env.Hash()
   353  	hd := decoded.Hash()
   354  
   355  	if he != hd {
   356  		t.Fatalf("Hashes are not equal: %x vs. %x", he, hd)
   357  	}
   358  }
   359  
   360  func singlePaddingTest(t *testing.T, padSize int) {
   361  	params, err := generateMessageParams()
   362  	if err != nil {
   363  		t.Fatalf("failed generateMessageParams with seed %d and sz=%d: %s.", seed, padSize, err)
   364  	}
   365  	params.Padding = make([]byte, padSize)
   366  	params.PoW = 0.0000000001
   367  	pad := make([]byte, padSize)
   368  	_, err = mrand.Read(pad)
   369  	if err != nil {
   370  		t.Fatalf("padding is not generated (seed %d): %s", seed, err)
   371  	}
   372  	n := copy(params.Padding, pad)
   373  	if n != padSize {
   374  		t.Fatalf("padding is not copied (seed %d): %s", seed, err)
   375  	}
   376  	msg, err := NewSentMessage(params)
   377  	if err != nil {
   378  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   379  	}
   380  	env, err := msg.Wrap(params)
   381  	if err != nil {
   382  		t.Fatalf("failed to wrap, seed: %d and sz=%d.", seed, padSize)
   383  	}
   384  	f := Filter{KeySym: params.KeySym}
   385  	decrypted := env.Open(&f)
   386  	if decrypted == nil {
   387  		t.Fatalf("failed to open, seed and sz=%d: %d.", seed, padSize)
   388  	}
   389  	if !bytes.Equal(pad, decrypted.Padding) {
   390  		t.Fatalf("padding is not retireved as expected with seed %d and sz=%d:\n[%x]\n[%x].", seed, padSize, pad, decrypted.Padding)
   391  	}
   392  }
   393  
   394  func TestPadding(t *testing.T) {
   395  	InitSingleTest()
   396  
   397  	for i := 1; i < 260; i++ {
   398  		singlePaddingTest(t, i)
   399  	}
   400  
   401  	lim := 256 * 256
   402  	for i := lim - 5; i < lim+2; i++ {
   403  		singlePaddingTest(t, i)
   404  	}
   405  
   406  	for i := 0; i < 256; i++ {
   407  		n := mrand.Intn(256*254) + 256
   408  		singlePaddingTest(t, n)
   409  	}
   410  
   411  	for i := 0; i < 256; i++ {
   412  		n := mrand.Intn(256*1024) + 256*256
   413  		singlePaddingTest(t, n)
   414  	}
   415  }