github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/whisper/whisperv6/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 whisperv6
    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  
   178  	env := NewEnvelope(params.TTL, params.Topic, msg)
   179  	if err != nil {
   180  		t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
   181  	}
   182  
   183  	env.Expiry = uint32(seed) // make it deterministic
   184  	target := 32.0
   185  	params.WorkTime = 4
   186  	params.PoW = target
   187  	env.Seal(params)
   188  
   189  	env.calculatePoW(0)
   190  	pow := env.PoW()
   191  	if pow < target {
   192  		t.Fatalf("failed Wrap with seed %d: pow < target (%f vs. %f).", seed, pow, target)
   193  	}
   194  
   195  	params.WorkTime = 1
   196  	params.PoW = 1000000000.0
   197  	env.Seal(params)
   198  	env.calculatePoW(0)
   199  	pow = env.PoW()
   200  	if pow < 2*target {
   201  		t.Fatalf("failed Wrap with seed %d: pow too small %f.", seed, pow)
   202  	}
   203  }
   204  
   205  func TestEnvelopeOpen(t *testing.T) {
   206  	InitSingleTest()
   207  
   208  	var symmetric bool
   209  	for i := 0; i < 256; i++ {
   210  		singleEnvelopeOpenTest(t, symmetric)
   211  		symmetric = !symmetric
   212  	}
   213  }
   214  
   215  func singleEnvelopeOpenTest(t *testing.T, symmetric bool) {
   216  	params, err := generateMessageParams()
   217  	if err != nil {
   218  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
   219  	}
   220  
   221  	key, err := crypto.GenerateKey()
   222  	if err != nil {
   223  		t.Fatalf("failed GenerateKey with seed %d: %s.", seed, err)
   224  	}
   225  
   226  	if !symmetric {
   227  		params.KeySym = nil
   228  		params.Dst = &key.PublicKey
   229  	}
   230  
   231  	text := make([]byte, 0, 512)
   232  	text = append(text, params.Payload...)
   233  
   234  	msg, err := NewSentMessage(params)
   235  	if err != nil {
   236  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   237  	}
   238  	env, err := msg.Wrap(params)
   239  	if err != nil {
   240  		t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
   241  	}
   242  
   243  	var f Filter
   244  	if symmetric {
   245  		f = Filter{KeySym: params.KeySym}
   246  	} else {
   247  		f = Filter{KeyAsym: key}
   248  	}
   249  	decrypted := env.Open(&f)
   250  	if decrypted == nil {
   251  		t.Fatalf("failed to open with seed %d.", seed)
   252  	}
   253  
   254  	if !bytes.Equal(text, decrypted.Payload) {
   255  		t.Fatalf("failed with seed %d: compare payload.", seed)
   256  	}
   257  	if !isMessageSigned(decrypted.Raw[0]) {
   258  		t.Fatalf("failed with seed %d: unsigned.", seed)
   259  	}
   260  	if len(decrypted.Signature) != signatureLength {
   261  		t.Fatalf("failed with seed %d: signature len %d.", seed, len(decrypted.Signature))
   262  	}
   263  	if !IsPubKeyEqual(decrypted.Src, &params.Src.PublicKey) {
   264  		t.Fatalf("failed with seed %d: signature mismatch.", seed)
   265  	}
   266  	if decrypted.isAsymmetricEncryption() == symmetric {
   267  		t.Fatalf("failed with seed %d: asymmetric %v vs. %v.", seed, decrypted.isAsymmetricEncryption(), symmetric)
   268  	}
   269  	if decrypted.isSymmetricEncryption() != symmetric {
   270  		t.Fatalf("failed with seed %d: symmetric %v vs. %v.", seed, decrypted.isSymmetricEncryption(), symmetric)
   271  	}
   272  	if !symmetric {
   273  		if decrypted.Dst == nil {
   274  			t.Fatalf("failed with seed %d: dst is nil.", seed)
   275  		}
   276  		if !IsPubKeyEqual(decrypted.Dst, &key.PublicKey) {
   277  			t.Fatalf("failed with seed %d: Dst.", seed)
   278  		}
   279  	}
   280  }
   281  
   282  func TestEncryptWithZeroKey(t *testing.T) {
   283  	InitSingleTest()
   284  
   285  	params, err := generateMessageParams()
   286  	if err != nil {
   287  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
   288  	}
   289  	msg, err := NewSentMessage(params)
   290  	if err != nil {
   291  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   292  	}
   293  	params.KeySym = make([]byte, aesKeyLength)
   294  	_, err = msg.Wrap(params)
   295  	if err == nil {
   296  		t.Fatalf("wrapped with zero key, seed: %d.", seed)
   297  	}
   298  
   299  	params, err = generateMessageParams()
   300  	if err != nil {
   301  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
   302  	}
   303  	msg, err = NewSentMessage(params)
   304  	if err != nil {
   305  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   306  	}
   307  	params.KeySym = make([]byte, 0)
   308  	_, err = msg.Wrap(params)
   309  	if err == nil {
   310  		t.Fatalf("wrapped with empty key, seed: %d.", seed)
   311  	}
   312  
   313  	params, err = generateMessageParams()
   314  	if err != nil {
   315  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
   316  	}
   317  	msg, err = NewSentMessage(params)
   318  	if err != nil {
   319  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   320  	}
   321  	params.KeySym = nil
   322  	_, err = msg.Wrap(params)
   323  	if err == nil {
   324  		t.Fatalf("wrapped with nil key, seed: %d.", seed)
   325  	}
   326  }
   327  
   328  func TestRlpEncode(t *testing.T) {
   329  	InitSingleTest()
   330  
   331  	params, err := generateMessageParams()
   332  	if err != nil {
   333  		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
   334  	}
   335  	msg, err := NewSentMessage(params)
   336  	if err != nil {
   337  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   338  	}
   339  	env, err := msg.Wrap(params)
   340  	if err != nil {
   341  		t.Fatalf("wrapped with zero key, seed: %d.", seed)
   342  	}
   343  
   344  	raw, err := rlp.EncodeToBytes(env)
   345  	if err != nil {
   346  		t.Fatalf("RLP encode failed: %s.", err)
   347  	}
   348  
   349  	var decoded Envelope
   350  	rlp.DecodeBytes(raw, &decoded)
   351  	if err != nil {
   352  		t.Fatalf("RLP decode failed: %s.", err)
   353  	}
   354  
   355  	he := env.Hash()
   356  	hd := decoded.Hash()
   357  
   358  	if he != hd {
   359  		t.Fatalf("Hashes are not equal: %x vs. %x", he, hd)
   360  	}
   361  }
   362  
   363  func singlePaddingTest(t *testing.T, padSize int) {
   364  	params, err := generateMessageParams()
   365  	if err != nil {
   366  		t.Fatalf("failed generateMessageParams with seed %d and sz=%d: %s.", seed, padSize, err)
   367  	}
   368  	params.Padding = make([]byte, padSize)
   369  	params.PoW = 0.0000000001
   370  	pad := make([]byte, padSize)
   371  	_, err = mrand.Read(pad)
   372  	if err != nil {
   373  		t.Fatalf("padding is not generated (seed %d): %s", seed, err)
   374  	}
   375  	n := copy(params.Padding, pad)
   376  	if n != padSize {
   377  		t.Fatalf("padding is not copied (seed %d): %s", seed, err)
   378  	}
   379  	msg, err := NewSentMessage(params)
   380  	if err != nil {
   381  		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
   382  	}
   383  	env, err := msg.Wrap(params)
   384  	if err != nil {
   385  		t.Fatalf("failed to wrap, seed: %d and sz=%d.", seed, padSize)
   386  	}
   387  	f := Filter{KeySym: params.KeySym}
   388  	decrypted := env.Open(&f)
   389  	if decrypted == nil {
   390  		t.Fatalf("failed to open, seed and sz=%d: %d.", seed, padSize)
   391  	}
   392  	if !bytes.Equal(pad, decrypted.Padding) {
   393  		t.Fatalf("padding is not retireved as expected with seed %d and sz=%d:\n[%x]\n[%x].", seed, padSize, pad, decrypted.Padding)
   394  	}
   395  }
   396  
   397  func TestPadding(t *testing.T) {
   398  	InitSingleTest()
   399  
   400  	for i := 1; i < 260; i++ {
   401  		singlePaddingTest(t, i)
   402  	}
   403  
   404  	lim := 256 * 256
   405  	for i := lim - 5; i < lim+2; i++ {
   406  		singlePaddingTest(t, i)
   407  	}
   408  
   409  	for i := 0; i < 256; i++ {
   410  		n := mrand.Intn(256*254) + 256
   411  		singlePaddingTest(t, n)
   412  	}
   413  
   414  	for i := 0; i < 256; i++ {
   415  		n := mrand.Intn(256*1024) + 256*256
   416  		singlePaddingTest(t, n)
   417  	}
   418  }
   419  
   420  func TestPaddingAppendedToSymMessages(t *testing.T) {
   421  	params := &MessageParams{
   422  		Payload: make([]byte, 246),
   423  		KeySym:  make([]byte, aesKeyLength),
   424  	}
   425  
   426  	// Simulate a message with a payload just under 256 so that
   427  	// payload + flag + aesnonce > 256. Check that the result
   428  	// is padded on the next 256 boundary.
   429  	msg := sentMessage{}
   430  	msg.Raw = make([]byte, len(params.Payload)+1+AESNonceLength)
   431  
   432  	err := msg.appendPadding(params)
   433  
   434  	if err != nil {
   435  		t.Fatalf("Error appending padding to message %v", err)
   436  		return
   437  	}
   438  
   439  	if len(msg.Raw) != 512 {
   440  		t.Errorf("Invalid size %d != 512", len(msg.Raw))
   441  	}
   442  }
   443  
   444  func TestPaddingAppendedToSymMessagesWithSignature(t *testing.T) {
   445  	params := &MessageParams{
   446  		Payload: make([]byte, 246),
   447  		KeySym:  make([]byte, aesKeyLength),
   448  	}
   449  
   450  	pSrc, err := crypto.GenerateKey()
   451  
   452  	if err != nil {
   453  		t.Fatalf("Error creating the signature key %v", err)
   454  		return
   455  	}
   456  	params.Src = pSrc
   457  
   458  	// Simulate a message with a payload just under 256 so that
   459  	// payload + flag + aesnonce > 256. Check that the result
   460  	// is padded on the next 256 boundary.
   461  	msg := sentMessage{}
   462  	msg.Raw = make([]byte, len(params.Payload)+1+AESNonceLength+signatureLength)
   463  
   464  	err = msg.appendPadding(params)
   465  
   466  	if err != nil {
   467  		t.Fatalf("Error appending padding to message %v", err)
   468  		return
   469  	}
   470  
   471  	if len(msg.Raw) != 512 {
   472  		t.Errorf("Invalid size %d != 512", len(msg.Raw))
   473  	}
   474  }