github.com/google/osv-scalibr@v0.4.1/detector/weakcredentials/winlocal/samreg/crypto_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 samreg 16 17 import ( 18 "slices" 19 "strings" 20 "testing" 21 ) 22 23 func TestDecryptRC4Hash(t *testing.T) { 24 tests := []struct { 25 name string 26 rid []byte 27 syskey []byte 28 hash []byte 29 hashConstant []byte 30 want []byte 31 wantErr bool 32 wantErrText string 33 }{ 34 { 35 name: "valid_input_decrypts", 36 rid: []byte("\xf4\x01\x00\x00"), 37 syskey: []byte("\x3d\x21\x2c\xe8\xa2\xda\x83\x43\xbd\xad\x1e\xf2\xcf\xb6\xb3\x1c"), 38 hash: []byte("\xed\x92\x87\x92\x78\x3b\x69\x2c\x21\x37\x49\xbc\xdb\xe3\x1a\xf5"), 39 hashConstant: []byte("\x4e\x54\x50\x41\x53\x53\x57\x4f\x52\x44\x00"), 40 want: []byte("\x58\xa4\x78\x13\x5a\x93\xac\x3b\xf0\x58\xa5\xea\x0e\x8f\xdb\x71"), 41 }, 42 { 43 name: "RID_too_short_returns_error", 44 rid: []byte(""), 45 syskey: []byte("\x3d\x21\x2c\xe8\xa2\xda\x83\x43\xbd\xad\x1e\xf2\xcf\xb6\xb3\x1c"), 46 hash: []byte("\xed\x92\x87\x92\x78\x3b\x69\x2c\x21\x37\x49\xbc\xdb\xe3\x1a\xf5"), 47 hashConstant: []byte("\x4e\x54\x50\x41\x53\x53\x57\x4f\x52\x44\x00"), 48 wantErr: true, 49 wantErrText: errInvalidRIDSize.Error(), 50 }, 51 } 52 53 for _, tc := range tests { 54 t.Run(tc.name, func(t *testing.T) { 55 hash, err := decryptRC4Hash(tc.rid, tc.syskey, tc.hash, tc.hashConstant) 56 if (err != nil) != tc.wantErr { 57 t.Errorf("decryptRC4Hash(...): unexpected error: %v", err) 58 } 59 60 if tc.wantErr { 61 if !strings.Contains(err.Error(), tc.wantErrText) { 62 t.Errorf("decryptRC4Hash(...): unexpected error, got: %v, want: %v", err, tc.wantErrText) 63 } 64 65 return 66 } 67 68 if !slices.Equal(hash, tc.want) { 69 t.Errorf("decryptRC4Hash(...): unexpected result, got: %v, want: %v", hash, tc.want) 70 } 71 }) 72 } 73 } 74 75 func TestDecryptAESHash(t *testing.T) { 76 tests := []struct { 77 name string 78 rid []byte 79 syskey []byte 80 hash []byte 81 salt []byte 82 want []byte 83 wantErr bool 84 wantErrText string 85 }{ 86 { 87 name: "valid_input_decrypts", 88 rid: []byte("\xf4\x01\x00\x00"), 89 syskey: []byte("\xfc\xde\xe8\x3a\xc6\xc1\x4b\x28\xf5\x26\x50\x1f\xc6\xe8\xbb\xc3"), 90 hash: []byte("\x48\xf2\xb6\x8b\xd9\x06\xa2\xbd\xb2\xaf\x39\x1c\xe2\x60\x44\x56\x6b\x80\x62\xb6\x55\xf4\x2b\x05\x9d\xfb\x5c\x68\x55\x4a\x5b\xc3"), 91 salt: []byte("\xa3\x28\x48\xec\x7d\x73\x12\xec\x81\xeb\x50\xd0\x65\x09\x55\xd4"), 92 want: []byte("\x58\xa4\x78\x13\x5a\x93\xac\x3b\xf0\x58\xa5\xea\x0e\x8f\xdb\x71"), 93 }, 94 { 95 name: "empty_hash_returns_empty", 96 rid: []byte("\xf4\x01\x00\x00"), 97 syskey: []byte("\xfc\xde\xe8\x3a\xc6\xc1\x4b\x28\xf5\x26\x50\x1f\xc6\xe8\xbb\xc3"), 98 hash: []byte(""), 99 salt: []byte("\xa3\x28\x48\xec\x7d\x73\x12\xec\x81\xeb\x50\xd0\x65\x09\x55\xd4"), 100 want: []byte(""), 101 }, 102 { 103 name: "empty_syskey_returns_error", 104 rid: []byte(""), 105 syskey: []byte(""), 106 hash: []byte("\x00"), 107 wantErr: true, 108 wantErrText: "hash length not aligned with AES block size", 109 }, 110 { 111 name: "RID_too_short_returns_error", 112 rid: []byte(""), 113 syskey: []byte("\xfc\xde\xe8\x3a\xc6\xc1\x4b\x28\xf5\x26\x50\x1f\xc6\xe8\xbb\xc3"), 114 hash: []byte("\x48\xf2\xb6\x8b\xd9\x06\xa2\xbd\xb2\xaf\x39\x1c\xe2\x60\x44\x56\x6b\x80\x62\xb6\x55\xf4\x2b\x05\x9d\xfb\x5c\x68\x55\x4a\x5b\xc3"), 115 salt: []byte("\xa3\x28\x48\xec\x7d\x73\x12\xec\x81\xeb\x50\xd0\x65\x09\x55\xd4"), 116 wantErr: true, 117 wantErrText: errInvalidRIDSize.Error(), 118 }, 119 } 120 121 for _, tc := range tests { 122 t.Run(tc.name, func(t *testing.T) { 123 hash, err := decryptAESHash(tc.rid, tc.syskey, tc.hash, tc.salt) 124 if (err != nil) != tc.wantErr { 125 t.Errorf("decryptAESHash(...): unexpected error: %v", err) 126 } 127 128 if tc.wantErr { 129 if !strings.Contains(err.Error(), tc.wantErrText) { 130 t.Errorf("decryptAESHash(...): unexpected error, got: %v, want: %v", err, tc.wantErrText) 131 } 132 133 return 134 } 135 136 if !slices.Equal(hash, tc.want) { 137 t.Errorf("decryptAESHash(...): unexpected result, got: %v, want: %v", hash, tc.want) 138 } 139 }) 140 } 141 }