Add "Signature" for "auth-scheme"

このコミットが含まれているのは:
Cory Slep 2019-02-28 22:38:53 +01:00
コミット c86d639563
3個のファイルの変更49行の追加13行の削除

ファイルの表示

@ -72,6 +72,25 @@ const (
Authorization SignatureScheme = "Authorization"
)
const (
// The HTTP Signatures specification uses the "Signature" auth-scheme
// for the Authorization header. This is coincidentally named, but not
// semantically the same, as the "Signature" HTTP header value.
signatureAuthScheme = "Signature"
)
// There are subtle differences to the values in the header. The Authorization
// header has an 'auth-scheme' value that must be prefixed to the rest of the
// key and values.
func (s SignatureScheme) authScheme() string {
switch s {
case Authorization:
return signatureAuthScheme
default:
return ""
}
}
// Signers will sign HTTP requests or responses based on the algorithms and
// headers selected at creation time.
//
@ -175,6 +194,7 @@ func newSigner(algo Algorithm, headers []string, scheme SignatureScheme) (Signer
s: s,
headers: headers,
targetHeader: scheme,
prefix: scheme.authScheme(),
}
return a, nil
}

ファイルの表示

@ -17,6 +17,7 @@ const (
algorithmParameter = "algorithm"
headersParameter = "headers"
signatureParameter = "signature"
prefixSeparater = " "
parameterKVSeparater = "="
parameterValueDelimiter = "\""
parameterSeparater = ","
@ -41,6 +42,7 @@ type macSigner struct {
m macer
headers []string
targetHeader SignatureScheme
prefix string
}
func (m *macSigner) SignRequest(pKey crypto.PrivateKey, pubKeyId string, r *http.Request) error {
@ -52,7 +54,7 @@ func (m *macSigner) SignRequest(pKey crypto.PrivateKey, pubKeyId string, r *http
if err != nil {
return err
}
setSignatureHeader(r.Header, string(m.targetHeader), pubKeyId, m.m.String(), enc, m.headers)
setSignatureHeader(r.Header, string(m.targetHeader), m.prefix, pubKeyId, m.m.String(), enc, m.headers)
return nil
}
@ -65,7 +67,7 @@ func (m *macSigner) SignResponse(pKey crypto.PrivateKey, pubKeyId string, r http
if err != nil {
return err
}
setSignatureHeader(r.Header(), string(m.targetHeader), pubKeyId, m.m.String(), enc, m.headers)
setSignatureHeader(r.Header(), string(m.targetHeader), m.prefix, pubKeyId, m.m.String(), enc, m.headers)
return nil
}
@ -96,6 +98,7 @@ type asymmSigner struct {
s signer
headers []string
targetHeader SignatureScheme
prefix string
}
func (a *asymmSigner) SignRequest(pKey crypto.PrivateKey, pubKeyId string, r *http.Request) error {
@ -107,7 +110,7 @@ func (a *asymmSigner) SignRequest(pKey crypto.PrivateKey, pubKeyId string, r *ht
if err != nil {
return err
}
setSignatureHeader(r.Header, string(a.targetHeader), pubKeyId, a.s.String(), enc, a.headers)
setSignatureHeader(r.Header, string(a.targetHeader), a.prefix, pubKeyId, a.s.String(), enc, a.headers)
return nil
}
@ -120,7 +123,7 @@ func (a *asymmSigner) SignResponse(pKey crypto.PrivateKey, pubKeyId string, r ht
if err != nil {
return err
}
setSignatureHeader(r.Header(), string(a.targetHeader), pubKeyId, a.s.String(), enc, a.headers)
setSignatureHeader(r.Header(), string(a.targetHeader), a.prefix, pubKeyId, a.s.String(), enc, a.headers)
return nil
}
@ -141,12 +144,16 @@ func (a *asymmSigner) signatureStringResponse(r http.ResponseWriter) (string, er
return signatureString(r.Header(), a.headers, requestTargetNotPermitted)
}
func setSignatureHeader(h http.Header, targetHeader, pubKeyId, algo, enc string, headers []string) {
func setSignatureHeader(h http.Header, targetHeader, prefix, pubKeyId, algo, enc string, headers []string) {
if len(headers) == 0 {
headers = defaultHeaders
}
var b bytes.Buffer
// KeyId
b.WriteString(prefix)
if len(prefix) > 0 {
b.WriteString(prefixSeparater)
}
b.WriteString(keyIdParameter)
b.WriteString(parameterKVSeparater)
b.WriteString(parameterValueDelimiter)

ファイルの表示

@ -19,11 +19,11 @@ type verifier struct {
}
func newVerifier(h http.Header, sigStringFn func(http.Header, []string) (string, error)) (*verifier, error) {
s, err := getSignatureScheme(h)
scheme, s, err := getSignatureScheme(h)
if err != nil {
return nil, err
}
kId, sig, headers, err := getSignatureComponents(s)
kId, sig, headers, err := getSignatureComponents(scheme, s)
if err != nil {
return nil, err
}
@ -90,7 +90,7 @@ func (v *verifier) asymmVerify(s signer, pKey crypto.PublicKey) error {
return nil
}
func getSignatureScheme(h http.Header) (string, error) {
func getSignatureScheme(h http.Header) (scheme SignatureScheme, val string, err error) {
s := h.Get(string(Signature))
sigHasAll := strings.Contains(s, keyIdParameter) ||
strings.Contains(s, headersParameter) ||
@ -100,17 +100,26 @@ func getSignatureScheme(h http.Header) (string, error) {
strings.Contains(a, headersParameter) ||
strings.Contains(a, signatureParameter)
if sigHasAll && authHasAll {
return "", fmt.Errorf("both %q and %q have signature parameters", Signature, Authorization)
err = fmt.Errorf("both %q and %q have signature parameters", Signature, Authorization)
return
} else if !sigHasAll && !authHasAll {
return "", fmt.Errorf("neither %q nor %q have signature parameters", Signature, Authorization)
err = fmt.Errorf("neither %q nor %q have signature parameters", Signature, Authorization)
return
} else if sigHasAll {
return s, nil
val = s
scheme = Signature
return
} else { // authHasAll
return a, nil
val = a
scheme = Authorization
return
}
}
func getSignatureComponents(s string) (kId, sig string, headers []string, err error) {
func getSignatureComponents(scheme SignatureScheme, s string) (kId, sig string, headers []string, err error) {
if as := scheme.authScheme(); len(as) > 0 {
s = strings.TrimPrefix(s, as+prefixSeparater)
}
params := strings.Split(s, parameterSeparater)
for _, p := range params {
kv := strings.SplitN(p, parameterKVSeparater, 2)