1// Copyright 2022 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 streamingprf 18 19import ( 20 "fmt" 21 "hash" 22 "io" 23 24 "golang.org/x/crypto/hkdf" 25 "github.com/google/tink/go/subtle" 26) 27 28// minHKDFStreamingPRFKeySize is the minimum allowed key size in bytes. 29const minHKDFStreamingPRFKeySize = 32 30 31// hkdfStreamingPRF is a HKDF Streaming PRF that implements StreamingPRF. 32type hkdfStreamingPRF struct { 33 h func() hash.Hash 34 key []byte 35 salt []byte 36} 37 38// Asserts that hkdfStreamingPRF implements the StreamingPRF interface. 39var _ StreamingPRF = (*hkdfStreamingPRF)(nil) 40 41// newHKDFStreamingPRF constructs a new hkdfStreamingPRF using hashName, key, 42// and salt. Salt can be nil. 43func newHKDFStreamingPRF(hashName string, key, salt []byte) (*hkdfStreamingPRF, error) { 44 if err := validateHKDFStreamingPRFParams(hashName, len(key)); err != nil { 45 return nil, err 46 } 47 return &hkdfStreamingPRF{ 48 h: subtle.GetHashFunc(hashName), 49 key: key, 50 salt: salt, 51 }, nil 52} 53 54// Compute computes and returns the HKDF as a Reader. 55func (h *hkdfStreamingPRF) Compute(data []byte) (io.Reader, error) { 56 return hkdf.New(h.h, h.key, h.salt, data), nil 57} 58 59func validateHKDFStreamingPRFParams(hash string, keySize int) error { 60 if hash != "SHA256" && hash != "SHA512" { 61 return fmt.Errorf("only SHA-256, SHA-512 allowed for HKDF") 62 } 63 if keySize < minHKDFStreamingPRFKeySize { 64 return fmt.Errorf("key too short, require %d-bytes: %d", minHKDFStreamingPRFKeySize, keySize) 65 } 66 return nil 67} 68