github.com/olivere/camlistore@v0.0.0-20140121221811-1b7ac2da0199/third_party/code.google.com/p/go.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 "testing" 10 ) 11 12 func TestBcryptingIsEasy(t *testing.T) { 13 pass := []byte("mypassword") 14 hp, err := GenerateFromPassword(pass, 0) 15 if err != nil { 16 t.Fatalf("GenerateFromPassword error: %s", err) 17 } 18 19 if CompareHashAndPassword(hp, pass) != nil { 20 t.Errorf("%v should hash %s correctly", hp, pass) 21 } 22 23 notPass := "notthepass" 24 err = CompareHashAndPassword(hp, []byte(notPass)) 25 if err != ErrMismatchedHashAndPassword { 26 t.Errorf("%v and %s should be mismatched", hp, notPass) 27 } 28 } 29 30 func TestBcryptingIsCorrect(t *testing.T) { 31 pass := []byte("allmine") 32 salt := []byte("XajjQvNhvvRt5GSeFk1xFe") 33 expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga") 34 35 hash, err := bcrypt(pass, 10, salt) 36 if err != nil { 37 t.Fatalf("bcrypt blew up: %v", err) 38 } 39 if !bytes.HasSuffix(expectedHash, hash) { 40 t.Errorf("%v should be the suffix of %v", hash, expectedHash) 41 } 42 43 h, err := newFromHash(expectedHash) 44 if err != nil { 45 t.Errorf("Unable to parse %s: %v", string(expectedHash), err) 46 } 47 48 // This is not the safe way to compare these hashes. We do this only for 49 // testing clarity. Use bcrypt.CompareHashAndPassword() 50 if err == nil && !bytes.Equal(expectedHash, h.Hash()) { 51 t.Errorf("Parsed hash %v should equal %v", h.Hash(), expectedHash) 52 } 53 } 54 55 func TestTooLongPasswordsWork(t *testing.T) { 56 salt := []byte("XajjQvNhvvRt5GSeFk1xFe") 57 // One byte over the usual 56 byte limit that blowfish has 58 tooLongPass := []byte("012345678901234567890123456789012345678901234567890123456") 59 tooLongExpected := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C") 60 hash, err := bcrypt(tooLongPass, 10, salt) 61 if err != nil { 62 t.Fatalf("bcrypt blew up on long password: %v", err) 63 } 64 if !bytes.HasSuffix(tooLongExpected, hash) { 65 t.Errorf("%v should be the suffix of %v", hash, tooLongExpected) 66 } 67 } 68 69 type InvalidHashTest struct { 70 err error 71 hash []byte 72 } 73 74 var invalidTests = []InvalidHashTest{ 75 {ErrHashTooShort, []byte("$2a$10$fooo")}, 76 {ErrHashTooShort, []byte("$2a")}, 77 {HashVersionTooNewError('3'), []byte("$3a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")}, 78 {InvalidHashPrefixError('%'), []byte("%2a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")}, 79 {InvalidCostError(32), []byte("$2a$32$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")}, 80 } 81 82 func TestInvalidHashErrors(t *testing.T) { 83 check := func(name string, expected, err error) { 84 if err == nil { 85 t.Errorf("%s: Should have returned an error", name) 86 } 87 if err != nil && err != expected { 88 t.Errorf("%s gave err %v but should have given %v", name, err, expected) 89 } 90 } 91 for _, iht := range invalidTests { 92 _, err := newFromHash(iht.hash) 93 check("newFromHash", iht.err, err) 94 err = CompareHashAndPassword(iht.hash, []byte("anything")) 95 check("CompareHashAndPassword", iht.err, err) 96 } 97 } 98 99 func TestUnpaddedBase64Encoding(t *testing.T) { 100 original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 32, 30, 109, 243, 30} 101 encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe") 102 103 encoded := base64Encode(original) 104 105 if !bytes.Equal(encodedOriginal, encoded) { 106 t.Errorf("Encoded %v should have equaled %v", encoded, encodedOriginal) 107 } 108 109 decoded, err := base64Decode(encodedOriginal) 110 if err != nil { 111 t.Fatalf("base64Decode blew up: %s", err) 112 } 113 114 if !bytes.Equal(decoded, original) { 115 t.Errorf("Decoded %v should have equaled %v", decoded, original) 116 } 117 } 118 119 func TestCost(t *testing.T) { 120 if testing.Short() { 121 return 122 } 123 124 pass := []byte("mypassword") 125 126 for c := 0; c < MinCost; c++ { 127 p, _ := newFromPassword(pass, c) 128 if p.cost != uint32(DefaultCost) { 129 t.Errorf("newFromPassword should default costs below %d to %d, but was %d", MinCost, DefaultCost, p.cost) 130 } 131 } 132 133 p, _ := newFromPassword(pass, 14) 134 if p.cost != 14 { 135 t.Errorf("newFromPassword should default cost to 14, but was %d", p.cost) 136 } 137 138 hp, _ := newFromHash(p.Hash()) 139 if p.cost != hp.cost { 140 t.Errorf("newFromHash should maintain the cost at %d, but was %d", p.cost, hp.cost) 141 } 142 143 _, err := newFromPassword(pass, 32) 144 if err == nil { 145 t.Fatalf("newFromPassword: should return a cost error") 146 } 147 if err != InvalidCostError(32) { 148 t.Errorf("newFromPassword: should return cost error, got %#v", err) 149 } 150 } 151 152 func TestCostReturnsWithLeadingZeroes(t *testing.T) { 153 hp, _ := newFromPassword([]byte("abcdefgh"), 7) 154 cost := hp.Hash()[4:7] 155 expected := []byte("07$") 156 157 if !bytes.Equal(expected, cost) { 158 t.Errorf("single digit costs in hash should have leading zeros: was %v instead of %v", cost, expected) 159 } 160 } 161 162 func TestMinorNotRequired(t *testing.T) { 163 noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga") 164 h, err := newFromHash(noMinorHash) 165 if err != nil { 166 t.Fatalf("No minor hash blew up: %s", err) 167 } 168 if h.minor != 0 { 169 t.Errorf("Should leave minor version at 0, but was %d", h.minor) 170 } 171 172 if !bytes.Equal(noMinorHash, h.Hash()) { 173 t.Errorf("Should generate hash %v, but created %v", noMinorHash, h.Hash()) 174 } 175 } 176 177 func BenchmarkEqual(b *testing.B) { 178 b.StopTimer() 179 passwd := []byte("somepasswordyoulike") 180 hash, _ := GenerateFromPassword(passwd, 10) 181 b.StartTimer() 182 for i := 0; i < b.N; i++ { 183 CompareHashAndPassword(hash, passwd) 184 } 185 } 186 187 func BenchmarkGeneration(b *testing.B) { 188 b.StopTimer() 189 passwd := []byte("mylongpassword1234") 190 b.StartTimer() 191 for i := 0; i < b.N; i++ { 192 GenerateFromPassword(passwd, 10) 193 } 194 }