github.com/zntrio/harp/v2@v2.0.9/pkg/sdk/value/encryption/dae/helpers.go (about) 1 // Licensed to Elasticsearch B.V. under one or more contributor 2 // license agreements. See the NOTICE file distributed with 3 // this work for additional information regarding copyright 4 // ownership. Elasticsearch B.V. licenses this file to you under 5 // the Apache License, Version 2.0 (the "License"); you may 6 // not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, 12 // software distributed under the License is distributed on an 13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 // KIND, either express or implied. See the License for the 15 // specific language governing permissions and limitations 16 // under the License. 17 18 package dae 19 20 import ( 21 "bytes" 22 "crypto/cipher" 23 "crypto/hmac" 24 "crypto/sha256" 25 "encoding/base64" 26 "errors" 27 "fmt" 28 "hash" 29 "io" 30 "strings" 31 32 "golang.org/x/crypto/hkdf" 33 ) 34 35 // decode the input key 36 // <key>(:<salt>)? 37 func decodeKey(key string) (k, salt []byte, err error) { 38 // Check arguments 39 if key == "" { 40 return nil, nil, errors.New("input key must not be blank") 41 } 42 43 // Try to split input key 44 parts := strings.Split(key, ":") 45 if len(parts) > 2 { 46 return nil, nil, errors.New("unable to decode input key") 47 } 48 49 // Decode key 50 k, err = base64.URLEncoding.DecodeString(parts[0]) 51 if err != nil { 52 return nil, nil, fmt.Errorf("unable to decode key: %w", err) 53 } 54 55 // Are we using salt? 56 if len(parts) > 1 { 57 // Decode salt 58 salt, err = base64.URLEncoding.DecodeString(parts[1]) 59 if err != nil { 60 return nil, nil, fmt.Errorf("unable to decode salt: %w", err) 61 } 62 } 63 64 return k, salt, err 65 } 66 67 //nolint:unparam // info is always nil 68 func deriveKey(secret, salt, info []byte, dkLen int) ([]byte, error) { 69 // Prepare HKDF-SHA256 70 reader := hkdf.New(sha256.New, secret, salt, info) 71 72 // Prepare output buffer 73 out := bytes.NewBuffer(nil) 74 out.Grow(dkLen) 75 limReader := &io.LimitedReader{ 76 R: reader, 77 N: int64(dkLen), 78 } 79 80 // Read all data from buffer 81 n, err := out.ReadFrom(limReader) 82 if err != nil { 83 return nil, fmt.Errorf("unable to derive key: %w", err) 84 } 85 if n != int64(dkLen) { 86 return nil, errors.New("invalid derived key length") 87 } 88 89 // No error 90 return out.Bytes(), nil 91 } 92 93 // ----------------------------------------------------------------------------- 94 95 type NonceDeriverFunc func([]byte, cipher.AEAD) ([]byte, error) 96 97 func HMAC(h func() hash.Hash, key []byte) NonceDeriverFunc { 98 return func(input []byte, ciph cipher.AEAD) ([]byte, error) { 99 hm := hmac.New(h, key) 100 hm.Write(input) 101 nonceSum := hm.Sum(nil) 102 nonce := nonceSum[:ciph.NonceSize()] 103 return nonce, nil 104 } 105 } 106 107 func Keyed(key []byte, khf func([]byte) (hash.Hash, error)) NonceDeriverFunc { 108 return func(input []byte, ciph cipher.AEAD) ([]byte, error) { 109 hm, err := khf(key) 110 if err != nil { 111 return nil, fmt.Errorf("dae: unable to initialize blake2b nonce deriver: %w", err) 112 } 113 hm.Write(input) 114 nonceSum := hm.Sum(nil) 115 nonce := nonceSum[:ciph.NonceSize()] 116 return nonce, nil 117 } 118 }