Add test condition for auth-scheme, fix bug in HMAC
このコミットが含まれているのは:
コミット
2555707168
|
@ -206,6 +206,7 @@ func newSigner(algo Algorithm, headers []string, scheme SignatureScheme) (Signer
|
||||||
m: m,
|
m: m,
|
||||||
headers: headers,
|
headers: headers,
|
||||||
targetHeader: scheme,
|
targetHeader: scheme,
|
||||||
|
prefix: scheme.authScheme(),
|
||||||
}
|
}
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
261
httpsig_test.go
261
httpsig_test.go
|
@ -12,10 +12,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
testUrl = "foo.net/bar/baz?q=test&r=ok"
|
testUrl = "foo.net/bar/baz?q=test&r=ok"
|
||||||
testDate = "Tue, 07 Jun 2014 20:51:35 GMT"
|
testUrlPath = "bar/baz"
|
||||||
testDigest = "SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE="
|
testDate = "Tue, 07 Jun 2014 20:51:35 GMT"
|
||||||
testMethod = "GET"
|
testDigest = "SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE="
|
||||||
|
testMethod = "GET"
|
||||||
)
|
)
|
||||||
|
|
||||||
type httpsigTest struct {
|
type httpsigTest struct {
|
||||||
|
@ -28,6 +29,7 @@ type httpsigTest struct {
|
||||||
pubKeyId string
|
pubKeyId string
|
||||||
expectedAlgorithm Algorithm
|
expectedAlgorithm Algorithm
|
||||||
expectErrorSigningResponse bool
|
expectErrorSigningResponse bool
|
||||||
|
expectRequestPath bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -126,6 +128,7 @@ func init() {
|
||||||
pubKeyId: "pubKeyId",
|
pubKeyId: "pubKeyId",
|
||||||
expectedAlgorithm: RSA_SHA512,
|
expectedAlgorithm: RSA_SHA512,
|
||||||
expectErrorSigningResponse: true,
|
expectErrorSigningResponse: true,
|
||||||
|
expectRequestPath: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,42 +148,59 @@ func toHeaderSignatureParameters(k string, vals []string) string {
|
||||||
return fmt.Sprintf("%s%s%s%s%s", k, parameterKVSeparater, parameterValueDelimiter, v, parameterValueDelimiter)
|
return fmt.Sprintf("%s%s%s%s%s", k, parameterKVSeparater, parameterValueDelimiter, v, parameterValueDelimiter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewSigner(t *testing.T) {
|
func TestSignerRequest(t *testing.T) {
|
||||||
for _, test := range tests {
|
testFn := func(t *testing.T, test httpsigTest) {
|
||||||
s, a, err := NewSigner(test.prefs, test.headers, test.scheme)
|
s, a, err := NewSigner(test.prefs, test.headers, test.scheme)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%q: %s", test.name, err)
|
t.Fatalf("%s", err)
|
||||||
}
|
}
|
||||||
if a != test.expectedAlgorithm {
|
if a != test.expectedAlgorithm {
|
||||||
t.Fatalf("%q: got %s, want %s", test.name, a, test.expectedAlgorithm)
|
t.Fatalf("got %s, want %s", a, test.expectedAlgorithm)
|
||||||
}
|
}
|
||||||
// Test request signing
|
// Test request signing
|
||||||
req, err := http.NewRequest(testMethod, testUrl, nil)
|
req, err := http.NewRequest(testMethod, testUrl, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%q: %s", test.name, err)
|
t.Fatalf("%s", err)
|
||||||
}
|
}
|
||||||
req.Header.Set("Date", testDate)
|
req.Header.Set("Date", testDate)
|
||||||
req.Header.Set("Digest", testDigest)
|
req.Header.Set("Digest", testDigest)
|
||||||
err = s.SignRequest(test.privKey, test.pubKeyId, req)
|
err = s.SignRequest(test.privKey, test.pubKeyId, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%q: %s", test.name, err)
|
t.Fatalf("%s", err)
|
||||||
}
|
}
|
||||||
vals, ok := req.Header[string(test.scheme)]
|
vals, ok := req.Header[string(test.scheme)]
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("%q: not in header %s", test.name, test.scheme)
|
t.Fatalf("not in header %s", test.scheme)
|
||||||
}
|
}
|
||||||
if len(vals) != 1 {
|
if len(vals) != 1 {
|
||||||
t.Fatalf("%q: too many in header %s: %d", test.name, test.scheme, len(vals))
|
t.Fatalf("too many in header %s: %d", test.scheme, len(vals))
|
||||||
}
|
}
|
||||||
if p := toSignatureParameter(keyIdParameter, test.pubKeyId); !strings.Contains(vals[0], p) {
|
if p := toSignatureParameter(keyIdParameter, test.pubKeyId); !strings.Contains(vals[0], p) {
|
||||||
t.Fatalf("%q: %s\ndoes not contain\n%s", test.name, vals[0], p)
|
t.Fatalf("%s\ndoes not contain\n%s", vals[0], p)
|
||||||
} else if p := toSignatureParameter(algorithmParameter, string(test.expectedAlgorithm)); !strings.Contains(vals[0], p) {
|
} else if p := toSignatureParameter(algorithmParameter, string(test.expectedAlgorithm)); !strings.Contains(vals[0], p) {
|
||||||
t.Fatalf("%q: %s\ndoes not contain\n%s", test.name, vals[0], p)
|
t.Fatalf("%s\ndoes not contain\n%s", vals[0], p)
|
||||||
} else if p := toHeaderSignatureParameters(headersParameter, test.headers); !strings.Contains(vals[0], p) {
|
} else if p := toHeaderSignatureParameters(headersParameter, test.headers); !strings.Contains(vals[0], p) {
|
||||||
t.Fatalf("%q: %s\ndoes not contain\n%s", test.name, vals[0], p)
|
t.Fatalf("%s\ndoes not contain\n%s", vals[0], p)
|
||||||
} else if !strings.Contains(vals[0], signatureParameter) {
|
} else if !strings.Contains(vals[0], signatureParameter) {
|
||||||
t.Fatalf("%q: %s\ndoes not contain\n%s", test.name, vals[0], signatureParameter)
|
t.Fatalf("%s\ndoes not contain\n%s", vals[0], signatureParameter)
|
||||||
}
|
}
|
||||||
|
// For schemes with an authScheme, enforce its is present and at the beginning
|
||||||
|
if len(test.scheme.authScheme()) > 0 {
|
||||||
|
if !strings.HasPrefix(vals[0], test.scheme.authScheme()) {
|
||||||
|
t.Fatalf("%s\ndoes not start with\n%s", vals[0], test.scheme.authScheme())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
testFn(t, test)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSignerResponse(t *testing.T) {
|
||||||
|
testFn := func(t *testing.T, test httpsigTest) {
|
||||||
|
s, _, err := NewSigner(test.prefs, test.headers, test.scheme)
|
||||||
// Test response signing
|
// Test response signing
|
||||||
resp := httptest.NewRecorder()
|
resp := httptest.NewRecorder()
|
||||||
resp.HeaderMap.Set("Date", testDate)
|
resp.HeaderMap.Set("Date", testDate)
|
||||||
|
@ -189,27 +209,38 @@ func TestNewSigner(t *testing.T) {
|
||||||
if test.expectErrorSigningResponse {
|
if test.expectErrorSigningResponse {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Skip rest of testing
|
// Skip rest of testing
|
||||||
continue
|
return
|
||||||
} else {
|
} else {
|
||||||
t.Fatalf("%q: expected error, got nil", test.name)
|
t.Fatalf("expected error, got nil")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vals, ok = resp.HeaderMap[string(test.scheme)]
|
vals, ok := resp.HeaderMap[string(test.scheme)]
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("%q: not in header %s", test.name, test.scheme)
|
t.Fatalf("not in header %s", test.scheme)
|
||||||
}
|
}
|
||||||
if len(vals) != 1 {
|
if len(vals) != 1 {
|
||||||
t.Fatalf("%q: too many in header %s: %d", test.name, test.scheme, len(vals))
|
t.Fatalf("too many in header %s: %d", test.scheme, len(vals))
|
||||||
}
|
}
|
||||||
if p := toSignatureParameter(keyIdParameter, test.pubKeyId); !strings.Contains(vals[0], p) {
|
if p := toSignatureParameter(keyIdParameter, test.pubKeyId); !strings.Contains(vals[0], p) {
|
||||||
t.Fatalf("%q: %s\ndoes not contain\n%s", test.name, vals[0], p)
|
t.Fatalf("%s\ndoes not contain\n%s", vals[0], p)
|
||||||
} else if p := toSignatureParameter(algorithmParameter, string(test.expectedAlgorithm)); !strings.Contains(vals[0], p) {
|
} else if p := toSignatureParameter(algorithmParameter, string(test.expectedAlgorithm)); !strings.Contains(vals[0], p) {
|
||||||
t.Fatalf("%q: %s\ndoes not contain\n%s", test.name, vals[0], p)
|
t.Fatalf("%s\ndoes not contain\n%s", vals[0], p)
|
||||||
} else if p := toHeaderSignatureParameters(headersParameter, test.headers); !strings.Contains(vals[0], p) {
|
} else if p := toHeaderSignatureParameters(headersParameter, test.headers); !strings.Contains(vals[0], p) {
|
||||||
t.Fatalf("%q: %s\ndoes not contain\n%s", test.name, vals[0], p)
|
t.Fatalf("%s\ndoes not contain\n%s", vals[0], p)
|
||||||
} else if !strings.Contains(vals[0], signatureParameter) {
|
} else if !strings.Contains(vals[0], signatureParameter) {
|
||||||
t.Fatalf("%q: %s\ndoes not contain\n%s", test.name, vals[0], signatureParameter)
|
t.Fatalf("%s\ndoes not contain\n%s", vals[0], signatureParameter)
|
||||||
}
|
}
|
||||||
|
// For schemes with an authScheme, enforce its is present and at the beginning
|
||||||
|
if len(test.scheme.authScheme()) > 0 {
|
||||||
|
if !strings.HasPrefix(vals[0], test.scheme.authScheme()) {
|
||||||
|
t.Fatalf("%s\ndoes not start with\n%s", vals[0], test.scheme.authScheme())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
testFn(t, test)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,22 +265,25 @@ func TestNewSignerRequestMissingHeaders(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range failingTests {
|
for _, test := range failingTests {
|
||||||
s, a, err := NewSigner(test.prefs, test.headers, test.scheme)
|
t.Run(test.name, func(t *testing.T) {
|
||||||
if err != nil {
|
test := test
|
||||||
t.Fatalf("%q: %s", test.name, err)
|
s, a, err := NewSigner(test.prefs, test.headers, test.scheme)
|
||||||
}
|
if err != nil {
|
||||||
if a != test.expectedAlgorithm {
|
t.Fatalf("%s", err)
|
||||||
t.Fatalf("%q: got %s, want %s", test.name, a, test.expectedAlgorithm)
|
}
|
||||||
}
|
if a != test.expectedAlgorithm {
|
||||||
req, err := http.NewRequest(testMethod, testUrl, nil)
|
t.Fatalf("got %s, want %s", a, test.expectedAlgorithm)
|
||||||
if err != nil {
|
}
|
||||||
t.Fatalf("%q: %s", test.name, err)
|
req, err := http.NewRequest(testMethod, testUrl, nil)
|
||||||
}
|
if err != nil {
|
||||||
req.Header.Set("Date", testDate)
|
t.Fatalf("%s", err)
|
||||||
err = s.SignRequest(test.privKey, test.pubKeyId, req)
|
}
|
||||||
if err == nil {
|
req.Header.Set("Date", testDate)
|
||||||
t.Fatalf("%q: expect error but got nil", test.name)
|
err = s.SignRequest(test.privKey, test.pubKeyId, req)
|
||||||
}
|
if err == nil {
|
||||||
|
t.Fatalf("expect error but got nil")
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,83 +309,92 @@ func TestNewSignerResponseMissingHeaders(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range failingTests {
|
for _, test := range failingTests {
|
||||||
s, a, err := NewSigner(test.prefs, test.headers, test.scheme)
|
t.Run(test.name, func(t *testing.T) {
|
||||||
if err != nil {
|
test := test
|
||||||
t.Fatalf("%q: %s", test.name, err)
|
s, a, err := NewSigner(test.prefs, test.headers, test.scheme)
|
||||||
}
|
if err != nil {
|
||||||
if a != test.expectedAlgorithm {
|
t.Fatalf("%s", err)
|
||||||
t.Fatalf("%q: got %s, want %s", test.name, a, test.expectedAlgorithm)
|
}
|
||||||
}
|
if a != test.expectedAlgorithm {
|
||||||
resp := httptest.NewRecorder()
|
t.Fatalf("got %s, want %s", a, test.expectedAlgorithm)
|
||||||
resp.HeaderMap.Set("Date", testDate)
|
}
|
||||||
resp.HeaderMap.Set("Digest", testDigest)
|
resp := httptest.NewRecorder()
|
||||||
err = s.SignResponse(test.privKey, test.pubKeyId, resp)
|
resp.HeaderMap.Set("Date", testDate)
|
||||||
if err != nil {
|
resp.HeaderMap.Set("Digest", testDigest)
|
||||||
t.Fatalf("%q: expected error, got nil", test.name)
|
err = s.SignResponse(test.privKey, test.pubKeyId, resp)
|
||||||
}
|
if err != nil {
|
||||||
|
t.Fatalf("expected error, got nil")
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewVerifier(t *testing.T) {
|
func TestNewVerifier(t *testing.T) {
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
// Prepare
|
t.Run(test.name, func(t *testing.T) {
|
||||||
req, err := http.NewRequest(testMethod, testUrl, nil)
|
test := test
|
||||||
if err != nil {
|
// Prepare
|
||||||
t.Fatalf("%q: %s", test.name, err)
|
req, err := http.NewRequest(testMethod, testUrl, nil)
|
||||||
}
|
if err != nil {
|
||||||
req.Header.Set("Date", testDate)
|
t.Fatalf("%s", err)
|
||||||
req.Header.Set("Digest", testDigest)
|
}
|
||||||
s, _, err := NewSigner(test.prefs, test.headers, test.scheme)
|
req.Header.Set("Date", testDate)
|
||||||
if err != nil {
|
req.Header.Set("Digest", testDigest)
|
||||||
t.Fatalf("%q: %s", test.name, err)
|
s, _, err := NewSigner(test.prefs, test.headers, test.scheme)
|
||||||
}
|
if err != nil {
|
||||||
err = s.SignRequest(test.privKey, test.pubKeyId, req)
|
t.Fatalf("%s", err)
|
||||||
if err != nil {
|
}
|
||||||
t.Fatalf("%q: %s", test.name, err)
|
err = s.SignRequest(test.privKey, test.pubKeyId, req)
|
||||||
}
|
if err != nil {
|
||||||
// Test verification
|
t.Fatalf("%s", err)
|
||||||
v, err := NewVerifier(req)
|
}
|
||||||
if err != nil {
|
// Test verification
|
||||||
t.Fatalf("%q: %s", test.name, err)
|
v, err := NewVerifier(req)
|
||||||
}
|
if err != nil {
|
||||||
if v.KeyId() != test.pubKeyId {
|
t.Fatalf("%s", err)
|
||||||
t.Fatalf("%q: got %s, want %s", test.name, v.KeyId(), test.pubKeyId)
|
}
|
||||||
}
|
if v.KeyId() != test.pubKeyId {
|
||||||
err = v.Verify(test.pubKey, test.expectedAlgorithm)
|
t.Fatalf("got %s, want %s", v.KeyId(), test.pubKeyId)
|
||||||
if err != nil {
|
}
|
||||||
t.Fatalf("%q: %s", test.name, err)
|
err = v.Verify(test.pubKey, test.expectedAlgorithm)
|
||||||
}
|
if err != nil {
|
||||||
|
t.Fatalf("%s", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewResponseVerifier(t *testing.T) {
|
func TestNewResponseVerifier(t *testing.T) {
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
if test.expectErrorSigningResponse {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
continue
|
test := test
|
||||||
}
|
if test.expectErrorSigningResponse {
|
||||||
// Prepare
|
return
|
||||||
resp := httptest.NewRecorder()
|
}
|
||||||
resp.HeaderMap.Set("Date", testDate)
|
// Prepare
|
||||||
resp.HeaderMap.Set("Digest", testDigest)
|
resp := httptest.NewRecorder()
|
||||||
s, _, err := NewSigner(test.prefs, test.headers, test.scheme)
|
resp.HeaderMap.Set("Date", testDate)
|
||||||
if err != nil {
|
resp.HeaderMap.Set("Digest", testDigest)
|
||||||
t.Fatalf("%q: %s", test.name, err)
|
s, _, err := NewSigner(test.prefs, test.headers, test.scheme)
|
||||||
}
|
if err != nil {
|
||||||
err = s.SignResponse(test.privKey, test.pubKeyId, resp)
|
t.Fatalf("%s", err)
|
||||||
if err != nil {
|
}
|
||||||
t.Fatalf("%q: %s", test.name, err)
|
err = s.SignResponse(test.privKey, test.pubKeyId, resp)
|
||||||
}
|
if err != nil {
|
||||||
// Test verification
|
t.Fatalf("%s", err)
|
||||||
v, err := NewResponseVerifier(resp.Result())
|
}
|
||||||
if err != nil {
|
// Test verification
|
||||||
t.Fatalf("%q: %s", test.name, err)
|
v, err := NewResponseVerifier(resp.Result())
|
||||||
}
|
if err != nil {
|
||||||
if v.KeyId() != test.pubKeyId {
|
t.Fatalf("%s", err)
|
||||||
t.Fatalf("%q: got %s, want %s", test.name, v.KeyId(), test.pubKeyId)
|
}
|
||||||
}
|
if v.KeyId() != test.pubKeyId {
|
||||||
err = v.Verify(test.pubKey, test.expectedAlgorithm)
|
t.Fatalf("got %s, want %s", v.KeyId(), test.pubKeyId)
|
||||||
if err != nil {
|
}
|
||||||
t.Fatalf("%q: %s", test.name, err)
|
err = v.Verify(test.pubKey, test.expectedAlgorithm)
|
||||||
}
|
if err != nil {
|
||||||
|
t.Fatalf("%s", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
読み込み中…
新しいイシューから参照