signature

package module
v1.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 13, 2020 License: BSD-3-Clause Imports: 13 Imported by: 5

README

go-signature

Verify signed HTTP requests from Manifold

Code of Conduct | Contribution Guidelines

GitHub release GoDoc Travis Go Report Card License

Usage

import "github.com/manifoldco/go-signature"

signature includes middleware that conforms to the http.Handler interface, wrapping another http.Handler. If the request is invalid, the middleware will respond directly, instead of calling your handler.

Using the included middleware:

verifier, _ := signature.NewVerifier(signature.ManifoldKey)
http.Handle("/v1", verifier.WrapFunc(func (rw http.ResponseWriter, r *http.Request) {
	// your code goes here.
}))

Verifying a request manually:

body, err := ioutil.ReadAll(req.Body)
buf := bytes.NewBuffer(body)

verifier, err := signature.NewVerifier(signature.ManifoldKey)
if err := verifier.Verify(req, buf); err != nil {
	// return an error...
}

// continue using the request and body

Manual verification may be useful if you are not using a standard net/http setup.

Documentation

Overview

Package signature provides validation of signed HTTP requests from Manifold.

signature includes middleware that conforms to the http.Handler interface, wrapping another http.Handler. If the request is invalid, the middleware will respond directly, instead of calling your handler.

Using the included middleware:

verifier := signature.NewVerifier(signature.ManifoldKey)
http.Handle("/v1", verifier.WrapFunc(func (rw http.ResponseWriter, r *http.Request) {
	// your code goes here.
}))

Verifying a request manually:

body, err := ioutil.ReadAll(req.Body)
buf := bytes.NewBuffer(body)

verifiier := signature.NewVerifier(signature.ManifoldKey)
if err := verifiier.Verify(req, buf); err != nil {
	// return an error...
}

// continue using the request and body

Manual verification may be useful if you are not using a standard net/http setup.

Index

Examples

Constants

View Source
const ManifoldKey = "PtISNzqQmQPBxNlUw3CdxsWczXbIwyExxlkRqZ7E690"

ManifoldKey is Manifold's public master signing key, base64 encoded.

View Source
const PermittedTimeSkew = 5 * time.Minute

PermittedTimeSkew is the time skew allowed on requests, on either side.

Variables

View Source
var ErrInvalidPublicKey = errors.New("The provided base64 public key is not valid")

ErrInvalidPublicKey is returned from NewVerifier when the provided public key is not valid

Functions

func Canonize

func Canonize(req *http.Request, body io.Reader) ([]byte, error)

Canonize builds the canonical representation of the given request, for use in verifying the Manifold request signature applied to it. The request body is not read directly, instead, body is read, allowing buffering or duplication of the body to be handled outside of this func.

Example
body := bytes.NewBufferString("Test body data")
req, _ := http.NewRequest("PUT", "/v1/resources?foo=bar", body)
req.Header.Set("X-Signed-Headers", "date")
req.Header.Set("Date", "2017-03-05T23:53:08Z")
b, _ := Canonize(req, body)

fmt.Println()
fmt.Println(string(b))
Output:

put /v1/resources?foo=bar
date: 2017-03-05T23:53:08Z
x-signed-headers: date
Test body data

Types

type Error

type Error struct {
	Code    int    `json:"-"` // The HTTP status code.
	Message string `json:"message"`
}

Error represents an unsuccessful HTTP error response.

func (*Error) Error

func (e *Error) Error() string

Error implements the standard error interface for signature Errors.

func (*Error) Respond

func (e *Error) Respond(rw http.ResponseWriter)

Respond writes the Error to the provided ResponseWriter as JSON, in the format expected by Manifold for errors.

type Middleware

type Middleware func(http.ResponseWriter, *http.Request, http.HandlerFunc)

Middleware implements the Negroni middleware interface for funcs

func (Middleware) ServeHTTP

func (m Middleware) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)

type Signature

type Signature struct {
	Value       *base64.Value
	PublicKey   *base64.Value
	Endorsement *base64.Value
}

Signature represents a Signature of an HTTP request

func ParseSignature

func ParseSignature(value string) (*Signature, error)

ParseSignature parses the given string and returns a Signature struct

func (*Signature) String

func (s *Signature) String() string

String returns the string representatino of a Signature

func (*Signature) Validate

func (s *Signature) Validate(masterPubKey ed25519.PublicKey, b []byte) error

Validate returns an error if the given byte slice does not match this signature

type Verifier

type Verifier struct {
	// contains filtered or unexported fields
}

Verifier verifies that HTTP requests are signed by Manifold

func NewVerifier

func NewVerifier(publicKey string) (*Verifier, error)

NewVerifier returns a new Verifier, configured with the provided raw base64 URL encoded public key.

It returns an error if the given public key is not a valid base64 URL encoded value, or if it is not a valid Ed25519 public key.

func (*Verifier) Negroni

func (v *Verifier) Negroni() Middleware

Negroni returns a Negroni compatible middleware for verifying requests. This middleware behaves like Wrap; it will not pass through to the next Handler in the chain if the request does not have a valid signature.

func (*Verifier) Verify

func (v *Verifier) Verify(req *http.Request, body io.Reader) error

Verify verifies that the given request is signed by Manifold. It returns an error if the signature is invalid. The request body is not read directly, instead, body is read, allowing buffering or duplication of the body to be handled outside of this method.

Example
body := bytes.NewBufferString("{\"id\":\"2686c96868emyj61cgt2ma7vdntg4\",\"plan\":\"low\",\"product\":\"generators\",\"region\":\"aws::us-east-1\",\"user_id\":\"200e7aeg2kf2d6nud8jran3zxnz5j\"}\n")
req, _ := http.NewRequest("PUT", "https://127.0.0.1:4567/v1/resources/2686c96868emyj61cgt2ma7vdntg4", body)

req.Host = "127.0.0.1:4567"
req.Header.Set("Date", "2017-03-05T23:53:08Z")
req.Header.Set("Content-Length", "143")
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Signed-Headers", "host date content-type content-length")
req.Header.Set("X-Signature", "Nb9iJZVDFrcf8-dw7AsuSCPtdoxoAr61YVWQe-5b9z_YiuQW73wR7RRsDBPnrBMtXIg_h8yKWsr-ZNRgYbM7CA FzNbTkRjAGjkpwHUbAhjvLsIlAlL_M6EUh5E9OVEwXs qGR6iozBfLUCHbRywz1mHDdGYeqZ0JEcseV4KcwjEVeZtQN54odcJ1_QyZkmHacbQeHEai2-Aw9EF8-Ceh09Cg")

// For production usage, use verifier.ManifoldKey
dummyKey := "PY7wu3q3-adYr9-0ES6CMRixup9OjO5iL7EFDFpolhk"
verifier, _ := NewVerifier(dummyKey)

err := verifier.Verify(req, body)
if err != nil {
	fmt.Println("Signature is not valid:", err)
} else {
	fmt.Println("Signature is ok!")
}
Output:

Signature is ok!

func (*Verifier) Wrap

func (v *Verifier) Wrap(handler http.Handler) http.Handler

Wrap wraps the provided Handler, returning a new Handler that will verify the request before passing it through to the Handler. If the request is invalid, Wrap will respond appropriately through the RequestWriter

func (*Verifier) WrapFunc

func (v *Verifier) WrapFunc(handler http.HandlerFunc) http.Handler

WrapFunc is the HandlerFunc version of Wrap.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL