This library implements http request signature generation and verification based on the RFC draft specification: https://tools.ietf.org/html/draft-cavage-http-signatures-06.
The library strives be compatible with the popular python library of the same name: https://github.com/ahknight/httpsig
go get gopkg.in/spacemonkey/spacemonkeygo/httpsig.v1
Signing requests is done by constructing a new Signer. The key id, key, algorithm, and what headers to sign is required.
For example to construct a signer with key id "foo", using an RSA private key, for the rsa-sha256 algorithm, with the default header set, you can do:
var key *rsa.PrivateKey = ...
signer := httpsig.NewSigner("foo", key, httpsig.RSASHA256, nil)
There are helper functions for specific algorithms that are less verbose and
provide more type safety (the key paramater need not be of type interface{}
because the type required for the algorithm is known).
var key *rsa.PrivateKey = ...
signer := httpsig.NewRSASHA256Signer("foo", key, nil)
By default, if no headers are passed to NewSigner
(or the helpers), the
(request-target)
pseudo-header and Date
header are signed.
To sign requests, call the Sign()
method. The method signs the request and
adds an Authorization
header containing the signature parameters.
err = signer.Sign(req)
Verify requests is done by constructing a new Verifier. The verifier requires a KeyGetter implementation to look up keys based on keyId's retrieved from signature parameters.
var getter httpsig.KeyGetter = ....
verifier := httpsig.NewVerifier(getter)
A request can be verified by calling the Verify()
method:
err = verifier.Verify(req)
By default, the verifier only requires the Date
header to be included
in the signature. The RequireHeaders
field can be set to enforce stricter
requirements.
verifier.RequireHeaders = []string{"(request-target)", "host", "date"}
Note that RequiredHeaders is simply a requirement for which headers get included in the signature, and does not enforce header presence in requests. It is up to callers to validate header contents (or the lack thereof).
A simple in-memory store is provided by the library and can be constructed with
the NewMemoryKeyStore()
function. Keys can be added using the SetKey method:
keystore := NewMemoryKeyStore()
var rsa_key *rsa.PublicKey = ...
keystore.SetKey("foo", rsa_key)
var hmac_key []byte = ...
keystore.SetKey("foo", hmac_key)
A convenience function is provided that wraps an http.Handler
and verifies
incoming request signatures before passing them down to the wrapped handler.
If requires a verifier and optionally a realm (for constructing the
WWW-Authenticate
header).
var handler http.Handler = ...
var verifier *httpsig.Verifier = ...
wrapped := httpsig.RequireSignature(handler, verifier, "example.com")
If signature validation fails, a 401
is along with a WWW-Authenticate
with the Signature
challenge with an optional realm
and headers
parameters.
- rsa-sha1 (using PKCS1v15)
- rsa-sha256 (using PKCS1v15)
- hmac-sha256
Copyright (C) 2014 Space Monkey, Inc.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.