github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/crypto/bcrypt/bcrypt_test.go (about) 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 }