github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/cloudflare/cfssl/auth/auth.go (about) 1 // Package auth implements an interface for providing CFSSL 2 // authentication. This is meant to authenticate a client CFSSL to a 3 // remote CFSSL in order to prevent unauthorised use of the signature 4 // capabilities. This package provides both the interface and a 5 // standard HMAC-based implementation. 6 package auth 7 8 import ( 9 "crypto/hmac" 10 "crypto/sha256" 11 "encoding/hex" 12 "fmt" 13 "io/ioutil" 14 "os" 15 "strings" 16 ) 17 18 // An AuthenticatedRequest contains a request and authentication 19 // token. The Provider may determine whether to validate the timestamp 20 // and remote address. 21 type AuthenticatedRequest struct { 22 // An Authenticator decides whether to use this field. 23 Timestamp int64 `json:"timestamp,omitempty"` 24 RemoteAddress []byte `json:"remote_address,omitempty"` 25 Token []byte `json:"token"` 26 Request []byte `json:"request"` 27 } 28 29 // A Provider can generate tokens from a request and verify a 30 // request. The handling of additional authentication data (such as 31 // the IP address) is handled by the concrete type, as is any 32 // serialisation and state-keeping. 33 type Provider interface { 34 Token(req []byte) (token []byte, err error) 35 Verify(aReq *AuthenticatedRequest) bool 36 } 37 38 // Standard implements an HMAC-SHA-256 authentication provider. It may 39 // be supplied additional data at creation time that will be used as 40 // request || additional-data with the HMAC. 41 type Standard struct { 42 key []byte 43 ad []byte 44 } 45 46 // New generates a new standard authentication provider from the key 47 // and additional data. The additional data will be used when 48 // generating a new token. 49 func New(key string, ad []byte) (*Standard, error) { 50 if splitKey := strings.SplitN(key, ":", 2); len(splitKey) == 2 { 51 switch splitKey[0] { 52 case "env": 53 key = os.Getenv(splitKey[1]) 54 case "file": 55 data, err := ioutil.ReadFile(splitKey[1]) 56 if err != nil { 57 return nil, err 58 } 59 key = string(data) 60 default: 61 return nil, fmt.Errorf("unknown key prefix: %s", splitKey[0]) 62 } 63 } 64 65 keyBytes, err := hex.DecodeString(key) 66 if err != nil { 67 return nil, err 68 } 69 70 return &Standard{keyBytes, ad}, nil 71 } 72 73 // Token generates a new authentication token from the request. 74 func (p Standard) Token(req []byte) (token []byte, err error) { 75 h := hmac.New(sha256.New, p.key) 76 h.Write(req) 77 h.Write(p.ad) 78 return h.Sum(nil), nil 79 } 80 81 // Verify determines whether an authenticated request is valid. 82 func (p Standard) Verify(ad *AuthenticatedRequest) bool { 83 if ad == nil { 84 return false 85 } 86 87 // Standard token generation returns no error. 88 token, _ := p.Token(ad.Request) 89 if len(ad.Token) != len(token) { 90 return false 91 } 92 93 return hmac.Equal(token, ad.Token) 94 }