blob: 7cc7a8bb8760fbafe81f6315e27c041af4386461 [file] [log] [blame]
Ankurf21ac832014-08-05 17:45:31 -07001package serialization
2
3import (
4 "bytes"
5 "crypto/ecdsa"
Ankur3ebf4ee2014-08-15 15:35:00 -07006 "crypto/elliptic"
7 "crypto/rand"
Ankurf21ac832014-08-05 17:45:31 -07008 "fmt"
9 "io"
10 "io/ioutil"
11 mrand "math/rand"
12 "reflect"
13 "strings"
14 "testing"
15
16 "veyron/lib/testutil"
Ankur3ebf4ee2014-08-15 15:35:00 -070017 "veyron/security/signing"
Ankurf21ac832014-08-05 17:45:31 -070018
Ankurf21ac832014-08-05 17:45:31 -070019 "veyron2/security"
20)
21
22type bufferCloser struct {
23 bytes.Buffer
24}
25
26func (*bufferCloser) Close() error {
27 return nil
28}
29
30func signingWrite(d, s io.WriteCloser, signer security.Signer, writeList [][]byte, opts *Options) error {
31 swc, err := NewSigningWriteCloser(d, s, signer, opts)
32 if err != nil {
33 return fmt.Errorf("NewSigningWriteCloser failed: %s", err)
34 }
35 for _, b := range writeList {
36 if _, err := swc.Write(b); err != nil {
37 return fmt.Errorf("signingWriteCloser.Write failed: %s", err)
38 }
39 }
40 if err := swc.Close(); err != nil {
41 return fmt.Errorf("signingWriteCloser.Close failed: %s", err)
42 }
43 return nil
44}
45
46func verifyingRead(d, s io.Reader, key *ecdsa.PublicKey) ([]byte, error) {
47 vr, err := NewVerifyingReader(d, s, key)
48 if err != nil {
49 return nil, fmt.Errorf("NewVerifyingReader failed: %s", err)
50 }
51 return ioutil.ReadAll(vr)
52}
53
54func newSigner() security.Signer {
Ankur3ebf4ee2014-08-15 15:35:00 -070055 key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
Ankurf21ac832014-08-05 17:45:31 -070056 if err != nil {
57 panic(err)
58 }
Ankur3ebf4ee2014-08-15 15:35:00 -070059 return signing.NewClearSigner(key)
Ankurf21ac832014-08-05 17:45:31 -070060}
61
62func matchesErrorPattern(err error, pattern string) bool {
63 if (len(pattern) == 0) != (err == nil) {
64 return false
65 }
66 return err == nil || strings.Index(err.Error(), pattern) >= 0
67}
68
69func TestRoundTrip(t *testing.T) {
70 signer := newSigner()
71 d, s := &bufferCloser{}, &bufferCloser{}
72
73 testdata := []struct {
74 writeList [][]byte
75 opts *Options
76 }{
77 {[][]byte{testutil.RandomBytes(1)}, nil},
78 {[][]byte{testutil.RandomBytes(100)}, nil},
79 {[][]byte{testutil.RandomBytes(100)}, &Options{ChunkSizeBytes: 10}},
80 {[][]byte{testutil.RandomBytes(25), testutil.RandomBytes(15), testutil.RandomBytes(60), testutil.RandomBytes(5)}, &Options{ChunkSizeBytes: 7}},
81 }
82 for _, test := range testdata {
83 d.Reset()
84 s.Reset()
85
86 if err := signingWrite(d, s, signer, test.writeList, test.opts); err != nil {
87 t.Errorf("signingWrite(_, _, %v, %v) failed: %s", test.writeList, test.opts, err)
88 continue
89 }
90 dataRead, err := verifyingRead(d, s, signer.PublicKey())
91 if err != nil {
92 t.Errorf("verifyingRead failed: %s", err)
93 continue
94 }
95
96 dataWritten := bytes.Join(test.writeList, nil)
97 if !reflect.DeepEqual(dataRead, dataWritten) {
98 t.Errorf("Read-Write mismatch: data read: %v, data written: %v", dataRead, dataWritten)
99 continue
100 }
101 }
102}
103
104func TestIntegrityAndAuthenticity(t *testing.T) {
105 tamper := func(b []byte) []byte {
106 c := make([]byte, len(b))
107 copy(c, b)
108 c[mrand.Int()%len(b)] += 1
109 return c
110 }
111
112 signer := newSigner()
113 d, s := &bufferCloser{}, &bufferCloser{}
114 if err := signingWrite(d, s, signer, [][]byte{testutil.RandomBytes(100)}, &Options{ChunkSizeBytes: 7}); err != nil {
115 t.Fatalf("signingWrite failed: %s", err)
116 }
117
118 // copy the data and signature bytes written.
119 dataBytes := d.Bytes()
120 sigBytes := s.Bytes()
121
122 // Test that any tampering of the data bytes, or any change
123 // to the signer causes a verifyingRead to fail.
124 testdata := []struct {
125 dataBytes, sigBytes []byte
126 key *ecdsa.PublicKey
127 wantErr string
128 }{
129 {dataBytes, sigBytes, signer.PublicKey(), ""},
130 {dataBytes, sigBytes, newSigner().PublicKey(), "signature verification failed"},
131 {tamper(dataBytes), sigBytes, signer.PublicKey(), "data has been modified"},
132 }
133 for _, test := range testdata {
134 if _, err := verifyingRead(&bufferCloser{*bytes.NewBuffer(test.dataBytes)}, &bufferCloser{*bytes.NewBuffer(test.sigBytes)}, test.key); !matchesErrorPattern(err, test.wantErr) {
135 t.Errorf("verifyingRead: got error: %s, want to match: %v", err, test.wantErr)
136 }
137 }
138}