~ubuntu-branches/ubuntu/utopic/hockeypuck/utopic-proposed

« back to all changes in this revision

Viewing changes to build/src/code.google.com/p/go.crypto/otr/otr_test.go

  • Committer: Package Import Robot
  • Author(s): Casey Marshall
  • Date: 2014-04-13 20:06:01 UTC
  • Revision ID: package-import@ubuntu.com-20140413200601-oxdlqn1gy0x8m55u
Tags: 1.0~rel20140413+7a1892a~trusty
Hockeypuck 1.0 release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 TestConversation(t *testing.T) {
 
125
        alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex)
 
126
        bobPrivateKey, _ := hex.DecodeString(bobPrivateKeyHex)
 
127
 
 
128
        var alice, bob Conversation
 
129
        alice.PrivateKey = new(PrivateKey)
 
130
        bob.PrivateKey = new(PrivateKey)
 
131
        alice.PrivateKey.Parse(alicePrivateKey)
 
132
        bob.PrivateKey.Parse(bobPrivateKey)
 
133
        alice.FragmentSize = 100
 
134
        bob.FragmentSize = 100
 
135
 
 
136
        var alicesMessage, bobsMessage [][]byte
 
137
        var out []byte
 
138
        var aliceChange, bobChange SecurityChange
 
139
        var err error
 
140
        alicesMessage = append(alicesMessage, []byte(QueryMessage))
 
141
 
 
142
        if alice.IsEncrypted() {
 
143
                t.Error("Alice believes that the conversation is secure before we've started")
 
144
        }
 
145
        if bob.IsEncrypted() {
 
146
                t.Error("Bob believes that the conversation is secure before we've started")
 
147
        }
 
148
 
 
149
        for round := 0; len(alicesMessage) > 0 || len(bobsMessage) > 0; round++ {
 
150
                bobsMessage = nil
 
151
                for i, msg := range alicesMessage {
 
152
                        out, _, bobChange, bobsMessage, err = bob.Receive(msg)
 
153
                        if len(out) > 0 {
 
154
                                t.Errorf("Bob generated output during key exchange, round %d, message %d", round, i)
 
155
                        }
 
156
                        if err != nil {
 
157
                                t.Fatalf("Bob returned an error, round %d, message %d (%x): %s", round, i, msg, err)
 
158
                        }
 
159
                        if len(bobsMessage) > 0 && i != len(alicesMessage)-1 {
 
160
                                t.Errorf("Bob produced output while processing a fragment, round %d, message %d", round, i)
 
161
                        }
 
162
                }
 
163
 
 
164
                alicesMessage = nil
 
165
                for i, msg := range bobsMessage {
 
166
                        out, _, aliceChange, alicesMessage, err = alice.Receive(msg)
 
167
                        if len(out) > 0 {
 
168
                                t.Errorf("Alice generated output during key exchange, round %d, message %d", round, i)
 
169
                        }
 
170
                        if err != nil {
 
171
                                t.Fatalf("Alice returned an error, round %d, message %d (%x): %s", round, i, msg, err)
 
172
                        }
 
173
                        if len(alicesMessage) > 0 && i != len(bobsMessage)-1 {
 
174
                                t.Errorf("Alice produced output while processing a fragment, round %d, message %d", round, i)
 
175
                        }
 
176
                }
 
177
        }
 
178
 
 
179
        if aliceChange != NewKeys {
 
180
                t.Errorf("Alice terminated without signaling new keys")
 
181
        }
 
182
        if bobChange != NewKeys {
 
183
                t.Errorf("Bob terminated without signaling new keys")
 
184
        }
 
185
 
 
186
        if !bytes.Equal(alice.SSID[:], bob.SSID[:]) {
 
187
                t.Errorf("Session identifiers don't match. Alice has %x, Bob has %x", alice.SSID[:], bob.SSID[:])
 
188
        }
 
189
 
 
190
        if !alice.IsEncrypted() {
 
191
                t.Error("Alice doesn't believe that the conversation is secure")
 
192
        }
 
193
        if !bob.IsEncrypted() {
 
194
                t.Error("Bob doesn't believe that the conversation is secure")
 
195
        }
 
196
 
 
197
        var testMessage = []byte("hello Bob")
 
198
        alicesMessage, err = alice.Send(testMessage)
 
199
        for i, msg := range alicesMessage {
 
200
                out, encrypted, _, _, err := bob.Receive(msg)
 
201
                if err != nil {
 
202
                        t.Errorf("Error generated while processing test message: %s", err.Error())
 
203
                }
 
204
                if len(out) > 0 {
 
205
                        if i != len(alicesMessage)-1 {
 
206
                                t.Fatal("Bob produced a message while processing a fragment of Alice's")
 
207
                        }
 
208
                        if !encrypted {
 
209
                                t.Errorf("Message was not marked as encrypted")
 
210
                        }
 
211
                        if !bytes.Equal(out, testMessage) {
 
212
                                t.Errorf("Message corrupted: got %x, want %x", out, testMessage)
 
213
                        }
 
214
                }
 
215
        }
 
216
}
 
217
 
 
218
func TestGoodSMP(t *testing.T) {
 
219
        var alice, bob Conversation
 
220
 
 
221
        alice.smp.secret = new(big.Int).SetInt64(42)
 
222
        bob.smp.secret = alice.smp.secret
 
223
 
 
224
        var alicesMessages, bobsMessages []tlv
 
225
        var aliceComplete, bobComplete bool
 
226
        var err error
 
227
        var out tlv
 
228
 
 
229
        alicesMessages = alice.startSMP("")
 
230
        for round := 0; len(alicesMessages) > 0 || len(bobsMessages) > 0; round++ {
 
231
                bobsMessages = bobsMessages[:0]
 
232
                for i, msg := range alicesMessages {
 
233
                        out, bobComplete, err = bob.processSMP(msg)
 
234
                        if err != nil {
 
235
                                t.Errorf("Error from Bob in round %d: %s", round, err)
 
236
                        }
 
237
                        if bobComplete && i != len(alicesMessages)-1 {
 
238
                                t.Errorf("Bob returned a completed signal before processing all of Alice's messages in round %d", round)
 
239
                        }
 
240
                        if out.typ != 0 {
 
241
                                bobsMessages = append(bobsMessages, out)
 
242
                        }
 
243
                }
 
244
 
 
245
                alicesMessages = alicesMessages[:0]
 
246
                for i, msg := range bobsMessages {
 
247
                        out, aliceComplete, err = alice.processSMP(msg)
 
248
                        if err != nil {
 
249
                                t.Errorf("Error from Alice in round %d: %s", round, err)
 
250
                        }
 
251
                        if aliceComplete && i != len(bobsMessages)-1 {
 
252
                                t.Errorf("Alice returned a completed signal before processing all of Bob's messages in round %d", round)
 
253
                        }
 
254
                        if out.typ != 0 {
 
255
                                alicesMessages = append(alicesMessages, out)
 
256
                        }
 
257
                }
 
258
        }
 
259
 
 
260
        if !aliceComplete || !bobComplete {
 
261
                t.Errorf("SMP completed without both sides reporting success: alice: %v, bob: %v\n", aliceComplete, bobComplete)
 
262
        }
 
263
}
 
264
 
 
265
func TestBadSMP(t *testing.T) {
 
266
        var alice, bob Conversation
 
267
 
 
268
        alice.smp.secret = new(big.Int).SetInt64(42)
 
269
        bob.smp.secret = new(big.Int).SetInt64(43)
 
270
 
 
271
        var alicesMessages, bobsMessages []tlv
 
272
 
 
273
        alicesMessages = alice.startSMP("")
 
274
        for round := 0; len(alicesMessages) > 0 || len(bobsMessages) > 0; round++ {
 
275
                bobsMessages = bobsMessages[:0]
 
276
                for _, msg := range alicesMessages {
 
277
                        out, complete, _ := bob.processSMP(msg)
 
278
                        if complete {
 
279
                                t.Errorf("Bob signaled completion in round %d", round)
 
280
                        }
 
281
                        if out.typ != 0 {
 
282
                                bobsMessages = append(bobsMessages, out)
 
283
                        }
 
284
                }
 
285
 
 
286
                alicesMessages = alicesMessages[:0]
 
287
                for _, msg := range bobsMessages {
 
288
                        out, complete, _ := alice.processSMP(msg)
 
289
                        if complete {
 
290
                                t.Errorf("Alice signaled completion in round %d", round)
 
291
                        }
 
292
                        if out.typ != 0 {
 
293
                                alicesMessages = append(alicesMessages, out)
 
294
                        }
 
295
                }
 
296
        }
 
297
}
 
298
 
 
299
func TestAgainstLibOTR(t *testing.T) {
 
300
        // This test requires otr.c.test to be built as /tmp/a.out.
 
301
        // If enabled, this tests runs forever performing OTR handshakes in a
 
302
        // loop.
 
303
        return
 
304
 
 
305
        alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex)
 
306
        var alice Conversation
 
307
        alice.PrivateKey = new(PrivateKey)
 
308
        alice.PrivateKey.Parse(alicePrivateKey)
 
309
 
 
310
        cmd := exec.Command("/tmp/a.out")
 
311
        cmd.Stderr = os.Stderr
 
312
 
 
313
        out, err := cmd.StdinPipe()
 
314
        if err != nil {
 
315
                t.Fatal(err)
 
316
        }
 
317
        defer out.Close()
 
318
        stdout, err := cmd.StdoutPipe()
 
319
        if err != nil {
 
320
                t.Fatal(err)
 
321
        }
 
322
        in := bufio.NewReader(stdout)
 
323
 
 
324
        if err := cmd.Start(); err != nil {
 
325
                t.Fatal(err)
 
326
        }
 
327
 
 
328
        out.Write([]byte(QueryMessage))
 
329
        out.Write([]byte("\n"))
 
330
        var expectedText = []byte("test message")
 
331
 
 
332
        for {
 
333
                line, isPrefix, err := in.ReadLine()
 
334
                if isPrefix {
 
335
                        t.Fatal("line from subprocess too long")
 
336
                }
 
337
                if err != nil {
 
338
                        t.Fatal(err)
 
339
                }
 
340
                text, encrypted, change, alicesMessage, err := alice.Receive(line)
 
341
                if err != nil {
 
342
                        t.Fatal(err)
 
343
                }
 
344
                for _, msg := range alicesMessage {
 
345
                        out.Write(msg)
 
346
                        out.Write([]byte("\n"))
 
347
                }
 
348
                if change == NewKeys {
 
349
                        alicesMessage, err := alice.Send([]byte("Go -> libotr test message"))
 
350
                        if err != nil {
 
351
                                t.Errorf("error sending message: %s", err.Error())
 
352
                        } else {
 
353
                                for _, msg := range alicesMessage {
 
354
                                        out.Write(msg)
 
355
                                        out.Write([]byte("\n"))
 
356
                                }
 
357
                        }
 
358
                }
 
359
                if len(text) > 0 {
 
360
                        if !bytes.Equal(text, expectedText) {
 
361
                                t.Errorf("expected %x, but got %x", expectedText, text)
 
362
                        }
 
363
                        if !encrypted {
 
364
                                t.Error("message wasn't encrypted")
 
365
                        }
 
366
                }
 
367
        }
 
368
}