mirror of
https://github.com/fleetdm/fleet
synced 2026-05-22 08:28:52 +00:00
218 lines
6.8 KiB
Go
218 lines
6.8 KiB
Go
|
|
package httpsig_test
|
||
|
|
|
||
|
|
import (
|
||
|
|
"crypto"
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
"github.com/remitly-oss/httpsig-go"
|
||
|
|
"github.com/remitly-oss/httpsig-go/keyman"
|
||
|
|
"github.com/remitly-oss/httpsig-go/keyutil"
|
||
|
|
"github.com/remitly-oss/httpsig-go/sigtest"
|
||
|
|
)
|
||
|
|
|
||
|
|
// TestRoundTrip tests that the signing code can be verified by the verify code.
|
||
|
|
func TestRoundTrip(t *testing.T) {
|
||
|
|
|
||
|
|
testcases := []struct {
|
||
|
|
Name string
|
||
|
|
PrivateKey crypto.PrivateKey
|
||
|
|
MetaKeyID string
|
||
|
|
Secret []byte
|
||
|
|
SignProfile httpsig.SigningProfile
|
||
|
|
RequestFile string
|
||
|
|
Keys httpsig.KeyFetcher
|
||
|
|
Profile httpsig.VerifyProfile
|
||
|
|
ExpectedErrCodeVerify httpsig.ErrCode
|
||
|
|
}{
|
||
|
|
{
|
||
|
|
Name: "RSA-PSS",
|
||
|
|
PrivateKey: keyutil.MustReadPrivateKeyFile("testdata/test-key-rsa-pss.key"),
|
||
|
|
MetaKeyID: "test-key-rsa",
|
||
|
|
SignProfile: httpsig.SigningProfile{
|
||
|
|
Algorithm: httpsig.Algo_RSA_PSS_SHA512,
|
||
|
|
Fields: httpsig.DefaultRequiredFields,
|
||
|
|
Metadata: []httpsig.Metadata{httpsig.MetaCreated, httpsig.MetaKeyID},
|
||
|
|
Label: "tst-rsa-pss",
|
||
|
|
},
|
||
|
|
RequestFile: "rfc-test-request.txt",
|
||
|
|
Keys: keyman.NewKeyFetchInMemory(map[string]httpsig.KeySpec{
|
||
|
|
"test-key-rsa": {
|
||
|
|
KeyID: "test-key-rsa",
|
||
|
|
Algo: httpsig.Algo_RSA_PSS_SHA512,
|
||
|
|
PubKey: keyutil.MustReadPublicKeyFile("testdata/test-key-rsa-pss.pub"),
|
||
|
|
},
|
||
|
|
}),
|
||
|
|
Profile: createVerifyProfile("tst-rsa-pss"),
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Name: "RSA-v15",
|
||
|
|
PrivateKey: keyutil.MustReadPrivateKeyFile("testdata/key-rsa-v15.key"),
|
||
|
|
MetaKeyID: "test-key-rsa",
|
||
|
|
SignProfile: httpsig.SigningProfile{
|
||
|
|
Algorithm: httpsig.Algo_RSA_v1_5_sha256,
|
||
|
|
Fields: httpsig.DefaultRequiredFields,
|
||
|
|
Metadata: []httpsig.Metadata{httpsig.MetaCreated, httpsig.MetaKeyID},
|
||
|
|
Label: "tst-rsa-pss",
|
||
|
|
},
|
||
|
|
RequestFile: "rfc-test-request.txt",
|
||
|
|
Keys: keyman.NewKeyFetchInMemory(map[string]httpsig.KeySpec{
|
||
|
|
"test-key-rsa": {
|
||
|
|
KeyID: "test-key-rsa",
|
||
|
|
Algo: httpsig.Algo_RSA_v1_5_sha256,
|
||
|
|
PubKey: keyutil.MustReadPublicKeyFile("testdata/key-rsa-v15.pub"),
|
||
|
|
},
|
||
|
|
}),
|
||
|
|
Profile: createVerifyProfile("tst-rsa-pss"),
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Name: "HMAC_SHA256",
|
||
|
|
Secret: sigtest.MustReadFile("testdata/test-shared-secret"),
|
||
|
|
MetaKeyID: "test-key-shared",
|
||
|
|
SignProfile: httpsig.SigningProfile{
|
||
|
|
Algorithm: httpsig.Algo_HMAC_SHA256,
|
||
|
|
Fields: httpsig.DefaultRequiredFields,
|
||
|
|
Metadata: []httpsig.Metadata{httpsig.MetaCreated, httpsig.MetaKeyID},
|
||
|
|
},
|
||
|
|
RequestFile: "rfc-test-request.txt",
|
||
|
|
Keys: keyman.NewKeyFetchInMemory(map[string]httpsig.KeySpec{
|
||
|
|
"test-key-shared": {
|
||
|
|
KeyID: "test-key-shared",
|
||
|
|
Algo: httpsig.Algo_HMAC_SHA256,
|
||
|
|
Secret: sigtest.MustReadFile("testdata/test-shared-secret"),
|
||
|
|
},
|
||
|
|
}),
|
||
|
|
Profile: createVerifyProfile("sig1"),
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Name: "ECDSA-p265",
|
||
|
|
PrivateKey: keyutil.MustReadPrivateKeyFile("testdata/test-key-ecc-p256.key"),
|
||
|
|
MetaKeyID: "test-key-ecdsa",
|
||
|
|
SignProfile: httpsig.SigningProfile{
|
||
|
|
Algorithm: httpsig.Algo_ECDSA_P256_SHA256,
|
||
|
|
Fields: httpsig.DefaultRequiredFields,
|
||
|
|
Metadata: []httpsig.Metadata{httpsig.MetaCreated, httpsig.MetaKeyID},
|
||
|
|
Label: "tst-ecdsa",
|
||
|
|
},
|
||
|
|
RequestFile: "rfc-test-request.txt",
|
||
|
|
Keys: keyman.NewKeyFetchInMemory(map[string]httpsig.KeySpec{
|
||
|
|
"test-key-ecdsa": {
|
||
|
|
KeyID: "test-key-ecds",
|
||
|
|
Algo: httpsig.Algo_ECDSA_P256_SHA256,
|
||
|
|
PubKey: keyutil.MustReadPublicKeyFile("testdata/test-key-ecc-p256.pub"),
|
||
|
|
},
|
||
|
|
}),
|
||
|
|
Profile: createVerifyProfile("tst-ecdsa"),
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Name: "ECDSA-p384",
|
||
|
|
PrivateKey: keyutil.MustReadPrivateKeyFile("testdata/test-key-ecc-p384.key"),
|
||
|
|
MetaKeyID: "test-key-ecdsa",
|
||
|
|
SignProfile: httpsig.SigningProfile{
|
||
|
|
Algorithm: httpsig.Algo_ECDSA_P384_SHA384,
|
||
|
|
Fields: httpsig.DefaultRequiredFields,
|
||
|
|
Metadata: []httpsig.Metadata{httpsig.MetaCreated, httpsig.MetaKeyID},
|
||
|
|
Label: "tst-ecdsa",
|
||
|
|
},
|
||
|
|
RequestFile: "rfc-test-request.txt",
|
||
|
|
Keys: keyman.NewKeyFetchInMemory(map[string]httpsig.KeySpec{
|
||
|
|
"test-key-ecdsa": {
|
||
|
|
KeyID: "test-key-ecdsa",
|
||
|
|
Algo: httpsig.Algo_ECDSA_P384_SHA384,
|
||
|
|
PubKey: keyutil.MustReadPublicKeyFile("testdata/test-key-ecc-p384.pub"),
|
||
|
|
},
|
||
|
|
}),
|
||
|
|
Profile: createVerifyProfile("tst-ecdsa"),
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Name: "ED25519",
|
||
|
|
PrivateKey: keyutil.MustReadPrivateKeyFile("testdata/test-key-ed25519.key"),
|
||
|
|
MetaKeyID: "test-key-ed",
|
||
|
|
SignProfile: httpsig.SigningProfile{
|
||
|
|
Algorithm: httpsig.Algo_ED25519,
|
||
|
|
Fields: httpsig.DefaultRequiredFields,
|
||
|
|
Metadata: []httpsig.Metadata{httpsig.MetaCreated, httpsig.MetaKeyID},
|
||
|
|
Label: "tst-ed",
|
||
|
|
},
|
||
|
|
RequestFile: "rfc-test-request.txt",
|
||
|
|
Keys: keyman.NewKeyFetchInMemory(map[string]httpsig.KeySpec{
|
||
|
|
"test-key-ed": {
|
||
|
|
KeyID: "test-key-ed",
|
||
|
|
Algo: httpsig.Algo_ED25519,
|
||
|
|
PubKey: keyutil.MustReadPublicKeyFile("testdata/test-key-ed25519.pub"),
|
||
|
|
},
|
||
|
|
}),
|
||
|
|
Profile: createVerifyProfile("tst-ed"),
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Name: "BadDigest",
|
||
|
|
PrivateKey: keyutil.MustReadPrivateKeyFile("testdata/test-key-ed25519.key"),
|
||
|
|
MetaKeyID: "test-key-ed",
|
||
|
|
SignProfile: httpsig.SigningProfile{
|
||
|
|
|
||
|
|
Algorithm: httpsig.Algo_ED25519,
|
||
|
|
Fields: httpsig.DefaultRequiredFields,
|
||
|
|
Metadata: []httpsig.Metadata{httpsig.MetaCreated, httpsig.MetaKeyID},
|
||
|
|
Label: "tst-content-digest",
|
||
|
|
},
|
||
|
|
RequestFile: "request_bad_digest.txt",
|
||
|
|
Keys: keyman.NewKeyFetchInMemory(map[string]httpsig.KeySpec{
|
||
|
|
"test-key-ed": {
|
||
|
|
KeyID: "test-key-ed",
|
||
|
|
Algo: httpsig.Algo_ED25519,
|
||
|
|
PubKey: keyutil.MustReadPublicKeyFile("testdata/test-key-ed25519.pub"),
|
||
|
|
},
|
||
|
|
}),
|
||
|
|
Profile: createVerifyProfile("tst-content-digest"),
|
||
|
|
ExpectedErrCodeVerify: httpsig.ErrNoSigWrongDigest,
|
||
|
|
},
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, tc := range testcases {
|
||
|
|
t.Run(tc.Name, func(t *testing.T) {
|
||
|
|
var signer *httpsig.Signer
|
||
|
|
sk := httpsig.SigningKey{
|
||
|
|
Key: tc.PrivateKey,
|
||
|
|
Secret: tc.Secret,
|
||
|
|
MetaKeyID: tc.MetaKeyID,
|
||
|
|
}
|
||
|
|
|
||
|
|
signer, err := httpsig.NewSigner(tc.SignProfile, sk)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
|
||
|
|
req := sigtest.ReadRequest(t, tc.RequestFile)
|
||
|
|
err = signer.Sign(req)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("%#v", err)
|
||
|
|
}
|
||
|
|
t.Log(req.Header.Get("Signature-Input"))
|
||
|
|
t.Log(req.Header.Get("Signature"))
|
||
|
|
ver, err := httpsig.NewVerifier(tc.Keys, tc.Profile)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
vf, err := ver.Verify(req)
|
||
|
|
if err != nil {
|
||
|
|
if tc.ExpectedErrCodeVerify != "" {
|
||
|
|
if sigerr, ok := err.(*httpsig.SignatureError); ok {
|
||
|
|
sigtest.Diff(t, tc.ExpectedErrCodeVerify, sigerr.Code, "Wrong err code")
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
t.Fatalf("%#v", err)
|
||
|
|
}
|
||
|
|
} else if tc.ExpectedErrCodeVerify != "" {
|
||
|
|
t.Fatal("Expected error")
|
||
|
|
}
|
||
|
|
t.Logf("%+v\n", vf)
|
||
|
|
})
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func createVerifyProfile(label string) httpsig.VerifyProfile {
|
||
|
|
vp := httpsig.DefaultVerifyProfile
|
||
|
|
vp.SignatureLabel = label
|
||
|
|
return vp
|
||
|
|
}
|