Skip to content

Commit

Permalink
Add support for hardware security module (HSM) signing. (#503)
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Wilson authored Apr 20, 2023
1 parent f9e6716 commit 34930b2
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 66 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ require (
github.com/kr/pretty v0.3.1
github.com/mattermost/xml-roundtrip-validator v0.1.0
github.com/pkg/errors v0.9.1 // indirect
github.com/russellhaering/goxmldsig v1.2.0
github.com/russellhaering/goxmldsig v1.3.0
github.com/stretchr/testify v1.8.1
github.com/zenazn/goji v1.0.1
golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/russellhaering/goxmldsig v1.2.0 h1:Y6GTTc9Un5hCxSzVz4UIWQ/zuVwDvzJk80guqzwx6Vg=
github.com/russellhaering/goxmldsig v1.2.0/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw=
github.com/russellhaering/goxmldsig v1.3.0 h1:DllIWUgMy0cRUMfGiASiYEa35nsieyD3cigIwLonTPM=
github.com/russellhaering/goxmldsig v1.3.0/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
Expand Down
82 changes: 46 additions & 36 deletions identity_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ type AssertionMaker interface {
// and password).
type IdentityProvider struct {
Key crypto.PrivateKey
Signer crypto.Signer
Logger logger.Interface
Certificate *x509.Certificate
Intermediates []*x509.Certificate
Expand Down Expand Up @@ -831,24 +832,8 @@ const canonicalizerPrefixList = ""

// MakeAssertionEl sets `AssertionEl` to a signed, possibly encrypted, version of `Assertion`.
func (req *IdpAuthnRequest) MakeAssertionEl() error {
keyPair := tls.Certificate{
Certificate: [][]byte{req.IDP.Certificate.Raw},
PrivateKey: req.IDP.Key,
Leaf: req.IDP.Certificate,
}
for _, cert := range req.IDP.Intermediates {
keyPair.Certificate = append(keyPair.Certificate, cert.Raw)
}
keyStore := dsig.TLSCertKeyStore(keyPair)

signatureMethod := req.IDP.SignatureMethod
if signatureMethod == "" {
signatureMethod = dsig.RSASHA1SignatureMethod
}

signingContext := dsig.NewDefaultSigningContext(keyStore)
signingContext.Canonicalizer = dsig.MakeC14N10ExclusiveCanonicalizerWithPrefixList(canonicalizerPrefixList)
if err := signingContext.SetSignatureMethod(signatureMethod); err != nil {
signingContext, err := req.signingContext()
if err != nil {
return err
}

Expand Down Expand Up @@ -1049,24 +1034,8 @@ func (req *IdpAuthnRequest) MakeResponse() error {

// Sign the response element (we've already signed the Assertion element)
{
keyPair := tls.Certificate{
Certificate: [][]byte{req.IDP.Certificate.Raw},
PrivateKey: req.IDP.Key,
Leaf: req.IDP.Certificate,
}
for _, cert := range req.IDP.Intermediates {
keyPair.Certificate = append(keyPair.Certificate, cert.Raw)
}
keyStore := dsig.TLSCertKeyStore(keyPair)

signatureMethod := req.IDP.SignatureMethod
if signatureMethod == "" {
signatureMethod = dsig.RSASHA1SignatureMethod
}

signingContext := dsig.NewDefaultSigningContext(keyStore)
signingContext.Canonicalizer = dsig.MakeC14N10ExclusiveCanonicalizerWithPrefixList(canonicalizerPrefixList)
if err := signingContext.SetSignatureMethod(signatureMethod); err != nil {
signingContext, err := req.signingContext()
if err != nil {
return err
}

Expand All @@ -1084,3 +1053,44 @@ func (req *IdpAuthnRequest) MakeResponse() error {
req.ResponseEl = responseEl
return nil
}

// signingContext will create a signing context for the request.
func (req *IdpAuthnRequest) signingContext() (*dsig.SigningContext, error) {
// Create a cert chain based off of the IDP cert and its intermediates.
certificates := [][]byte{req.IDP.Certificate.Raw}
for _, cert := range req.IDP.Intermediates {
certificates = append(certificates, cert.Raw)
}

var signingContext *dsig.SigningContext
var err error
// If signer is set, use it instead of the private key.
if req.IDP.Signer != nil {
signingContext, err = dsig.NewSigningContext(req.IDP.Signer, certificates)
if err != nil {
return nil, err
}
} else {
keyPair := tls.Certificate{
Certificate: certificates,
PrivateKey: req.IDP.Key,
Leaf: req.IDP.Certificate,
}
keyStore := dsig.TLSCertKeyStore(keyPair)

signingContext = dsig.NewDefaultSigningContext(keyStore)
}

// Default to using SHA1 if the signature method isn't set.
signatureMethod := req.IDP.SignatureMethod
if signatureMethod == "" {
signatureMethod = dsig.RSASHA1SignatureMethod
}

signingContext.Canonicalizer = dsig.MakeC14N10ExclusiveCanonicalizerWithPrefixList(canonicalizerPrefixList)
if err := signingContext.SetSignatureMethod(signatureMethod); err != nil {
return nil, err
}

return signingContext, nil
}
2 changes: 1 addition & 1 deletion identity_provider_go116_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
)

func TestIDPHTTPCanHandleSSORequest(t *testing.T) {
test := NewIdentifyProviderTest(t)
test := NewIdentityProviderTest(t, applyKey)
w := httptest.NewRecorder()

const validRequest = `lJJBayoxFIX%2FypC9JhnU5wszAz7lgWCLaNtFd5fMbQ1MkmnunVb%2FfUfbUqEgdhs%2BTr5zkmLW8S5s8KVD4mzvm0Cl6FIwEciRCeCRDFuznd2sTD5Upk2Ro42NyGZEmNjFMI%2BBOo9pi%2BnVWbzfrEqxY27JSEntEPfg2waHNnpJ4JtcgiWRLfoLXYBjwDfu6p%2B8JIoiWy5K4eqBUipXIzVRUwXKKtRK53qkJ3qqQVuNPUjU4TIQQ%2BBS5EqPBzofKH2ntBn%2FMervo8jWnyX%2BuVC78FwKkT1gopNKX1JUxSklXTMIfM0gsv8xeeDL%2BPGk7%2FF0Qg0GdnwQ1cW5PDLUwFDID6uquO1Dlot1bJw9%2FPLRmia%2BzRMCYyk4dSiq6205QSDXOxfy3KAq5Pkvqt4DAAD%2F%2Fw%3D%3D`
Expand Down
2 changes: 1 addition & 1 deletion identity_provider_go117_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
)

func TestIDPHTTPCanHandleSSORequest(t *testing.T) {
test := NewIdentifyProviderTest(t)
test := NewIdentityProviderTest(t, applyKey)
w := httptest.NewRecorder()

const validRequest = `lJJBayoxFIX%2FypC9JhnU5wszAz7lgWCLaNtFd5fMbQ1MkmnunVb%2FfUfbUqEgdhs%2BTr5zkmLW8S5s8KVD4mzvm0Cl6FIwEciRCeCRDFuznd2sTD5Upk2Ro42NyGZEmNjFMI%2BBOo9pi%2BnVWbzfrEqxY27JSEntEPfg2waHNnpJ4JtcgiWRLfoLXYBjwDfu6p%2B8JIoiWy5K4eqBUipXIzVRUwXKKtRK53qkJ3qqQVuNPUjU4TIQQ%2BBS5EqPBzofKH2ntBn%2FMervo8jWnyX%2BuVC78FwKkT1gopNKX1JUxSklXTMIfM0gsv8xeeDL%2BPGk7%2FF0Qg0GdnwQ1cW5PDLUwFDID6uquO1Dlot1bJw9%2FPLRmia%2BzRMCYyk4dSiq6205QSDXOxfy3KAq5Pkvqt4DAAD%2F%2Fw%3D%3D`
Expand Down
Loading

0 comments on commit 34930b2

Please sign in to comment.