github.com/gramework/gramework@v1.8.1-0.20231027140105-82555c9057f5/test/grypto_test.go (about) 1 // Copyright 2017-present Kirill Danshin and Gramework contributors 2 // Copyright 2019-present Highload LTD (UK CN: 11893420) 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 11 package test 12 13 import ( 14 "testing" 15 16 "github.com/gramework/gramework/grypto/providers/scrypt" 17 18 "github.com/gramework/gramework/grypto" 19 "github.com/gramework/utils/grand" 20 "golang.org/x/crypto/bcrypt" 21 ) 22 23 const ( 24 cost = 10 25 ) 26 27 // TestSalt128 makes sure the result is always 32 hex characters 28 func TestSalt128(t *testing.T) { 29 if testing.Short() { 30 t.Skip("skipping test in short mode.") 31 return 32 } 33 var salt []byte 34 for i := 0; i < 256; i++ { 35 salt = grypto.Salt128() 36 if len(salt) != 16 { 37 t.Errorf("Salt128 fail to generate 128 bit salt: %02x", salt) 38 t.FailNow() 39 } 40 } 41 } 42 43 // TestPasswordSanity makes sure PasswordHash and ComparePassword work well together 44 func TestPasswordSanity(t *testing.T) { 45 if testing.Short() { 46 t.Skip("skipping test in short mode.") 47 return 48 } 49 pw := make([]byte, 12) 50 pw2 := make([]byte, 12) 51 var hash, hash2 []byte 52 53 for i := 0; i < 8; i++ { 54 grand.Read(pw) 55 grand.Read(pw2) 56 hash = grypto.PasswordHash(pw) 57 hash2 = grypto.PasswordHash(pw2) 58 59 if !grypto.PasswordValid(hash, pw) { 60 t.Errorf("PasswordValid should return true for the pair: %s and %s", hash, pw) 61 t.FailNow() 62 } 63 if grypto.PasswordValid(hash2, pw) { 64 t.Error("PasswordValid is giving false positive") 65 t.FailNow() 66 } 67 } 68 } 69 70 // TestPasswordStringSanity makes sure PasswordHashString and ComparePassword work well together 71 func TestPasswordStringSanity(t *testing.T) { 72 if testing.Short() { 73 t.Skip("skipping test in short mode.") 74 return 75 } 76 pw := make([]byte, 12) 77 pw2 := make([]byte, 12) 78 var hash, hash2 []byte 79 80 for i := 0; i < 8; i++ { 81 grand.Read(pw) 82 grand.Read(pw2) 83 hash = grypto.PasswordHashString(string(pw)) 84 hash2 = grypto.PasswordHashString(string(pw2)) 85 86 if !grypto.PasswordValid(hash, pw) { 87 t.Errorf("PasswordValid should return true for the pair: %s and %s", hash, pw) 88 t.FailNow() 89 } 90 if grypto.PasswordValid(hash2, pw) { 91 t.Error("PasswordValid is giving false positive") 92 t.FailNow() 93 } 94 } 95 } 96 97 // TestPasswordNeedsRehash makes sure TestPasswordNeedsRehash works well 98 func TestPasswordNeedsRehash(t *testing.T) { 99 if testing.Short() { 100 t.Skip("skipping test in short mode.") 101 return 102 } 103 pw := make([]byte, 12) 104 for i := 0; i < 4; i++ { 105 grand.Read(pw) 106 hash, _ := bcrypt.GenerateFromPassword(pw, cost-1) 107 if !grypto.PasswordNeedsRehash(hash) { 108 t.Errorf("PasswordNeedsRehash returned false, expected true") 109 t.FailNow() 110 } 111 } 112 for i := 0; i < 4; i++ { 113 grand.Read(pw) 114 hash, _ := bcrypt.GenerateFromPassword(pw, cost) 115 if !grypto.PasswordNeedsRehash(hash) { 116 t.Errorf("PasswordNeedsRehash returned false, expected true as of bcrypt -> scrypt migration") 117 } 118 } 119 for i := 0; i < 4; i++ { 120 grand.Read(pw) 121 hash := scrypt.New().Hash(pw) 122 if grypto.PasswordNeedsRehash(hash) { 123 t.Errorf("PasswordNeedsRehash returned true, expected false for scrypt hash") 124 } 125 } 126 } 127 128 func BenchmarkPassHashAndValidation(b *testing.B) { 129 if testing.Short() { 130 b.Skip("skipping test in short mode.") 131 return 132 } 133 pws := make([][]byte, b.N) 134 for i := 0; i < b.N; i++ { 135 pws[i] = make([]byte, 12) 136 grand.Read(pws[i]) 137 } 138 139 b.ResetTimer() 140 141 for i := 0; i < b.N; i += 2 { 142 hash := grypto.PasswordHash(pws[i]) 143 if !grypto.PasswordValid(hash, pws[i]) { 144 b.Errorf("PasswordValid should return true for the pair: %s and %s", hash, pws[i]) 145 b.FailNow() 146 } 147 } 148 } 149 150 func BenchmarkPassHash(b *testing.B) { 151 if testing.Short() { 152 b.Skip("skipping test in short mode.") 153 return 154 } 155 pws := make([][]byte, b.N) 156 for i := 0; i < b.N; i++ { 157 pws[i] = make([]byte, 12) 158 grand.Read(pws[i]) 159 } 160 161 b.ResetTimer() 162 163 for i := 0; i < b.N; i++ { 164 hash := grypto.PasswordHash(pws[i]) 165 _ = hash 166 } 167 }