Skip to content

Commit

Permalink
replace sha1 with sha2-256 (#19779)
Browse files Browse the repository at this point in the history
Stop using sha-1, a deprecated hashing algorithm which triggers security reports, and use sha2-256 instead.

Link to tracking Issue:
Fixes #4759 and #5576
  • Loading branch information
atoulme authored Mar 24, 2023
1 parent 34401c2 commit 024a11c
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 10 deletions.
16 changes: 16 additions & 0 deletions .chloggen/introduce_sha2Hasher.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: attributesprocessor, resourceprocessor

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Add feature gate to support using SHA2-256 instead of SHA-1 for hashing

# One or more tracking issues related to the change
issues: [4759, 5576]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext: enable switching to use SHA-2 256 with the feature gate `coreinternal.attraction.hash.sha256`
21 changes: 17 additions & 4 deletions internal/coreinternal/attraction/attraction.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,17 @@ import (
"strings"

"go.opentelemetry.io/collector/client"
"go.opentelemetry.io/collector/featuregate"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.uber.org/zap"
)

var enableSha256Gate = featuregate.GlobalRegistry().MustRegister(
"coreinternal.attraction.hash.sha256",
featuregate.StageAlpha,
featuregate.WithRegisterDescription("When enabled, switches hashing algorithm from SHA-1 to SHA-2 256"),
)

// Settings specifies the processor settings.
type Settings struct {
// Actions specifies the list of attributes to act on.
Expand Down Expand Up @@ -85,7 +92,9 @@ type ActionKeyValue struct {
// DELETE - Deletes the attribute. If the key doesn't exist,
// no action is performed.
// HASH - Calculates the SHA-1 hash of an existing value and overwrites the
// value with it's SHA-1 hash result.
// value with its SHA-1 hash result. If the feature gate
// `coreinternal.attraction.hash.sha256` is enabled, it uses SHA2-256
// instead.
// EXTRACT - Extracts values using a regular expression rule from the input
// 'key' to target keys specified in the 'rule'. If a target key
// already exists, it will be overridden.
Expand Down Expand Up @@ -132,8 +141,8 @@ const (
// Supports pattern which is matched against attribute key.
DELETE Action = "delete"

// HASH calculates the SHA-1 hash of an existing value and overwrites the
// value with it's SHA-1 hash result.
// HASH calculates the SHA-256 hash of an existing value and overwrites the
// value with it's SHA-256 hash result.
// Supports pattern which is matched against attribute key.
HASH Action = "hash"

Expand Down Expand Up @@ -405,7 +414,11 @@ func getSourceAttributeValue(ctx context.Context, action attributeAction, attrs

func hashAttribute(key string, attrs pcommon.Map) {
if value, exists := attrs.Get(key); exists {
sha1Hasher(value)
if enableSha256Gate.IsEnabled() {
sha2Hasher(value)
} else {
sha1Hasher(value)
}
}
}

Expand Down
26 changes: 20 additions & 6 deletions internal/coreinternal/attraction/attraction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package attraction
import (
"context"
"crypto/sha1" // #nosec
"crypto/sha256"
"encoding/binary"
"errors"
"fmt"
Expand Down Expand Up @@ -630,7 +631,7 @@ func TestAttributes_HashValue(t *testing.T) {
"updateme": "foo",
},
expectedAttributes: map[string]interface{}{
"updateme": sha1Hash([]byte("foo")),
"updateme": hash([]byte("foo")),
},
},
// Ensure int data types are hashed correctly
Expand All @@ -640,7 +641,7 @@ func TestAttributes_HashValue(t *testing.T) {
"updateme": intVal,
},
expectedAttributes: map[string]interface{}{
"updateme": sha1Hash(intBytes),
"updateme": hash(intBytes),
},
},
// Ensure double data types are hashed correctly
Expand All @@ -650,7 +651,7 @@ func TestAttributes_HashValue(t *testing.T) {
"updateme": doubleVal,
},
expectedAttributes: map[string]interface{}{
"updateme": sha1Hash(doubleBytes),
"updateme": hash(doubleBytes),
},
},
// Ensure bool data types are hashed correctly
Expand All @@ -660,7 +661,7 @@ func TestAttributes_HashValue(t *testing.T) {
"updateme": true,
},
expectedAttributes: map[string]interface{}{
"updateme": sha1Hash([]byte{1}),
"updateme": hash([]byte{1}),
},
},
// Ensure bool data types are hashed correctly
Expand All @@ -670,7 +671,7 @@ func TestAttributes_HashValue(t *testing.T) {
"updateme": false,
},
expectedAttributes: map[string]interface{}{
"updateme": sha1Hash([]byte{0}),
"updateme": hash([]byte{0}),
},
},
// Ensure regex pattern is being used
Expand All @@ -681,7 +682,7 @@ func TestAttributes_HashValue(t *testing.T) {
"donotupdatemebyregexp": false,
},
expectedAttributes: map[string]interface{}{
"updatemebyregexp": sha1Hash([]byte{0}),
"updatemebyregexp": hash([]byte{0}),
"donotupdatemebyregexp": false,
},
},
Expand Down Expand Up @@ -939,13 +940,26 @@ func TestValidConfiguration(t *testing.T) {

}

func hash(b []byte) string {
if enableSha256Gate.IsEnabled() {
return sha2Hash(b)
}
return sha1Hash(b)
}

func sha1Hash(b []byte) string {
// #nosec
h := sha1.New()
h.Write(b)
return fmt.Sprintf("%x", h.Sum(nil))
}

func sha2Hash(b []byte) string {
h := sha256.New()
h.Write(b)
return fmt.Sprintf("%x", h.Sum(nil))
}

type mockInfoAuth map[string]interface{}

func (a mockInfoAuth) GetAttribute(name string) interface{} {
Expand Down
38 changes: 38 additions & 0 deletions internal/coreinternal/attraction/hasher.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package attraction // import "github.com/open-telemetry/opentelemetry-collector-

import (
"crypto/sha1" // #nosec
"crypto/sha256"
"encoding/binary"
"encoding/hex"
"math"
Expand All @@ -33,6 +34,7 @@ var (
byteFalse = [1]byte{0}
)

// Deprecated: [v0.75.0] use sha2Hasher instead.
// sha1Hasher hashes an AttributeValue using SHA1 and returns a
// hashed version of the attribute. In practice, this would mostly be used
// for string attributes but we support all types for completeness/correctness
Expand Down Expand Up @@ -69,3 +71,39 @@ func sha1Hasher(attr pcommon.Value) {

attr.SetStr(hashed)
}

// sha2Hasher hashes an AttributeValue using SHA2-256 and returns a
// hashed version of the attribute. In practice, this would mostly be used
// for string attributes but we support all types for completeness/correctness
// and eliminate any surprises.
func sha2Hasher(attr pcommon.Value) {
var val []byte
switch attr.Type() {
case pcommon.ValueTypeStr:
val = []byte(attr.Str())
case pcommon.ValueTypeBool:
if attr.Bool() {
val = byteTrue[:]
} else {
val = byteFalse[:]
}
case pcommon.ValueTypeInt:
val = make([]byte, int64ByteSize)
binary.LittleEndian.PutUint64(val, uint64(attr.Int()))
case pcommon.ValueTypeDouble:
val = make([]byte, float64ByteSize)
binary.LittleEndian.PutUint64(val, math.Float64bits(attr.Double()))
}

var hashed string
if len(val) > 0 {
h := sha256.New()
_, _ = h.Write(val)
val = h.Sum(nil)
hashedBytes := make([]byte, hex.EncodedLen(len(val)))
hex.Encode(hashedBytes, val)
hashed = string(hashedBytes)
}

attr.SetStr(hashed)
}
1 change: 1 addition & 0 deletions internal/coreinternal/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.19
require (
github.com/stretchr/testify v1.8.2
go.opentelemetry.io/collector v0.74.0
go.opentelemetry.io/collector/featuregate v0.74.0
go.opentelemetry.io/collector/pdata v1.0.0-rc8
go.opentelemetry.io/collector/semconv v0.74.0
go.uber.org/zap v1.24.0
Expand Down
2 changes: 2 additions & 0 deletions internal/coreinternal/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 024a11c

Please sign in to comment.