1// Copyright 2020 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//////////////////////////////////////////////////////////////////////////////// 16 17package subtle_test 18 19import ( 20 "encoding/hex" 21 "strings" 22 "testing" 23 24 "github.com/google/tink/go/mac/subtle" 25 "github.com/google/tink/go/subtle/random" 26) 27 28var key, _ = hex.DecodeString("000102030405060708090a0b0c0d0e0f") 29var data = []byte("Hello") 30var hmacTests = []struct { 31 hashAlg string 32 tagSize uint32 33 key []byte 34 data []byte 35 expectedMac string 36}{ 37 { 38 hashAlg: "SHA256", 39 tagSize: 32, 40 data: data, 41 key: key, 42 expectedMac: "e0ff02553d9a619661026c7aa1ddf59b7b44eac06a9908ff9e19961d481935d4", 43 }, 44 { 45 hashAlg: "SHA512", 46 tagSize: 64, 47 data: data, 48 key: key, 49 expectedMac: "481e10d823ba64c15b94537a3de3f253c16642451ac45124dd4dde120bf1e5c15" + 50 "e55487d55ba72b43039f235226e7954cd5854b30abc4b5b53171a4177047c9b", 51 }, 52 // empty data 53 { 54 hashAlg: "SHA256", 55 tagSize: 32, 56 data: []byte{}, 57 key: key, 58 expectedMac: "07eff8b326b7798c9ccfcbdbe579489ac785a7995a04618b1a2813c26744777d", 59 }, 60} 61 62func TestHMACBasic(t *testing.T) { 63 for i, test := range hmacTests { 64 cipher, err := subtle.NewHMAC(test.hashAlg, test.key, test.tagSize) 65 if err != nil { 66 t.Errorf("cannot create new mac in test case %d: %s", i, err) 67 } 68 mac, err := cipher.ComputeMAC(test.data) 69 if err != nil { 70 t.Errorf("mac computation failed in test case %d: %s", i, err) 71 } 72 if hex.EncodeToString(mac) != test.expectedMac[:(test.tagSize*2)] { 73 t.Errorf("incorrect mac in test case %d: expect %s, got %s", 74 i, test.expectedMac[:(test.tagSize*2)], hex.EncodeToString(mac)) 75 } 76 if err := cipher.VerifyMAC(mac, test.data); err != nil { 77 t.Errorf("mac verification failed in test case %d: %s", i, err) 78 } 79 } 80} 81 82func TestNewHMACWithInvalidInput(t *testing.T) { 83 // invalid hash algorithm 84 _, err := subtle.NewHMAC("MD5", random.GetRandomBytes(16), 32) 85 if err == nil || !strings.Contains(err.Error(), "invalid hash algorithm") { 86 t.Errorf("expect an error when hash algorithm is invalid") 87 } 88 // key too short 89 _, err = subtle.NewHMAC("SHA256", random.GetRandomBytes(1), 32) 90 if err == nil || !strings.Contains(err.Error(), "key too short") { 91 t.Errorf("expect an error when key is too short") 92 } 93 // tag too short 94 _, err = subtle.NewHMAC("SHA256", random.GetRandomBytes(16), 9) 95 if err == nil || !strings.Contains(err.Error(), "tag size too small") { 96 t.Errorf("expect an error when tag size is too small") 97 } 98 // tag too big 99 _, err = subtle.NewHMAC("SHA1", random.GetRandomBytes(16), 21) 100 if err == nil || !strings.Contains(err.Error(), "tag size too big") { 101 t.Errorf("expect an error when tag size is too big") 102 } 103 _, err = subtle.NewHMAC("SHA256", random.GetRandomBytes(16), 33) 104 if err == nil || !strings.Contains(err.Error(), "tag size too big") { 105 t.Errorf("expect an error when tag size is too big") 106 } 107 _, err = subtle.NewHMAC("SHA512", random.GetRandomBytes(16), 65) 108 if err == nil || !strings.Contains(err.Error(), "tag size too big") { 109 t.Errorf("expect an error when tag size is too big") 110 } 111} 112 113func TestHMAComputeVerifyWithNilInput(t *testing.T) { 114 cipher, err := subtle.NewHMAC("SHA256", random.GetRandomBytes(16), 32) 115 if err != nil { 116 t.Errorf("unexpected error when creating new HMAC") 117 } 118 tag, err := cipher.ComputeMAC(nil) 119 if err != nil { 120 t.Errorf("cipher.ComputeMAC(nil) failed: %v", err) 121 } 122 if err := cipher.VerifyMAC(tag, nil); err != nil { 123 t.Errorf("cipher.VerifyMAC(tag, nil) failed: %v", err) 124 } 125} 126 127func TestVerifyMACWithInvalidInput(t *testing.T) { 128 cipher, err := subtle.NewHMAC("SHA256", random.GetRandomBytes(16), 32) 129 if err != nil { 130 t.Errorf("unexpected error when creating new HMAC") 131 } 132 if err := cipher.VerifyMAC(nil, []byte{1}); err == nil { 133 t.Errorf("expect an error when mac is nil") 134 } 135 if err := cipher.VerifyMAC([]byte{1}, nil); err == nil { 136 t.Errorf("expect an error when data is nil") 137 } 138 if err := cipher.VerifyMAC(nil, nil); err == nil { 139 t.Errorf("cipher.VerifyMAC(nil, nil) succeeded unexpectedly") 140 } 141} 142 143func TestHMACModification(t *testing.T) { 144 for i, test := range hmacTests { 145 cipher, err := subtle.NewHMAC(test.hashAlg, test.key, test.tagSize) 146 if err != nil { 147 t.Errorf("cannot create new mac in test case %d: %s", i, err) 148 } 149 mac, _ := cipher.ComputeMAC(test.data) 150 for i := 0; i < len(mac); i++ { 151 tmp := mac[i] 152 for j := 0; j < 8; j++ { 153 mac[i] ^= 1 << uint8(j) 154 err := cipher.VerifyMAC(mac, test.data) 155 if err == nil { 156 t.Errorf("test case %d: modified MAC should be invalid", i) 157 } 158 mac[i] = tmp 159 } 160 } 161 } 162} 163 164func TestHMACTruncation(t *testing.T) { 165 for i, test := range hmacTests { 166 cipher, err := subtle.NewHMAC(test.hashAlg, test.key, test.tagSize) 167 if err != nil { 168 t.Errorf("cannot create new mac in test case %d: %s", i, err) 169 } 170 mac, _ := cipher.ComputeMAC(test.data) 171 for i := 1; i < len(mac); i++ { 172 tmp := mac[:i] 173 err := cipher.VerifyMAC(tmp, test.data) 174 if err == nil { 175 t.Errorf("test case %d: truncated MAC should be invalid", i) 176 } 177 } 178 } 179} 180