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, ¶ms.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, ¶ms.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 }