stream.go (2544B)
1 package v4 2 3 import ( 4 "context" 5 "crypto/sha256" 6 "encoding/hex" 7 "strings" 8 "time" 9 10 "github.com/aws/aws-sdk-go-v2/aws" 11 v4Internal "github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4" 12 ) 13 14 // EventStreamSigner is an AWS EventStream protocol signer. 15 type EventStreamSigner interface { 16 GetSignature(ctx context.Context, headers, payload []byte, signingTime time.Time, optFns ...func(*StreamSignerOptions)) ([]byte, error) 17 } 18 19 // StreamSignerOptions is the configuration options for StreamSigner. 20 type StreamSignerOptions struct{} 21 22 // StreamSigner implements Signature Version 4 (SigV4) signing of event stream encoded payloads. 23 type StreamSigner struct { 24 options StreamSignerOptions 25 26 credentials aws.Credentials 27 service string 28 region string 29 30 prevSignature []byte 31 32 signingKeyDeriver *v4Internal.SigningKeyDeriver 33 } 34 35 // NewStreamSigner returns a new AWS EventStream protocol signer. 36 func NewStreamSigner(credentials aws.Credentials, service, region string, seedSignature []byte, optFns ...func(*StreamSignerOptions)) *StreamSigner { 37 o := StreamSignerOptions{} 38 39 for _, fn := range optFns { 40 fn(&o) 41 } 42 43 return &StreamSigner{ 44 options: o, 45 credentials: credentials, 46 service: service, 47 region: region, 48 signingKeyDeriver: v4Internal.NewSigningKeyDeriver(), 49 prevSignature: seedSignature, 50 } 51 } 52 53 // GetSignature signs the provided header and payload bytes. 54 func (s *StreamSigner) GetSignature(ctx context.Context, headers, payload []byte, signingTime time.Time, optFns ...func(*StreamSignerOptions)) ([]byte, error) { 55 options := s.options 56 57 for _, fn := range optFns { 58 fn(&options) 59 } 60 61 prevSignature := s.prevSignature 62 63 st := v4Internal.NewSigningTime(signingTime.UTC()) 64 65 sigKey := s.signingKeyDeriver.DeriveKey(s.credentials, s.service, s.region, st) 66 67 scope := v4Internal.BuildCredentialScope(st, s.region, s.service) 68 69 stringToSign := s.buildEventStreamStringToSign(headers, payload, prevSignature, scope, &st) 70 71 signature := v4Internal.HMACSHA256(sigKey, []byte(stringToSign)) 72 s.prevSignature = signature 73 74 return signature, nil 75 } 76 77 func (s *StreamSigner) buildEventStreamStringToSign(headers, payload, previousSignature []byte, credentialScope string, signingTime *v4Internal.SigningTime) string { 78 hash := sha256.New() 79 return strings.Join([]string{ 80 "AWS4-HMAC-SHA256-PAYLOAD", 81 signingTime.TimeFormat(), 82 credentialScope, 83 hex.EncodeToString(previousSignature), 84 hex.EncodeToString(makeHash(hash, headers)), 85 hex.EncodeToString(makeHash(hash, payload)), 86 }, "\n") 87 }