Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(261)

Delta Between Two Patch Sets: src/pkg/crypto/bcrypt/bcrypt_test.go

Issue 4964078: code review 4964078: crypto/bcrypt: new package (Closed)
Left Patch Set: diff -r e54178c07218 https://go.googlecode.com/hg/ Created 12 years, 6 months ago
Right Patch Set: diff -r d21944c38c39 https://go.googlecode.com/hg/ Created 12 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/crypto/bcrypt/bcrypt.go ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2011 The Go Authors. All rights reserved. 1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package bcrypt 5 package bcrypt
6 6
7 import ( 7 import (
8 "bytes" 8 "bytes"
9 "os" 9 "os"
10 "testing" 10 "testing"
11 ) 11 )
12 12
13 func TestBcryptingIsEasy(t *testing.T) { 13 func TestBcryptingIsEasy(t *testing.T) {
14 pass := []byte("mypassword") 14 pass := []byte("mypassword")
15 hp, err := GenerateFromPassword(pass, 0) 15 hp, err := GenerateFromPassword(pass, 0)
16 if err != nil { 16 if err != nil {
17 » » t.Fatalf("NewFromPassword error: %s", err) 17 » » t.Fatalf("GenerateFromPassword error: %s", err)
18 } 18 }
19 19
20 if CompareHashAndPassword(hp, pass) != nil { 20 if CompareHashAndPassword(hp, pass) != nil {
21 t.Errorf("%v should hash %s correctly", hp, pass) 21 t.Errorf("%v should hash %s correctly", hp, pass)
22 }
23
24 notPass := "notthepass"
25 err = CompareHashAndPassword(hp, []byte(notPass))
26 if err != MismatchedHashAndPasswordError {
27 t.Errorf("%v and %s should be mismatched", hp, notPass)
22 } 28 }
23 } 29 }
24 30
25 func TestBcryptingIsCorrect(t *testing.T) { 31 func TestBcryptingIsCorrect(t *testing.T) {
26 pass := []byte("allmine") 32 pass := []byte("allmine")
27 salt := []byte("XajjQvNhvvRt5GSeFk1xFe") 33 salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
28 expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt. wU1qD4aFDcga") 34 expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt. wU1qD4aFDcga")
29 35
30 hash, err := bcrypt(pass, 10, salt) 36 hash, err := bcrypt(pass, 10, salt)
31 if err != nil { 37 if err != nil {
32 » » t.Fatalf("bcrypt blew up: %s", err) 38 » » t.Fatalf("bcrypt blew up: %v", err)
33 } 39 }
34 if !bytes.HasSuffix(expectedHash, hash) { 40 if !bytes.HasSuffix(expectedHash, hash) {
35 » » t.Errorf("%s should be the suffix of %s", string(hash), string(e xpectedHash)) 41 » » t.Errorf("%v should be the suffix of %v", hash, expectedHash)
36 } 42 }
37 43
38 h, err := newFromHash(expectedHash) 44 h, err := newFromHash(expectedHash)
39 if err != nil { 45 if err != nil {
40 t.Errorf("Unable to parse %s: %v", string(expectedHash), err) 46 t.Errorf("Unable to parse %s: %v", string(expectedHash), err)
41 } 47 }
42 48
43 // This is not the safe way to compare these hashes. We do this only for 49 // This is not the safe way to compare these hashes. We do this only for
44 // testing clarity. Use bcrypt.CompareHashAndPassword() 50 // testing clarity. Use bcrypt.CompareHashAndPassword()
45 if err == nil && !bytes.Equal(expectedHash, h.Hash()) { 51 if err == nil && !bytes.Equal(expectedHash, h.Hash()) {
46 t.Errorf("Parsed hash %v should equal %v", h.Hash(), expectedHas h) 52 t.Errorf("Parsed hash %v should equal %v", h.Hash(), expectedHas h)
47 } 53 }
48 } 54 }
49 55
56 func TestTooLongPasswordsWork(t *testing.T) {
57 salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
58 // One byte over the usual 56 byte limit that blowfish has
59 tooLongPass := []byte("0123456789012345678901234567890123456789012345678 90123456")
60 tooLongExpected := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZt d869sO8zfsHuw7C")
61 hash, err := bcrypt(tooLongPass, 10, salt)
62 if err != nil {
63 t.Fatalf("bcrypt blew up on long password: %v", err)
64 }
65 if !bytes.HasSuffix(tooLongExpected, hash) {
66 t.Errorf("%v should be the suffix of %v", hash, tooLongExpected)
67 }
68 }
69
70 type InvalidHashTest struct {
71 err os.Error
72 hash []byte
73 }
74
75 var invalidTests = []InvalidHashTest{
76 {HashTooShortError, []byte("$2a$10$fooo")},
77 {HashTooShortError, []byte("$2a")},
78 {HashVersionTooNewError('3'), []byte("$3a$10$sssssssssssssssssssssshhhhh hhhhhhhhhhhhhhhhhhhhhhhhhh")},
79 {InvalidHashPrefixError('%'), []byte("%2a$10$sssssssssssssssssssssshhhhh hhhhhhhhhhhhhhhhhhhhhhhhhh")},
80 {InvalidCostError(32), []byte("$2a$32$sssssssssssssssssssssshhhhhhhhhhhh hhhhhhhhhhhhhhhhhhh")},
81 }
82
50 func TestInvalidHashErrors(t *testing.T) { 83 func TestInvalidHashErrors(t *testing.T) {
51 » tooShort := []byte("$2a$10$fooo") 84 » check := func(name string, expected, err os.Error) {
52 » tooShortMsg := "hashedSecret too short to be a bcrypted password" 85 » » if err == nil {
53 » tooNew := []byte("$3a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhh hhhhhh") 86 » » » t.Errorf("%s: Should have returned an error", name)
54 » tooNewMsg := "bcrypt version '3' requested is newer than current version '2': " + string(tooNew) 87 » » }
55 88 » » if err != nil && err != expected {
56 » _, hashErr := newFromHash(tooShort) 89 » » » t.Errorf("%s gave err %v but should have given %v", name , err.String(), expected.String())
57 » hashErrorsCheck(t, "newFromHash", tooShort, tooShortMsg, hashErr) 90 » » }
58 » equalErr := CompareHashAndPassword(tooShort, []byte("anything")) 91 » }
59 » hashErrorsCheck(t, "EqualVerbose", tooShort, tooShortMsg, equalErr) 92 » for _, iht := range invalidTests {
60 93 » » _, err := newFromHash(iht.hash)
61 » _, hashErr = newFromHash(tooNew) 94 » » check("newFromHash", iht.err, err)
62 » hashErrorsCheck(t, "newFromHash", tooNew, tooNewMsg, hashErr) 95 » » err = CompareHashAndPassword(iht.hash, []byte("anything"))
63 » equalErr = CompareHashAndPassword(tooNew, []byte("anything")) 96 » » check("CompareHashAndPassword", iht.err, err)
64 » hashErrorsCheck(t, "EqualVerbose", tooNew, tooNewMsg, equalErr) 97 » }
65 } 98 }
66 99
67 func TestUnpaddedBase64EncodingWorks(t *testing.T) { 100 func TestUnpaddedBase64EncodingWorks(t *testing.T) {
68 original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 3 2, 30, 109, 243, 30} 101 original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 3 2, 30, 109, 243, 30}
69 encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe") 102 encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe")
70 103
71 encoded := base64Encode(original) 104 encoded := base64Encode(original)
72 105
73 if !bytes.Equal(encodedOriginal, encoded) { 106 if !bytes.Equal(encodedOriginal, encoded) {
74 t.Errorf("Encoded %v should have equaled %v", encoded, encodedOr iginal) 107 t.Errorf("Encoded %v should have equaled %v", encoded, encodedOr iginal)
75 } 108 }
76 109
77 decoded, err := base64Decode(encodedOriginal) 110 decoded, err := base64Decode(encodedOriginal)
78 if err != nil { 111 if err != nil {
79 t.Fatalf("base64Decode blew up: %s", err) 112 t.Fatalf("base64Decode blew up: %s", err)
80 } 113 }
81 114
82 if !bytes.Equal(decoded, original) { 115 if !bytes.Equal(decoded, original) {
83 t.Errorf("Decoded %v should have equaled %v", decoded, original) 116 t.Errorf("Decoded %v should have equaled %v", decoded, original)
84 } 117 }
85 } 118 }
86 119
87 func TestCost(t *testing.T) { 120 func TestCost(t *testing.T) {
88 pass := []byte("mypassword") 121 pass := []byte("mypassword")
89 122
90 for c := 0; c < MinCost; c++ { 123 for c := 0; c < MinCost; c++ {
91 p, _ := newFromPassword(pass, c) 124 p, _ := newFromPassword(pass, c)
92 if p.cost != uint32(DefaultCost) { 125 if p.cost != uint32(DefaultCost) {
93 » » » t.Errorf("NewFromPassword should default costs below %d to %d, but was %d", MinCost, DefaultCost, p.cost) 126 » » » t.Errorf("newFromPassword should default costs below %d to %d, but was %d", MinCost, DefaultCost, p.cost)
94 } 127 }
95 } 128 }
96 129
97 p, _ := newFromPassword(pass, 14) 130 p, _ := newFromPassword(pass, 14)
98 if p.cost != 14 { 131 if p.cost != 14 {
99 » » t.Errorf("NewFromPassword should default cost to 14, but was %d" , p.cost) 132 » » t.Errorf("newFromPassword should default cost to 14, but was %d" , p.cost)
100 } 133 }
101 134
102 hp, _ := newFromHash(p.Hash()) 135 hp, _ := newFromHash(p.Hash())
103 if p.cost != hp.cost { 136 if p.cost != hp.cost {
104 t.Errorf("newFromHash should maintain the cost at %d, but was %d ", p.cost, hp.cost) 137 t.Errorf("newFromHash should maintain the cost at %d, but was %d ", p.cost, hp.cost)
105 } 138 }
106 139
107 _, err := newFromPassword(pass, 32) 140 _, err := newFromPassword(pass, 32)
108 if err == nil { 141 if err == nil {
109 » » t.Fatalf("NewFromPassword: should return a cost error") 142 » » t.Fatalf("newFromPassword: should return a cost error")
110 } 143 }
111 » if err.String() != "cost in salt is invalid: 32" { 144 » if err != InvalidCostError(32) {
112 » » t.Fatalf("NewFromPassword: should return cost error, got %s", er r) 145 » » t.Errorf("newFromPassword: should return cost error, got %#v", e rr)
113 } 146 }
114 } 147 }
115 148
116 func TestCostReturnsWithLeadingZeroes(t *testing.T) { 149 func TestCostReturnsWithLeadingZeroes(t *testing.T) {
117 hp, _ := newFromPassword([]byte("abcdefgh"), 7) 150 hp, _ := newFromPassword([]byte("abcdefgh"), 7)
118 cost := hp.Hash()[4:7] 151 cost := hp.Hash()[4:7]
119 expected := []byte("07$") 152 expected := []byte("07$")
120 153
121 if !bytes.Equal(expected, cost) { 154 if !bytes.Equal(expected, cost) {
122 t.Errorf("single digit costs in hash should have leading zeros: was %v instead of %v", cost, expected) 155 t.Errorf("single digit costs in hash should have leading zeros: was %v instead of %v", cost, expected)
123 } 156 }
124 } 157 }
125 158
126 func TestMinorNotRequired(t *testing.T) { 159 func TestMinorNotRequired(t *testing.T) {
127 noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU 1qD4aFDcga") 160 noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU 1qD4aFDcga")
128 h, err := newFromHash(noMinorHash) 161 h, err := newFromHash(noMinorHash)
129 if err != nil { 162 if err != nil {
130 t.Fatalf("No minor hash blew up: %s", err) 163 t.Fatalf("No minor hash blew up: %s", err)
131 } 164 }
132 if h.minor != 0 { 165 if h.minor != 0 {
133 t.Errorf("Should leave minor version at 0, but was %d", h.minor) 166 t.Errorf("Should leave minor version at 0, but was %d", h.minor)
134 } 167 }
135 168
136 if !bytes.Equal(noMinorHash, h.Hash()) { 169 if !bytes.Equal(noMinorHash, h.Hash()) {
137 t.Logf("wut %v\n", noMinorHash)
138 t.Logf("wut %v\n", h.Hash())
139 t.Errorf("Should generate hash %v, but created %v", noMinorHash, h.Hash()) 170 t.Errorf("Should generate hash %v, but created %v", noMinorHash, h.Hash())
140 }
141 }
142
143 func hashErrorsCheck(t *testing.T, name string, hash []byte, expectedStr string, err os.Error) {
144 if err == nil {
145 t.Errorf("%s: Should have returned an error", name)
146 }
147 if err != nil && err.String() != expectedStr {
148 t.Errorf("%s gave err %v but should have given %v", name, err.St ring(), expectedStr)
149 } 171 }
150 } 172 }
151 173
152 func BenchmarkEqual(b *testing.B) { 174 func BenchmarkEqual(b *testing.B) {
153 b.StopTimer() 175 b.StopTimer()
154 passwd := []byte("somepasswordyoulike") 176 passwd := []byte("somepasswordyoulike")
155 hash, _ := GenerateFromPassword(passwd, 10) 177 hash, _ := GenerateFromPassword(passwd, 10)
156 b.StartTimer() 178 b.StartTimer()
157 for i := 0; i < b.N; i++ { 179 for i := 0; i < b.N; i++ {
158 CompareHashAndPassword(hash, passwd) 180 CompareHashAndPassword(hash, passwd)
159 } 181 }
160 } 182 }
161 183
162 func BenchmarkGeneration(b *testing.B) { 184 func BenchmarkGeneration(b *testing.B) {
163 b.StopTimer() 185 b.StopTimer()
164 passwd := []byte("mylongpassword1234") 186 passwd := []byte("mylongpassword1234")
165 b.StartTimer() 187 b.StartTimer()
166 for i := 0; i < b.N; i++ { 188 for i := 0; i < b.N; i++ {
167 GenerateFromPassword(passwd, 10) 189 GenerateFromPassword(passwd, 10)
168 } 190 }
169 } 191 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b