src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

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 }