1
1
package yoauth
2
2
3
3
import (
4
+ "crypto/sha512"
4
5
"time"
5
6
6
7
. "yo/cfg"
@@ -84,18 +85,10 @@ func UserRegister(ctx *Ctx, emailAddr string, passwordPlain string) (ret yodb.I6
84
85
panic (Err___yo_authRegister_EmailAddrAlreadyExists )
85
86
}
86
87
87
- pwd_hashed , err := bcrypt .GenerateFromPassword ([]byte (passwordPlain ), bcrypt .DefaultCost )
88
- if (err != nil ) || (len (pwd_hashed ) == 0 ) {
89
- if err == bcrypt .ErrPasswordTooLong {
90
- panic (Err___yo_authRegister_PasswordTooLong )
91
- } else {
92
- panic (Err___yo_authRegister_PasswordInvalid )
93
- }
94
- }
95
88
Try (func () {
96
89
ret = yodb .I64 (yodb .CreateOne [UserAccount ](ctx , & UserAccount {
97
90
EmailAddr : yodb .Text (emailAddr ),
98
- pwdHashed : pwd_hashed ,
91
+ pwdHashed : pwdHashStorable ( passwordPlain ) ,
99
92
}))
100
93
}, func (err any ) {
101
94
panic (If [any ](EnforceGenericizedErrors , err , errGeneric ))
@@ -117,8 +110,7 @@ func UserLogin(ctx *Ctx, emailAddr string, passwordPlain string) (*UserAccount,
117
110
user_email_addr , account_id , user_pwd_hashed = account .EmailAddr .String (), account .Id , account .pwdHashed
118
111
}
119
112
120
- err := bcrypt .CompareHashAndPassword (user_pwd_hashed , []byte (passwordPlain ))
121
- if err != nil {
113
+ if ! pwdHashVerify (user_pwd_hashed , passwordPlain ) {
122
114
if (account != nil ) && (! account .Lockout ) && (LoginThrottling .NumFailedAttemptsBeforeLockout > 0 ) && (LoginThrottling .WithinTimePeriod > 0 ) {
123
115
account .FailedLoginAttempts = append (account .FailedLoginAttempts , yodb .I64 (time .Now ().UnixNano ()))
124
116
if idx_start := account .FailedLoginAttempts .Len () - LoginThrottling .NumFailedAttemptsBeforeLockout ; idx_start >= 0 {
@@ -156,18 +148,10 @@ func UserLoginOrFinalizeRegisterOrPwdReset(ctx *Ctx, emailAddr string, passwordP
156
148
panic (Err___yo_authLoginOrFinalizePwdReset_PwdReqExpired )
157
149
}
158
150
// check temp one-time pwd
159
- err := bcrypt .CompareHashAndPassword (pwd_reset_req .tmpPwdHashed , []byte (passwordPlain ))
160
- if err != nil {
151
+ if ! pwdHashVerify (pwd_reset_req .tmpPwdHashed , passwordPlain ) {
161
152
panic (Err___yo_authLoginOrFinalizePwdReset_WrongPassword )
162
153
}
163
- pwd_hash , err := bcrypt .GenerateFromPassword ([]byte (password2Plain ), bcrypt .DefaultCost )
164
- if (err != nil ) || (len (pwd_hash ) == 0 ) {
165
- if err == bcrypt .ErrPasswordTooLong {
166
- panic (Err___yo_authLoginOrFinalizePwdReset_NewPasswordTooLong )
167
- } else {
168
- panic (Err___yo_authLoginOrFinalizePwdReset_NewPasswordInvalid )
169
- }
170
- }
154
+ pwd_hash := pwdHashStorable (password2Plain )
171
155
ctx .DbTx (true )
172
156
account := yodb .FindOne [UserAccount ](ctx , UserAccountEmailAddr .Equal (emailAddr ))
173
157
if account != nil { // existing user: pwd-reset
@@ -203,14 +187,7 @@ func UserVerify(jwtRaw string) *JwtPayload {
203
187
func UserChangePassword (ctx * Ctx , emailAddr string , passwordOldPlain string , passwordNewPlain string ) {
204
188
ctx .DbTx (true )
205
189
user_account , _ := UserLogin (ctx , emailAddr , passwordOldPlain )
206
- hash , err := bcrypt .GenerateFromPassword ([]byte (passwordNewPlain ), bcrypt .DefaultCost )
207
- if (err != nil ) || (len (hash ) == 0 ) {
208
- if err == bcrypt .ErrPasswordTooLong {
209
- panic (Err___yo_authLoginOrFinalizePwdReset_NewPasswordTooLong )
210
- } else {
211
- panic (Err___yo_authLoginOrFinalizePwdReset_NewPasswordInvalid )
212
- }
213
- }
190
+ hash := pwdHashStorable (passwordNewPlain )
214
191
user_account .pwdHashed , user_account .FailedLoginAttempts , user_account .Lockout = hash , nil , false
215
192
_ = yodb .Update [UserAccount ](ctx , user_account , nil , true , UserAccountFields (userAccountPwdHashed , UserAccountFailedLoginAttempts , UserAccountLockout )... )
216
193
}
@@ -222,3 +199,40 @@ func ById(ctx *Ctx, id yodb.I64) *UserAccount {
222
199
func ByEmailAddr (ctx * Ctx , emailAddr string ) * UserAccount {
223
200
return yodb .FindOne [UserAccount ](ctx , UserAccountEmailAddr .Equal (emailAddr ))
224
201
}
202
+
203
+ func pwdHashVerify (pwdHashStored []byte , passwordToCheckPlain string ) bool {
204
+ sha512 := sha512 .New ()
205
+ _ , err := sha512 .Write ([]byte (passwordToCheckPlain ))
206
+ if err != nil {
207
+ panic (err )
208
+ }
209
+ return (err == bcrypt .CompareHashAndPassword (pwdHashStored , sha512 .Sum (nil )))
210
+ }
211
+
212
+ func pwdHashStorable (passwordPlain string , salt string ) []byte {
213
+ sha512 := sha512 .New ()
214
+ _ , err := sha512 .Write ([]byte (passwordPlain ))
215
+ if err != nil {
216
+ panic (err )
217
+ }
218
+ sha512hash := sha512 .Sum (nil )
219
+ Assert (len (sha512hash ) == 64 , len (sha512hash ))
220
+ Assert (len (salt ) > 0 )
221
+
222
+ if (len (salt ) % 2 ) == 0 {
223
+
224
+ }
225
+ for len (salt ) < 8 {
226
+ salt += salt
227
+ }
228
+ bytes8 := []byte (salt [:8 ])
229
+ if (len (salt ) % 2 ) == 1 {
230
+ bytes8 = []byte (salt [len (salt )- 8 :])
231
+ }
232
+
233
+ ret , err := bcrypt .GenerateFromPassword (append (sha512hash , bytes8 [:]... ), bcrypt .DefaultCost )
234
+ if err != nil {
235
+ panic (err )
236
+ }
237
+ return ret
238
+ }
0 commit comments