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  }