OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / crypto / otr / otr_test.go
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 }