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