github.com/condensat/bank-core@v0.1.0/database/query/credential.go (about) 1 // Copyright 2020 Condensat Tech. All rights reserved. 2 // Use of this source code is governed by a MIT 3 // license that can be found in the LICENSE file. 4 5 package query 6 7 import ( 8 "context" 9 "encoding/hex" 10 "errors" 11 12 "github.com/condensat/bank-core/database" 13 "github.com/condensat/bank-core/database/model" 14 15 "github.com/condensat/bank-core/security" 16 "github.com/condensat/bank-core/security/utils" 17 18 "github.com/jinzhu/gorm" 19 "github.com/shengdoushi/base58" 20 ) 21 22 var ( 23 ErrUserNotFound = errors.New("User not found") 24 ErrInvalidPasswordHash = errors.New("Invalid PasswordHash") 25 ErrDatabaseError = errors.New("Database Operation failed") 26 ) 27 28 func HashEntry(entry model.Base58) model.Base58 { 29 hash := utils.HashBytes([]byte(entry)) 30 return model.Base58(hex.EncodeToString(hash[:])) 31 } 32 33 func CreateOrUpdatedCredential(ctx context.Context, db database.Context, credential model.Credential) (model.Credential, error) { 34 switch gdb := db.DB().(type) { 35 case *gorm.DB: 36 37 // perform a sha512 hex digest of login and password 38 login := HashEntry(credential.LoginHash) 39 password := HashEntry(credential.PasswordHash) 40 password = login + password // password prefixed with login for uniqueness 41 loginHash := security.SaltedHash(ctx, []byte(login)) 42 passwordHash := security.SaltedHash(ctx, []byte(password)) 43 defer utils.Memzero(loginHash) 44 defer utils.Memzero(passwordHash) 45 46 var result model.Credential 47 err := gdb. 48 Where(&model.Credential{UserID: credential.UserID}). 49 Assign(&model.Credential{ 50 LoginHash: model.Base58(base58.Encode(loginHash, base58.BitcoinAlphabet)), 51 PasswordHash: model.Base58(base58.Encode(passwordHash, base58.BitcoinAlphabet)), 52 TOTPSecret: credential.TOTPSecret, 53 }). 54 FirstOrCreate(&result).Error 55 56 return result, err 57 58 default: 59 return model.Credential{}, database.ErrInvalidDatabase 60 } 61 } 62 63 func CheckCredential(ctx context.Context, db database.Context, login, password model.Base58) (model.UserID, bool, error) { 64 switch gdb := db.DB().(type) { 65 case *gorm.DB: 66 67 // client should send a sha512 hex digest of the password 68 // login = hashEntry(login) 69 // password = hashEntry(password) 70 71 password = login + password // password prefixed with login for uniqueness 72 loginHash := security.SaltedHash(ctx, []byte(login)) 73 defer utils.Memzero(loginHash) 74 75 var cred model.Credential 76 err := gdb. 77 Where(&model.Credential{LoginHash: model.Base58(base58.Encode(loginHash, base58.BitcoinAlphabet))}). 78 First(&cred).Error 79 if err != nil { 80 return 0, false, ErrDatabaseError 81 } 82 if cred.UserID == 0 { 83 return 0, false, ErrUserNotFound 84 } 85 86 passwordHash, err := base58.Decode(string(cred.PasswordHash), base58.BitcoinAlphabet) 87 defer utils.Memzero(passwordHash) 88 if err != nil { 89 return 0, false, ErrInvalidPasswordHash 90 } 91 92 return cred.UserID, security.SaltedHashVerify(ctx, []byte(password), passwordHash), nil 93 94 default: 95 return 0, false, database.ErrInvalidDatabase 96 } 97 }