github.com/psiphon-Labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/quic/gquic-go/internal/crypto/hkdf.go (about)

     1  package crypto
     2  
     3  import (
     4  	"crypto"
     5  	"crypto/hmac"
     6  	"encoding/binary"
     7  )
     8  
     9  // copied from https://github.com/cloudflare/tls-tris/blob/master/hkdf.go
    10  func hkdfExtract(hash crypto.Hash, secret, salt []byte) []byte {
    11  	if salt == nil {
    12  		salt = make([]byte, hash.Size())
    13  	}
    14  	if secret == nil {
    15  		secret = make([]byte, hash.Size())
    16  	}
    17  	extractor := hmac.New(hash.New, salt)
    18  	extractor.Write(secret)
    19  	return extractor.Sum(nil)
    20  }
    21  
    22  // copied from https://github.com/cloudflare/tls-tris/blob/master/hkdf.go
    23  func hkdfExpand(hash crypto.Hash, prk, info []byte, l int) []byte {
    24  	var (
    25  		expander = hmac.New(hash.New, prk)
    26  		res      = make([]byte, l)
    27  		counter  = byte(1)
    28  		prev     []byte
    29  	)
    30  
    31  	if l > 255*expander.Size() {
    32  		panic("hkdf: requested too much output")
    33  	}
    34  
    35  	p := res
    36  	for len(p) > 0 {
    37  		expander.Reset()
    38  		expander.Write(prev)
    39  		expander.Write(info)
    40  		expander.Write([]byte{counter})
    41  		prev = expander.Sum(prev[:0])
    42  		counter++
    43  		n := copy(p, prev)
    44  		p = p[n:]
    45  	}
    46  
    47  	return res
    48  }
    49  
    50  func qhkdfExpand(secret []byte, label string, length int) []byte {
    51  	qlabel := make([]byte, 2+1+5+len(label))
    52  	binary.BigEndian.PutUint16(qlabel[0:2], uint16(length))
    53  	qlabel[2] = uint8(5 + len(label))
    54  	copy(qlabel[3:], []byte("QUIC "+label))
    55  	return hkdfExpand(crypto.SHA256, secret, qlabel, length)
    56  }