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 "testing" 22 23 "github.com/google/tink/go/subtle" 24) 25 26func TestHKDFBasic(t *testing.T) { 27 // Test vectors from RFC 5869, Appendix A. 28 // 29 // The name and desc fields align with the content from the RFC for easy 30 // cross referencing. 31 var tests = []struct { 32 name string 33 desc string 34 hashAlg string 35 key string 36 salt string 37 info string 38 tagSize uint32 39 okm string 40 }{ 41 { 42 name: "TestCase1", 43 desc: "Basic test case with SHA-256", 44 hashAlg: "SHA256", 45 key: "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", 46 salt: "000102030405060708090a0b0c", 47 info: "f0f1f2f3f4f5f6f7f8f9", 48 tagSize: 42, 49 okm: "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865", 50 }, 51 { 52 name: "TestCase2", 53 desc: "Test with SHA-256 and longer inputs/outputs", 54 hashAlg: "SHA256", 55 key: "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + 56 "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + 57 "404142434445464748494a4b4c4d4e4f", 58 salt: "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + 59 "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" + 60 "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", 61 info: "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + 62 "d0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeef" + 63 "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", 64 tagSize: 82, 65 okm: "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c" + 66 "59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71" + 67 "cc30c58179ec3e87c14c01d5c1f3434f1d87", 68 }, 69 { 70 name: "TestCase3", 71 desc: "Test with SHA-256 and zero-length salt/info", 72 hashAlg: "SHA256", 73 key: "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", 74 salt: "", 75 info: "", 76 tagSize: 42, 77 okm: "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d" + 78 "9d201395faa4b61a96c8", 79 }, 80 { 81 name: "TestCase4", 82 desc: "Basic test case with SHA-1", 83 hashAlg: "SHA1", 84 key: "0b0b0b0b0b0b0b0b0b0b0b", 85 salt: "000102030405060708090a0b0c", 86 info: "f0f1f2f3f4f5f6f7f8f9", 87 tagSize: 42, 88 okm: "085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896", 89 }, 90 { 91 name: "TestCase5", 92 desc: "Test with SHA-1 and longer inputs/outputs", 93 hashAlg: "SHA1", 94 key: "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + 95 "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + 96 "404142434445464748494a4b4c4d4e4f", 97 salt: "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + 98 "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" + 99 "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", 100 info: "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + 101 "d0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeef" + 102 "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", 103 tagSize: 82, 104 okm: "0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe" + 105 "8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e" + 106 "927336d0441f4c4300e2cff0d0900b52d3b4", 107 }, 108 { 109 name: "TestCase6", 110 desc: "Test with SHA-1 and zero-length salt/info", 111 hashAlg: "SHA1", 112 key: "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", 113 salt: "", 114 info: "", 115 tagSize: 42, 116 okm: "0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0" + 117 "ea00033de03984d34918", 118 }, 119 { 120 name: "TestCase7", 121 desc: "Test with SHA-1, salt not provided (defaults to HashLen zero octets), zero-length info", 122 hashAlg: "SHA1", 123 key: "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", 124 salt: "", 125 info: "", 126 tagSize: 42, 127 okm: "2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5" + 128 "673a081d70cce7acfc48", 129 }, 130 } 131 132 for _, test := range tests { 133 t.Run(test.name, func(t *testing.T) { 134 key, err := hex.DecodeString(test.key) 135 if err != nil { 136 t.Fatalf("%s\nhex.DecodeString(key) err = %v", test.desc, err) 137 } 138 salt, err := hex.DecodeString(test.salt) 139 if err != nil { 140 t.Fatalf("%s\nFailed decoding salt: %v", test.desc, err) 141 } 142 info, err := hex.DecodeString(test.info) 143 if err != nil { 144 t.Fatalf("%s\nFailed decoding info: %v", test.desc, err) 145 } 146 147 okm, err := subtle.ComputeHKDF(test.hashAlg, key, salt, info, test.tagSize) 148 if err != nil { 149 t.Errorf("%s\nsubtle.ComputeHKDF() err = %v, want nil", test.desc, err) 150 } 151 if got, want := hex.EncodeToString(okm), test.okm; got != want { 152 t.Errorf("%s\nsubtle.ComputeHKDF() = %q, want %q", test.desc, got, want) 153 } 154 }) 155 } 156} 157 158func TestNewHMACWithInvalidInput(t *testing.T) { 159 var tests = []struct { 160 name string 161 hashAlg string 162 tagSize uint32 163 }{ 164 { 165 name: "invalid algorithm", 166 hashAlg: "SHA0", 167 tagSize: 32, 168 }, 169 { 170 name: "tag too short", 171 hashAlg: "SHA256", 172 tagSize: 9, 173 }, 174 { 175 name: "tag too big", 176 hashAlg: "SHA512", 177 tagSize: 16323, 178 }, 179 } 180 181 for _, test := range tests { 182 t.Run(test.name, func(t *testing.T) { 183 if _, err := subtle.ComputeHKDF(test.hashAlg, nil, nil, nil, test.tagSize); err == nil { 184 t.Fatalf("subtle.ComputeHKDF(%q, nil, nil, nil, %d) err is nil, want not nil", test.hashAlg, test.tagSize) 185 } 186 }) 187 } 188} 189