github.com/maenmax/kairep@v0.0.0-20210218001208-55bf3df36788/src/golang.org/x/crypto/otr/otr_test.go (about) 1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package otr 6 7 import ( 8 "bufio" 9 "bytes" 10 "crypto/rand" 11 "encoding/hex" 12 "math/big" 13 "os" 14 "os/exec" 15 "testing" 16 ) 17 18 var isQueryTests = []struct { 19 msg string 20 expectedVersion int 21 }{ 22 {"foo", 0}, 23 {"?OtR", 0}, 24 {"?OtR?", 0}, 25 {"?OTR?", 0}, 26 {"?OTRv?", 0}, 27 {"?OTRv1?", 0}, 28 {"?OTR?v1?", 0}, 29 {"?OTR?v?", 0}, 30 {"?OTR?v2?", 2}, 31 {"?OTRv2?", 2}, 32 {"?OTRv23?", 2}, 33 {"?OTRv23 ?", 0}, 34 } 35 36 func TestIsQuery(t *testing.T) { 37 for i, test := range isQueryTests { 38 version := isQuery([]byte(test.msg)) 39 if version != test.expectedVersion { 40 t.Errorf("#%d: got %d, want %d", i, version, test.expectedVersion) 41 } 42 } 43 } 44 45 var alicePrivateKeyHex = "000000000080c81c2cb2eb729b7e6fd48e975a932c638b3a9055478583afa46755683e30102447f6da2d8bec9f386bbb5da6403b0040fee8650b6ab2d7f32c55ab017ae9b6aec8c324ab5844784e9a80e194830d548fb7f09a0410df2c4d5c8bc2b3e9ad484e65412be689cf0834694e0839fb2954021521ffdffb8f5c32c14dbf2020b3ce7500000014da4591d58def96de61aea7b04a8405fe1609308d000000808ddd5cb0b9d66956e3dea5a915d9aba9d8a6e7053b74dadb2fc52f9fe4e5bcc487d2305485ed95fed026ad93f06ebb8c9e8baf693b7887132c7ffdd3b0f72f4002ff4ed56583ca7c54458f8c068ca3e8a4dfa309d1dd5d34e2a4b68e6f4338835e5e0fb4317c9e4c7e4806dafda3ef459cd563775a586dd91b1319f72621bf3f00000080b8147e74d8c45e6318c37731b8b33b984a795b3653c2cd1d65cc99efe097cb7eb2fa49569bab5aab6e8a1c261a27d0f7840a5e80b317e6683042b59b6dceca2879c6ffc877a465be690c15e4a42f9a7588e79b10faac11b1ce3741fcef7aba8ce05327a2c16d279ee1b3d77eb783fb10e3356caa25635331e26dd42b8396c4d00000001420bec691fea37ecea58a5c717142f0b804452f57" 46 47 var aliceFingerprintHex = "0bb01c360424522e94ee9c346ce877a1a4288b2f" 48 49 var bobPrivateKeyHex = "000000000080a5138eb3d3eb9c1d85716faecadb718f87d31aaed1157671d7fee7e488f95e8e0ba60ad449ec732710a7dec5190f7182af2e2f98312d98497221dff160fd68033dd4f3a33b7c078d0d9f66e26847e76ca7447d4bab35486045090572863d9e4454777f24d6706f63e02548dfec2d0a620af37bbc1d24f884708a212c343b480d00000014e9c58f0ea21a5e4dfd9f44b6a9f7f6a9961a8fa9000000803c4d111aebd62d3c50c2889d420a32cdf1e98b70affcc1fcf44d59cca2eb019f6b774ef88153fb9b9615441a5fe25ea2d11b74ce922ca0232bd81b3c0fcac2a95b20cb6e6c0c5c1ace2e26f65dc43c751af0edbb10d669890e8ab6beea91410b8b2187af1a8347627a06ecea7e0f772c28aae9461301e83884860c9b656c722f0000008065af8625a555ea0e008cd04743671a3cda21162e83af045725db2eb2bb52712708dc0cc1a84c08b3649b88a966974bde27d8612c2861792ec9f08786a246fcadd6d8d3a81a32287745f309238f47618c2bd7612cb8b02d940571e0f30b96420bcd462ff542901b46109b1e5ad6423744448d20a57818a8cbb1647d0fea3b664e0000001440f9f2eb554cb00d45a5826b54bfa419b6980e48" 50 51 func TestKeySerialization(t *testing.T) { 52 var priv PrivateKey 53 alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex) 54 rest, ok := priv.Parse(alicePrivateKey) 55 if !ok { 56 t.Error("failed to parse private key") 57 } 58 if len(rest) > 0 { 59 t.Error("data remaining after parsing private key") 60 } 61 62 out := priv.Serialize(nil) 63 if !bytes.Equal(alicePrivateKey, out) { 64 t.Errorf("serialization (%x) is not equal to original (%x)", out, alicePrivateKey) 65 } 66 67 aliceFingerprint, _ := hex.DecodeString(aliceFingerprintHex) 68 fingerprint := priv.PublicKey.Fingerprint() 69 if !bytes.Equal(aliceFingerprint, fingerprint) { 70 t.Errorf("fingerprint (%x) is not equal to expected value (%x)", fingerprint, aliceFingerprint) 71 } 72 } 73 74 const libOTRPrivateKey = `(privkeys 75 (account 76 (name "foo@example.com") 77 (protocol prpl-jabber) 78 (private-key 79 (dsa 80 (p #00FC07ABCF0DC916AFF6E9AE47BEF60C7AB9B4D6B2469E436630E36F8A489BE812486A09F30B71224508654940A835301ACC525A4FF133FC152CC53DCC59D65C30A54F1993FE13FE63E5823D4C746DB21B90F9B9C00B49EC7404AB1D929BA7FBA12F2E45C6E0A651689750E8528AB8C031D3561FECEE72EBB4A090D450A9B7A857#) 81 (q #00997BD266EF7B1F60A5C23F3A741F2AEFD07A2081#) 82 (g #535E360E8A95EBA46A4F7DE50AD6E9B2A6DB785A66B64EB9F20338D2A3E8FB0E94725848F1AA6CC567CB83A1CC517EC806F2E92EAE71457E80B2210A189B91250779434B41FC8A8873F6DB94BEA7D177F5D59E7E114EE10A49CFD9CEF88AE43387023B672927BA74B04EB6BBB5E57597766A2F9CE3857D7ACE3E1E3BC1FC6F26#) 83 (y #0AC8670AD767D7A8D9D14CC1AC6744CD7D76F993B77FFD9E39DF01E5A6536EF65E775FCEF2A983E2A19BD6415500F6979715D9FD1257E1FE2B6F5E1E74B333079E7C880D39868462A93454B41877BE62E5EF0A041C2EE9C9E76BD1E12AE25D9628DECB097025DD625EF49C3258A1A3C0FF501E3DC673B76D7BABF349009B6ECF#) 84 (x #14D0345A3562C480A039E3C72764F72D79043216#) 85 ) 86 ) 87 ) 88 )` 89 90 func TestParseLibOTRPrivateKey(t *testing.T) { 91 var priv PrivateKey 92 93 if !priv.Import([]byte(libOTRPrivateKey)) { 94 t.Fatalf("Failed to import sample private key") 95 } 96 } 97 98 func TestSignVerify(t *testing.T) { 99 var priv PrivateKey 100 alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex) 101 _, ok := priv.Parse(alicePrivateKey) 102 if !ok { 103 t.Error("failed to parse private key") 104 } 105 106 var msg [32]byte 107 rand.Reader.Read(msg[:]) 108 109 sig := priv.Sign(rand.Reader, msg[:]) 110 rest, ok := priv.PublicKey.Verify(msg[:], sig) 111 if !ok { 112 t.Errorf("signature (%x) of %x failed to verify", sig, msg[:]) 113 } else if len(rest) > 0 { 114 t.Error("signature data remains after verification") 115 } 116 117 sig[10] ^= 80 118 _, ok = priv.PublicKey.Verify(msg[:], sig) 119 if ok { 120 t.Errorf("corrupted signature (%x) of %x verified", sig, msg[:]) 121 } 122 } 123 124 func setupConversation(t *testing.T) (alice, bob *Conversation) { 125 alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex) 126 bobPrivateKey, _ := hex.DecodeString(bobPrivateKeyHex) 127 128 alice, bob = new(Conversation), new(Conversation) 129 130 alice.PrivateKey = new(PrivateKey) 131 bob.PrivateKey = new(PrivateKey) 132 alice.PrivateKey.Parse(alicePrivateKey) 133 bob.PrivateKey.Parse(bobPrivateKey) 134 alice.FragmentSize = 100 135 bob.FragmentSize = 100 136 137 if alice.IsEncrypted() { 138 t.Error("Alice believes that the conversation is secure before we've started") 139 } 140 if bob.IsEncrypted() { 141 t.Error("Bob believes that the conversation is secure before we've started") 142 } 143 144 performHandshake(t, alice, bob) 145 return alice, bob 146 } 147 148 func performHandshake(t *testing.T, alice, bob *Conversation) { 149 var alicesMessage, bobsMessage [][]byte 150 var out []byte 151 var aliceChange, bobChange SecurityChange 152 var err error 153 alicesMessage = append(alicesMessage, []byte(QueryMessage)) 154 155 for round := 0; len(alicesMessage) > 0 || len(bobsMessage) > 0; round++ { 156 bobsMessage = nil 157 for i, msg := range alicesMessage { 158 out, _, bobChange, bobsMessage, err = bob.Receive(msg) 159 if len(out) > 0 { 160 t.Errorf("Bob generated output during key exchange, round %d, message %d", round, i) 161 } 162 if err != nil { 163 t.Fatalf("Bob returned an error, round %d, message %d (%x): %s", round, i, msg, err) 164 } 165 if len(bobsMessage) > 0 && i != len(alicesMessage)-1 { 166 t.Errorf("Bob produced output while processing a fragment, round %d, message %d", round, i) 167 } 168 } 169 170 alicesMessage = nil 171 for i, msg := range bobsMessage { 172 out, _, aliceChange, alicesMessage, err = alice.Receive(msg) 173 if len(out) > 0 { 174 t.Errorf("Alice generated output during key exchange, round %d, message %d", round, i) 175 } 176 if err != nil { 177 t.Fatalf("Alice returned an error, round %d, message %d (%x): %s", round, i, msg, err) 178 } 179 if len(alicesMessage) > 0 && i != len(bobsMessage)-1 { 180 t.Errorf("Alice produced output while processing a fragment, round %d, message %d", round, i) 181 } 182 } 183 } 184 185 if aliceChange != NewKeys { 186 t.Errorf("Alice terminated without signaling new keys") 187 } 188 if bobChange != NewKeys { 189 t.Errorf("Bob terminated without signaling new keys") 190 } 191 192 if !bytes.Equal(alice.SSID[:], bob.SSID[:]) { 193 t.Errorf("Session identifiers don't match. Alice has %x, Bob has %x", alice.SSID[:], bob.SSID[:]) 194 } 195 196 if !alice.IsEncrypted() { 197 t.Error("Alice doesn't believe that the conversation is secure") 198 } 199 if !bob.IsEncrypted() { 200 t.Error("Bob doesn't believe that the conversation is secure") 201 } 202 } 203 204 const ( 205 firstRoundTrip = iota 206 subsequentRoundTrip 207 noMACKeyCheck 208 ) 209 210 func roundTrip(t *testing.T, alice, bob *Conversation, message []byte, macKeyCheck int) { 211 alicesMessage, err := alice.Send(message) 212 if err != nil { 213 t.Errorf("Error from Alice sending message: %s", err) 214 } 215 216 if len(alice.oldMACs) != 0 { 217 t.Errorf("Alice has not revealed all MAC keys") 218 } 219 220 for i, msg := range alicesMessage { 221 out, encrypted, _, _, err := bob.Receive(msg) 222 223 if err != nil { 224 t.Errorf("Error generated while processing test message: %s", err.Error()) 225 } 226 if len(out) > 0 { 227 if i != len(alicesMessage)-1 { 228 t.Fatal("Bob produced a message while processing a fragment of Alice's") 229 } 230 if !encrypted { 231 t.Errorf("Message was not marked as encrypted") 232 } 233 if !bytes.Equal(out, message) { 234 t.Errorf("Message corrupted: got %x, want %x", out, message) 235 } 236 } 237 } 238 239 switch macKeyCheck { 240 case firstRoundTrip: 241 if len(bob.oldMACs) != 0 { 242 t.Errorf("Bob should not have MAC keys to reveal") 243 } 244 case subsequentRoundTrip: 245 if len(bob.oldMACs) != 40 { 246 t.Errorf("Bob has %d bytes of MAC keys to reveal, but should have 40", len(bob.oldMACs)) 247 } 248 } 249 250 bobsMessage, err := bob.Send(message) 251 if err != nil { 252 t.Errorf("Error from Bob sending message: %s", err) 253 } 254 255 if len(bob.oldMACs) != 0 { 256 t.Errorf("Bob has not revealed all MAC keys") 257 } 258 259 for i, msg := range bobsMessage { 260 out, encrypted, _, _, err := alice.Receive(msg) 261 262 if err != nil { 263 t.Errorf("Error generated while processing test message: %s", err.Error()) 264 } 265 if len(out) > 0 { 266 if i != len(bobsMessage)-1 { 267 t.Fatal("Alice produced a message while processing a fragment of Bob's") 268 } 269 if !encrypted { 270 t.Errorf("Message was not marked as encrypted") 271 } 272 if !bytes.Equal(out, message) { 273 t.Errorf("Message corrupted: got %x, want %x", out, message) 274 } 275 } 276 } 277 278 switch macKeyCheck { 279 case firstRoundTrip: 280 if len(alice.oldMACs) != 20 { 281 t.Errorf("Alice has %d bytes of MAC keys to reveal, but should have 20", len(alice.oldMACs)) 282 } 283 case subsequentRoundTrip: 284 if len(alice.oldMACs) != 40 { 285 t.Errorf("Alice has %d bytes of MAC keys to reveal, but should have 40", len(alice.oldMACs)) 286 } 287 } 288 } 289 290 func TestConversation(t *testing.T) { 291 alice, bob := setupConversation(t) 292 293 var testMessages = [][]byte{ 294 []byte("hello"), []byte("bye"), 295 } 296 297 roundTripType := firstRoundTrip 298 299 for _, testMessage := range testMessages { 300 roundTrip(t, alice, bob, testMessage, roundTripType) 301 roundTripType = subsequentRoundTrip 302 } 303 } 304 305 func TestGoodSMP(t *testing.T) { 306 var alice, bob Conversation 307 308 alice.smp.secret = new(big.Int).SetInt64(42) 309 bob.smp.secret = alice.smp.secret 310 311 var alicesMessages, bobsMessages []tlv 312 var aliceComplete, bobComplete bool 313 var err error 314 var out tlv 315 316 alicesMessages = alice.startSMP("") 317 for round := 0; len(alicesMessages) > 0 || len(bobsMessages) > 0; round++ { 318 bobsMessages = bobsMessages[:0] 319 for i, msg := range alicesMessages { 320 out, bobComplete, err = bob.processSMP(msg) 321 if err != nil { 322 t.Errorf("Error from Bob in round %d: %s", round, err) 323 } 324 if bobComplete && i != len(alicesMessages)-1 { 325 t.Errorf("Bob returned a completed signal before processing all of Alice's messages in round %d", round) 326 } 327 if out.typ != 0 { 328 bobsMessages = append(bobsMessages, out) 329 } 330 } 331 332 alicesMessages = alicesMessages[:0] 333 for i, msg := range bobsMessages { 334 out, aliceComplete, err = alice.processSMP(msg) 335 if err != nil { 336 t.Errorf("Error from Alice in round %d: %s", round, err) 337 } 338 if aliceComplete && i != len(bobsMessages)-1 { 339 t.Errorf("Alice returned a completed signal before processing all of Bob's messages in round %d", round) 340 } 341 if out.typ != 0 { 342 alicesMessages = append(alicesMessages, out) 343 } 344 } 345 } 346 347 if !aliceComplete || !bobComplete { 348 t.Errorf("SMP completed without both sides reporting success: alice: %v, bob: %v\n", aliceComplete, bobComplete) 349 } 350 } 351 352 func TestBadSMP(t *testing.T) { 353 var alice, bob Conversation 354 355 alice.smp.secret = new(big.Int).SetInt64(42) 356 bob.smp.secret = new(big.Int).SetInt64(43) 357 358 var alicesMessages, bobsMessages []tlv 359 360 alicesMessages = alice.startSMP("") 361 for round := 0; len(alicesMessages) > 0 || len(bobsMessages) > 0; round++ { 362 bobsMessages = bobsMessages[:0] 363 for _, msg := range alicesMessages { 364 out, complete, _ := bob.processSMP(msg) 365 if complete { 366 t.Errorf("Bob signaled completion in round %d", round) 367 } 368 if out.typ != 0 { 369 bobsMessages = append(bobsMessages, out) 370 } 371 } 372 373 alicesMessages = alicesMessages[:0] 374 for _, msg := range bobsMessages { 375 out, complete, _ := alice.processSMP(msg) 376 if complete { 377 t.Errorf("Alice signaled completion in round %d", round) 378 } 379 if out.typ != 0 { 380 alicesMessages = append(alicesMessages, out) 381 } 382 } 383 } 384 } 385 386 func TestRehandshaking(t *testing.T) { 387 alice, bob := setupConversation(t) 388 roundTrip(t, alice, bob, []byte("test"), firstRoundTrip) 389 roundTrip(t, alice, bob, []byte("test 2"), subsequentRoundTrip) 390 roundTrip(t, alice, bob, []byte("test 3"), subsequentRoundTrip) 391 roundTrip(t, alice, bob, []byte("test 4"), subsequentRoundTrip) 392 roundTrip(t, alice, bob, []byte("test 5"), subsequentRoundTrip) 393 roundTrip(t, alice, bob, []byte("test 6"), subsequentRoundTrip) 394 roundTrip(t, alice, bob, []byte("test 7"), subsequentRoundTrip) 395 roundTrip(t, alice, bob, []byte("test 8"), subsequentRoundTrip) 396 performHandshake(t, alice, bob) 397 roundTrip(t, alice, bob, []byte("test"), noMACKeyCheck) 398 roundTrip(t, alice, bob, []byte("test 2"), noMACKeyCheck) 399 } 400 401 func TestAgainstLibOTR(t *testing.T) { 402 // This test requires otr.c.test to be built as /tmp/a.out. 403 // If enabled, this tests runs forever performing OTR handshakes in a 404 // loop. 405 return 406 407 alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex) 408 var alice Conversation 409 alice.PrivateKey = new(PrivateKey) 410 alice.PrivateKey.Parse(alicePrivateKey) 411 412 cmd := exec.Command("/tmp/a.out") 413 cmd.Stderr = os.Stderr 414 415 out, err := cmd.StdinPipe() 416 if err != nil { 417 t.Fatal(err) 418 } 419 defer out.Close() 420 stdout, err := cmd.StdoutPipe() 421 if err != nil { 422 t.Fatal(err) 423 } 424 in := bufio.NewReader(stdout) 425 426 if err := cmd.Start(); err != nil { 427 t.Fatal(err) 428 } 429 430 out.Write([]byte(QueryMessage)) 431 out.Write([]byte("\n")) 432 var expectedText = []byte("test message") 433 434 for { 435 line, isPrefix, err := in.ReadLine() 436 if isPrefix { 437 t.Fatal("line from subprocess too long") 438 } 439 if err != nil { 440 t.Fatal(err) 441 } 442 text, encrypted, change, alicesMessage, err := alice.Receive(line) 443 if err != nil { 444 t.Fatal(err) 445 } 446 for _, msg := range alicesMessage { 447 out.Write(msg) 448 out.Write([]byte("\n")) 449 } 450 if change == NewKeys { 451 alicesMessage, err := alice.Send([]byte("Go -> libotr test message")) 452 if err != nil { 453 t.Fatalf("error sending message: %s", err.Error()) 454 } else { 455 for _, msg := range alicesMessage { 456 out.Write(msg) 457 out.Write([]byte("\n")) 458 } 459 } 460 } 461 if len(text) > 0 { 462 if !bytes.Equal(text, expectedText) { 463 t.Fatalf("expected %x, but got %x", expectedText, text) 464 } 465 if !encrypted { 466 t.Fatal("message wasn't encrypted") 467 } 468 } 469 } 470 }