File: stream.go

package info (click to toggle)
golang-github-aws-aws-sdk-go-v2 1.30.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 662,428 kB
  • sloc: java: 16,875; makefile: 432; sh: 175
file content (86 lines) | stat: -rw-r--r-- 2,537 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package v4

import (
	"context"
	"crypto/sha256"
	"encoding/hex"
	"github.com/aws/aws-sdk-go-v2/aws"
	v4Internal "github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4"
	"strings"
	"time"
)

// EventStreamSigner is an AWS EventStream protocol signer.
type EventStreamSigner interface {
	GetSignature(ctx context.Context, headers, payload []byte, signingTime time.Time, optFns ...func(*StreamSignerOptions)) ([]byte, error)
}

// StreamSignerOptions is the configuration options for StreamSigner.
type StreamSignerOptions struct{}

// StreamSigner implements Signature Version 4 (SigV4) signing of event stream encoded payloads.
type StreamSigner struct {
	options StreamSignerOptions

	credentials aws.Credentials
	service     string
	region      string

	prevSignature []byte

	signingKeyDeriver *v4Internal.SigningKeyDeriver
}

// NewStreamSigner returns a new AWS EventStream protocol signer.
func NewStreamSigner(credentials aws.Credentials, service, region string, seedSignature []byte, optFns ...func(*StreamSignerOptions)) *StreamSigner {
	o := StreamSignerOptions{}

	for _, fn := range optFns {
		fn(&o)
	}

	return &StreamSigner{
		options:           o,
		credentials:       credentials,
		service:           service,
		region:            region,
		signingKeyDeriver: v4Internal.NewSigningKeyDeriver(),
		prevSignature:     seedSignature,
	}
}

// GetSignature signs the provided header and payload bytes.
func (s *StreamSigner) GetSignature(ctx context.Context, headers, payload []byte, signingTime time.Time, optFns ...func(*StreamSignerOptions)) ([]byte, error) {
	options := s.options

	for _, fn := range optFns {
		fn(&options)
	}

	prevSignature := s.prevSignature

	st := v4Internal.NewSigningTime(signingTime)

	sigKey := s.signingKeyDeriver.DeriveKey(s.credentials, s.service, s.region, st)

	scope := v4Internal.BuildCredentialScope(st, s.region, s.service)

	stringToSign := s.buildEventStreamStringToSign(headers, payload, prevSignature, scope, &st)

	signature := v4Internal.HMACSHA256(sigKey, []byte(stringToSign))
	s.prevSignature = signature

	return signature, nil
}

func (s *StreamSigner) buildEventStreamStringToSign(headers, payload, previousSignature []byte, credentialScope string, signingTime *v4Internal.SigningTime) string {
	hash := sha256.New()
	return strings.Join([]string{
		"AWS4-HMAC-SHA256-PAYLOAD",
		signingTime.TimeFormat(),
		credentialScope,
		hex.EncodeToString(previousSignature),
		hex.EncodeToString(makeHash(hash, headers)),
		hex.EncodeToString(makeHash(hash, payload)),
	}, "\n")
}