github.com/google/osv-scalibr@v0.4.1/detector/weakcredentials/etcshadow/cracker.go (about) 1 // Copyright 2025 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package etcshadow 16 17 import ( 18 "context" 19 "errors" 20 "strings" 21 22 "github.com/GehirnInc/crypt/sha512_crypt" 23 "golang.org/x/crypto/bcrypt" 24 ) 25 26 // ErrNotCracked returned when a cracker did not find a matching password. 27 var ErrNotCracked = errors.New("not cracked") 28 29 // Cracker interface is implemented by types which know how to crack hashes. 30 type Cracker interface { 31 // Crack returns (password,nil) on success and ("", ErrNotCracked) on failure. 32 Crack(ctx context.Context, hash string) (string, error) 33 } 34 35 type passwordCracker struct { 36 bcryptCracker Cracker 37 sha512cryptCracker Cracker 38 } 39 40 // NewPasswordCracker returns a cracker that can attempt to find the password for a given hash. 41 func NewPasswordCracker() Cracker { 42 return passwordCracker{ 43 bcryptCracker: bcryptCracker{}, 44 sha512cryptCracker: sha512CryptCracker{}, 45 } 46 } 47 48 func (c passwordCracker) Crack(ctx context.Context, hash string) (string, error) { 49 // TODO(b/383302694): Add more hash algos. 50 switch { 51 case strings.HasPrefix(hash, "$2"): 52 return c.bcryptCracker.Crack(ctx, hash) 53 case strings.HasPrefix(hash, sha512_crypt.MagicPrefix): 54 return c.sha512cryptCracker.Crack(ctx, hash) 55 } 56 return "", ErrNotCracked 57 } 58 59 // Cracker for bcrypt password hashes. 60 type bcryptCracker struct { 61 } 62 63 func (c bcryptCracker) Crack(ctx context.Context, hash string) (string, error) { 64 for _, v := range topPasswords { 65 if ctx.Err() != nil { 66 return "", ctx.Err() 67 } 68 err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(v)) 69 if err == nil { 70 return v, nil 71 } 72 } 73 return "", ErrNotCracked 74 } 75 76 // Cracker for sha512crypt password hashes. 77 type sha512CryptCracker struct { 78 } 79 80 func (c sha512CryptCracker) Crack(ctx context.Context, hash string) (string, error) { 81 crypter := sha512_crypt.New() 82 for _, v := range topPasswords { 83 if ctx.Err() != nil { 84 return "", ctx.Err() 85 } 86 err := crypter.Verify(hash, []byte(v)) 87 if err == nil { 88 return v, nil 89 } 90 } 91 return "", ErrNotCracked 92 }