github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/whisper/whisperv6/message_test.go (about)

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