OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / crypto / bcrypt / bcrypt_test.go
1 // Copyright 2011 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 bcrypt
6
7 import (
8         "bytes"
9         "fmt"
10         "testing"
11 )
12
13 func TestBcryptingIsEasy(t *testing.T) {
14         pass := []byte("mypassword")
15         hp, err := GenerateFromPassword(pass, 0)
16         if err != nil {
17                 t.Fatalf("GenerateFromPassword error: %s", err)
18         }
19
20         if CompareHashAndPassword(hp, pass) != nil {
21                 t.Errorf("%v should hash %s correctly", hp, pass)
22         }
23
24         notPass := "notthepass"
25         err = CompareHashAndPassword(hp, []byte(notPass))
26         if err != ErrMismatchedHashAndPassword {
27                 t.Errorf("%v and %s should be mismatched", hp, notPass)
28         }
29 }
30
31 func TestBcryptingIsCorrect(t *testing.T) {
32         pass := []byte("allmine")
33         salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
34         expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
35
36         hash, err := bcrypt(pass, 10, salt)
37         if err != nil {
38                 t.Fatalf("bcrypt blew up: %v", err)
39         }
40         if !bytes.HasSuffix(expectedHash, hash) {
41                 t.Errorf("%v should be the suffix of %v", hash, expectedHash)
42         }
43
44         h, err := newFromHash(expectedHash)
45         if err != nil {
46                 t.Errorf("Unable to parse %s: %v", string(expectedHash), err)
47         }
48
49         // This is not the safe way to compare these hashes. We do this only for
50         // testing clarity. Use bcrypt.CompareHashAndPassword()
51         if err == nil && !bytes.Equal(expectedHash, h.Hash()) {
52                 t.Errorf("Parsed hash %v should equal %v", h.Hash(), expectedHash)
53         }
54 }
55
56 func TestVeryShortPasswords(t *testing.T) {
57         key := []byte("k")
58         salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
59         _, err := bcrypt(key, 10, salt)
60         if err != nil {
61                 t.Errorf("One byte key resulted in error: %s", err)
62         }
63 }
64
65 func TestTooLongPasswordsWork(t *testing.T) {
66         salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
67         // One byte over the usual 56 byte limit that blowfish has
68         tooLongPass := []byte("012345678901234567890123456789012345678901234567890123456")
69         tooLongExpected := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C")
70         hash, err := bcrypt(tooLongPass, 10, salt)
71         if err != nil {
72                 t.Fatalf("bcrypt blew up on long password: %v", err)
73         }
74         if !bytes.HasSuffix(tooLongExpected, hash) {
75                 t.Errorf("%v should be the suffix of %v", hash, tooLongExpected)
76         }
77 }
78
79 type InvalidHashTest struct {
80         err  error
81         hash []byte
82 }
83
84 var invalidTests = []InvalidHashTest{
85         {ErrHashTooShort, []byte("$2a$10$fooo")},
86         {ErrHashTooShort, []byte("$2a")},
87         {HashVersionTooNewError('3'), []byte("$3a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
88         {InvalidHashPrefixError('%'), []byte("%2a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
89         {InvalidCostError(32), []byte("$2a$32$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
90 }
91
92 func TestInvalidHashErrors(t *testing.T) {
93         check := func(name string, expected, err error) {
94                 if err == nil {
95                         t.Errorf("%s: Should have returned an error", name)
96                 }
97                 if err != nil && err != expected {
98                         t.Errorf("%s gave err %v but should have given %v", name, err, expected)
99                 }
100         }
101         for _, iht := range invalidTests {
102                 _, err := newFromHash(iht.hash)
103                 check("newFromHash", iht.err, err)
104                 err = CompareHashAndPassword(iht.hash, []byte("anything"))
105                 check("CompareHashAndPassword", iht.err, err)
106         }
107 }
108
109 func TestUnpaddedBase64Encoding(t *testing.T) {
110         original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 32, 30, 109, 243, 30}
111         encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe")
112
113         encoded := base64Encode(original)
114
115         if !bytes.Equal(encodedOriginal, encoded) {
116                 t.Errorf("Encoded %v should have equaled %v", encoded, encodedOriginal)
117         }
118
119         decoded, err := base64Decode(encodedOriginal)
120         if err != nil {
121                 t.Fatalf("base64Decode blew up: %s", err)
122         }
123
124         if !bytes.Equal(decoded, original) {
125                 t.Errorf("Decoded %v should have equaled %v", decoded, original)
126         }
127 }
128
129 func TestCost(t *testing.T) {
130         suffix := "XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C"
131         for _, vers := range []string{"2a", "2"} {
132                 for _, cost := range []int{4, 10} {
133                         s := fmt.Sprintf("$%s$%02d$%s", vers, cost, suffix)
134                         h := []byte(s)
135                         actual, err := Cost(h)
136                         if err != nil {
137                                 t.Errorf("Cost, error: %s", err)
138                                 continue
139                         }
140                         if actual != cost {
141                                 t.Errorf("Cost, expected: %d, actual: %d", cost, actual)
142                         }
143                 }
144         }
145         _, err := Cost([]byte("$a$a$" + suffix))
146         if err == nil {
147                 t.Errorf("Cost, malformed but no error returned")
148         }
149 }
150
151 func TestCostValidationInHash(t *testing.T) {
152         if testing.Short() {
153                 return
154         }
155
156         pass := []byte("mypassword")
157
158         for c := 0; c < MinCost; c++ {
159                 p, _ := newFromPassword(pass, c)
160                 if p.cost != DefaultCost {
161                         t.Errorf("newFromPassword should default costs below %d to %d, but was %d", MinCost, DefaultCost, p.cost)
162                 }
163         }
164
165         p, _ := newFromPassword(pass, 14)
166         if p.cost != 14 {
167                 t.Errorf("newFromPassword should default cost to 14, but was %d", p.cost)
168         }
169
170         hp, _ := newFromHash(p.Hash())
171         if p.cost != hp.cost {
172                 t.Errorf("newFromHash should maintain the cost at %d, but was %d", p.cost, hp.cost)
173         }
174
175         _, err := newFromPassword(pass, 32)
176         if err == nil {
177                 t.Fatalf("newFromPassword: should return a cost error")
178         }
179         if err != InvalidCostError(32) {
180                 t.Errorf("newFromPassword: should return cost error, got %#v", err)
181         }
182 }
183
184 func TestCostReturnsWithLeadingZeroes(t *testing.T) {
185         hp, _ := newFromPassword([]byte("abcdefgh"), 7)
186         cost := hp.Hash()[4:7]
187         expected := []byte("07$")
188
189         if !bytes.Equal(expected, cost) {
190                 t.Errorf("single digit costs in hash should have leading zeros: was %v instead of %v", cost, expected)
191         }
192 }
193
194 func TestMinorNotRequired(t *testing.T) {
195         noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
196         h, err := newFromHash(noMinorHash)
197         if err != nil {
198                 t.Fatalf("No minor hash blew up: %s", err)
199         }
200         if h.minor != 0 {
201                 t.Errorf("Should leave minor version at 0, but was %d", h.minor)
202         }
203
204         if !bytes.Equal(noMinorHash, h.Hash()) {
205                 t.Errorf("Should generate hash %v, but created %v", noMinorHash, h.Hash())
206         }
207 }
208
209 func BenchmarkEqual(b *testing.B) {
210         b.StopTimer()
211         passwd := []byte("somepasswordyoulike")
212         hash, _ := GenerateFromPassword(passwd, 10)
213         b.StartTimer()
214         for i := 0; i < b.N; i++ {
215                 CompareHashAndPassword(hash, passwd)
216         }
217 }
218
219 func BenchmarkGeneration(b *testing.B) {
220         b.StopTimer()
221         passwd := []byte("mylongpassword1234")
222         b.StartTimer()
223         for i := 0; i < b.N; i++ {
224                 GenerateFromPassword(passwd, 10)
225         }
226 }
227
228 // See Issue https://github.com/golang/go/issues/20425.
229 func TestNoSideEffectsFromCompare(t *testing.T) {
230         source := []byte("passw0rd123456")
231         password := source[:len(source)-6]
232         token := source[len(source)-6:]
233         want := make([]byte, len(source))
234         copy(want, source)
235
236         wantHash := []byte("$2a$10$LK9XRuhNxHHCvjX3tdkRKei1QiCDUKrJRhZv7WWZPuQGRUM92rOUa")
237         _ = CompareHashAndPassword(wantHash, password)
238
239         got := bytes.Join([][]byte{password, token}, []byte(""))
240         if !bytes.Equal(got, want) {
241                 t.Errorf("got=%q want=%q", got, want)
242         }
243 }