github.com/google/osv-scalibr@v0.4.1/detector/weakcredentials/etcshadow/cracker_test.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_test 16 17 import ( 18 "context" 19 "errors" 20 "testing" 21 22 "github.com/google/osv-scalibr/detector/weakcredentials/etcshadow" 23 ) 24 25 // All the hashes below are for the string "Password123" and where obtained 26 // running: 'mkpasswd -m METHOD PASSWORD'. 27 // 28 // Note the obsolete descrypt will limit password to 8 characters and 29 // there will be cracked as the value 'Password'. 30 var testHashes = map[string]string{ 31 "yescrypt": "$y$j9T$huXYrFRxr5.EtlA/GqJQg1$R36Nu5MbY5YM0SzRaWbBPyGpM7KMcWtbUmBq5gDZA9B", 32 "gost-yescrypt": "$gy$j9T$i.krMgTvuXE2doi6Hguka/$qwn482j7gJbWZNQ3cF0YdKAud.C3vUIorQGsF0ryox3", 33 "scrypt": "$7$CU..../....oupVTCfqrgm0HQkQR3JaB1$2m9CeDTqL8i5pMsc8E73A2bCIsvQPhntxBmSVlbrql2", 34 "bcrypt": "$2b$05$IYDlXvHmeORyyiUwu8KKuek2LE8VrxIYZ2skPvRDDNngpXJHRq7sG", 35 "bcrypt-a": "$2a$05$pRmHHyGfKl9/9AZLORG/neKW39VHGF4ptLT2MLq1BqQOnbwL6DQM6", 36 "sha512crypt": "$6$5dZ5RtTlA.rNzi8o$sE23IbqB0Q57/7nI2.AqazHUnWGP06HmkadfBJ90mHgAHkWVZteoaUWV25jITMIUXC/buIgZ9hU2JYQM5qGZn1", 37 "sha256crypt": "$5$bMDt75aAcRJMgynJ$7dvcQe0UPWAlpr4VFNQI2iDDUQLgwcaTOV5oQVSIR56", 38 "sunmd5": "$md5,rounds=46947$ieGPlcPv$$sJ4xQqZ5DHZu0Bma2EW/..", 39 "md5crypt": "$1$emQTNiRX$kZ2UzRTLgfsTBGS0M1OOb1", 40 "NT-Hash": "$3$$58a478135a93ac3bf058a5ea0e8fdb71", 41 // Quite old and insecure password hash algorithms. Do not use the $ format. 42 "bsdicrypt": "_J9..Sc51o5Op8yDIuHc", 43 "descrypt": "chERDiI95PGCQ", 44 } 45 46 func TestPasswordHashCracker(t *testing.T) { 47 cracker := etcshadow.NewPasswordCracker() 48 crackableHash := map[string]bool{ 49 "bcrypt": true, 50 "bcrypt-a": true, 51 "sha512crypt": true, 52 } 53 for k, v := range testHashes { 54 password, err := cracker.Crack(t.Context(), v) 55 _, isCrackable := crackableHash[k] 56 if isCrackable && err != nil { 57 t.Errorf("not cracked supported hash: [%v] [%v]", k, v) 58 } else if !isCrackable && err == nil { 59 t.Errorf("cracked unsupported hash: [%v] [%v] [%v]", k, password, v) 60 } else if password != "Password123" && err == nil { 61 t.Errorf("cracked password is not 'Password123': [%v] [%v] [%v]", k, password, v) 62 } 63 } 64 } 65 66 func TestPasswordHashCrackerBadHashes(t *testing.T) { 67 cracker := etcshadow.NewPasswordCracker() 68 badValues := []string{ 69 "$2$", 70 "$2$123", 71 "$2$123$", 72 "$6$", 73 "$6$123", 74 "$6$123$", 75 "*", 76 "!!", 77 "!", 78 "$2$*", 79 "$2$!", 80 "$6$*", 81 "$6$!", 82 } 83 84 for _, v := range badValues { 85 if _, err := cracker.Crack(t.Context(), v); !errors.Is(err, etcshadow.ErrNotCracked) { 86 t.Errorf("expected ErrNotCracked on hash [%s] received [%v]", v, err) 87 } 88 } 89 } 90 91 func TestPasswordHashCrackerCancelled(t *testing.T) { 92 cracker := etcshadow.NewPasswordCracker() 93 ctx, cancelFunc := context.WithCancel(t.Context()) 94 cancelFunc() 95 _, err := cracker.Crack(ctx, testHashes["bcrypt"]) 96 if !errors.Is(err, ctx.Err()) { 97 t.Errorf("expected error %v on cancelled context, received error %v", ctx.Err(), err) 98 } 99 }