github.com/Jeffail/benthos/v3@v3.65.0/lib/processor/hash.go (about) 1 package processor 2 3 import ( 4 "crypto/hmac" 5 "crypto/md5" 6 "crypto/sha1" 7 "crypto/sha256" 8 "crypto/sha512" 9 "fmt" 10 "strconv" 11 "time" 12 13 "github.com/Jeffail/benthos/v3/internal/docs" 14 "github.com/Jeffail/benthos/v3/internal/tracing" 15 "github.com/Jeffail/benthos/v3/lib/log" 16 "github.com/Jeffail/benthos/v3/lib/metrics" 17 "github.com/Jeffail/benthos/v3/lib/response" 18 "github.com/Jeffail/benthos/v3/lib/types" 19 "github.com/OneOfOne/xxhash" 20 ) 21 22 //------------------------------------------------------------------------------ 23 24 func init() { 25 Constructors[TypeHash] = TypeSpec{ 26 constructor: NewHash, 27 Status: docs.StatusDeprecated, 28 Footnotes: ` 29 ## Alternatives 30 31 All functionality of this processor has been superseded by the 32 [bloblang](/docs/components/processors/bloblang) processor.`, 33 FieldSpecs: docs.FieldSpecs{ 34 docs.FieldCommon("algorithm", "The hash algorithm to use.").HasOptions("sha256", "sha512", "sha1", "xxhash64", "hmac-sha1", "hmac-sha256", "hmac-sha512", "md5"), 35 docs.FieldCommon("key", "key used for HMAC algorithms"), 36 PartsFieldSpec, 37 }, 38 } 39 } 40 41 //------------------------------------------------------------------------------ 42 43 // HashConfig contains configuration fields for the Hash processor. 44 type HashConfig struct { 45 Parts []int `json:"parts" yaml:"parts"` 46 Algorithm string `json:"algorithm" yaml:"algorithm"` 47 Key string `json:"key" yaml:"key"` 48 } 49 50 // NewHashConfig returns a HashConfig with default values. 51 func NewHashConfig() HashConfig { 52 return HashConfig{ 53 Parts: []int{}, 54 Algorithm: "sha256", 55 } 56 } 57 58 //------------------------------------------------------------------------------ 59 60 type hashFunc func(bytes []byte) ([]byte, error) 61 62 func hmacsha1Hash(key string) hashFunc { 63 return func(b []byte) ([]byte, error) { 64 hasher := hmac.New(sha1.New, []byte(key)) 65 hasher.Write(b) 66 return hasher.Sum(nil), nil 67 } 68 } 69 70 func hmacsha256Hash(key string) hashFunc { 71 return func(b []byte) ([]byte, error) { 72 hasher := hmac.New(sha256.New, []byte(key)) 73 hasher.Write(b) 74 return hasher.Sum(nil), nil 75 } 76 } 77 78 func hmacsha512Hash(key string) hashFunc { 79 return func(b []byte) ([]byte, error) { 80 hasher := hmac.New(sha512.New, []byte(key)) 81 hasher.Write(b) 82 return hasher.Sum(nil), nil 83 } 84 } 85 86 func md5Hash(b []byte) ([]byte, error) { 87 hasher := md5.New() 88 hasher.Write(b) 89 return hasher.Sum(nil), nil 90 } 91 92 func sha1Hash(b []byte) ([]byte, error) { 93 hasher := sha1.New() 94 hasher.Write(b) 95 return hasher.Sum(nil), nil 96 } 97 98 func sha256Hash(b []byte) ([]byte, error) { 99 hasher := sha256.New() 100 hasher.Write(b) 101 return hasher.Sum(nil), nil 102 } 103 104 func sha512Hash(b []byte) ([]byte, error) { 105 hasher := sha512.New() 106 hasher.Write(b) 107 return hasher.Sum(nil), nil 108 } 109 110 func xxhash64Hash(b []byte) ([]byte, error) { 111 h := xxhash.New64() 112 h.Write(b) 113 return []byte(strconv.FormatUint(h.Sum64(), 10)), nil 114 } 115 116 func strToHashr(conf HashConfig) (hashFunc, error) { 117 switch conf.Algorithm { 118 case "hmac-sha1": 119 return hmacsha1Hash(conf.Key), nil 120 case "hmac-sha256": 121 return hmacsha256Hash(conf.Key), nil 122 case "hmac-sha512": 123 return hmacsha512Hash(conf.Key), nil 124 case "md5": 125 return md5Hash, nil 126 case "sha1": 127 return sha1Hash, nil 128 case "sha256": 129 return sha256Hash, nil 130 case "sha512": 131 return sha512Hash, nil 132 case "xxhash64": 133 return xxhash64Hash, nil 134 } 135 return nil, fmt.Errorf("hash algorithm not recognised: %v", conf.Algorithm) 136 } 137 138 //------------------------------------------------------------------------------ 139 140 // Hash is a processor that can selectively hash parts of a message following a 141 // chosen algorithm. 142 type Hash struct { 143 conf HashConfig 144 fn hashFunc 145 146 log log.Modular 147 stats metrics.Type 148 149 mCount metrics.StatCounter 150 mErr metrics.StatCounter 151 mSent metrics.StatCounter 152 mBatchSent metrics.StatCounter 153 } 154 155 // NewHash returns a Hash processor. 156 func NewHash( 157 conf Config, mgr types.Manager, log log.Modular, stats metrics.Type, 158 ) (Type, error) { 159 cor, err := strToHashr(conf.Hash) 160 if err != nil { 161 return nil, err 162 } 163 return &Hash{ 164 conf: conf.Hash, 165 fn: cor, 166 log: log, 167 stats: stats, 168 169 mCount: stats.GetCounter("count"), 170 mErr: stats.GetCounter("error"), 171 mSent: stats.GetCounter("sent"), 172 mBatchSent: stats.GetCounter("batch.sent"), 173 }, nil 174 } 175 176 //------------------------------------------------------------------------------ 177 178 // ProcessMessage applies the processor to a message, either creating >0 179 // resulting messages or a response to be sent back to the message source. 180 func (c *Hash) ProcessMessage(msg types.Message) ([]types.Message, types.Response) { 181 c.mCount.Incr(1) 182 183 newMsg := msg.Copy() 184 185 proc := func(index int, span *tracing.Span, part types.Part) error { 186 newPart, err := c.fn(part.Get()) 187 if err == nil { 188 newMsg.Get(index).Set(newPart) 189 } else { 190 c.log.Debugf("Failed to hash message part: %v\n", err) 191 c.mErr.Incr(1) 192 } 193 return err 194 } 195 196 if newMsg.Len() == 0 { 197 return nil, response.NewAck() 198 } 199 200 IteratePartsWithSpanV2(TypeHash, c.conf.Parts, newMsg, proc) 201 202 c.mBatchSent.Incr(1) 203 c.mSent.Incr(int64(newMsg.Len())) 204 msgs := [1]types.Message{newMsg} 205 return msgs[:], nil 206 } 207 208 // CloseAsync shuts down the processor and stops processing requests. 209 func (c *Hash) CloseAsync() { 210 } 211 212 // WaitForClose blocks until the processor has closed down. 213 func (c *Hash) WaitForClose(timeout time.Duration) error { 214 return nil 215 } 216 217 //------------------------------------------------------------------------------