Skip to content

Commit 34930b2

Browse files
author
Michael Wilson
authored
Add support for hardware security module (HSM) signing. (#503)
1 parent f9e6716 commit 34930b2

7 files changed

+125
-66
lines changed

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ require (
1111
github.com/kr/pretty v0.3.1
1212
github.com/mattermost/xml-roundtrip-validator v0.1.0
1313
github.com/pkg/errors v0.9.1 // indirect
14-
github.com/russellhaering/goxmldsig v1.2.0
14+
github.com/russellhaering/goxmldsig v1.3.0
1515
github.com/stretchr/testify v1.8.1
1616
github.com/zenazn/goji v1.0.1
1717
golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE
3535
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
3636
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
3737
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
38-
github.com/russellhaering/goxmldsig v1.2.0 h1:Y6GTTc9Un5hCxSzVz4UIWQ/zuVwDvzJk80guqzwx6Vg=
39-
github.com/russellhaering/goxmldsig v1.2.0/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw=
38+
github.com/russellhaering/goxmldsig v1.3.0 h1:DllIWUgMy0cRUMfGiASiYEa35nsieyD3cigIwLonTPM=
39+
github.com/russellhaering/goxmldsig v1.3.0/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw=
4040
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
4141
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
4242
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=

identity_provider.go

+46-36
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ type AssertionMaker interface {
9696
// and password).
9797
type IdentityProvider struct {
9898
Key crypto.PrivateKey
99+
Signer crypto.Signer
99100
Logger logger.Interface
100101
Certificate *x509.Certificate
101102
Intermediates []*x509.Certificate
@@ -831,24 +832,8 @@ const canonicalizerPrefixList = ""
831832

832833
// MakeAssertionEl sets `AssertionEl` to a signed, possibly encrypted, version of `Assertion`.
833834
func (req *IdpAuthnRequest) MakeAssertionEl() error {
834-
keyPair := tls.Certificate{
835-
Certificate: [][]byte{req.IDP.Certificate.Raw},
836-
PrivateKey: req.IDP.Key,
837-
Leaf: req.IDP.Certificate,
838-
}
839-
for _, cert := range req.IDP.Intermediates {
840-
keyPair.Certificate = append(keyPair.Certificate, cert.Raw)
841-
}
842-
keyStore := dsig.TLSCertKeyStore(keyPair)
843-
844-
signatureMethod := req.IDP.SignatureMethod
845-
if signatureMethod == "" {
846-
signatureMethod = dsig.RSASHA1SignatureMethod
847-
}
848-
849-
signingContext := dsig.NewDefaultSigningContext(keyStore)
850-
signingContext.Canonicalizer = dsig.MakeC14N10ExclusiveCanonicalizerWithPrefixList(canonicalizerPrefixList)
851-
if err := signingContext.SetSignatureMethod(signatureMethod); err != nil {
835+
signingContext, err := req.signingContext()
836+
if err != nil {
852837
return err
853838
}
854839

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

10501035
// Sign the response element (we've already signed the Assertion element)
10511036
{
1052-
keyPair := tls.Certificate{
1053-
Certificate: [][]byte{req.IDP.Certificate.Raw},
1054-
PrivateKey: req.IDP.Key,
1055-
Leaf: req.IDP.Certificate,
1056-
}
1057-
for _, cert := range req.IDP.Intermediates {
1058-
keyPair.Certificate = append(keyPair.Certificate, cert.Raw)
1059-
}
1060-
keyStore := dsig.TLSCertKeyStore(keyPair)
1061-
1062-
signatureMethod := req.IDP.SignatureMethod
1063-
if signatureMethod == "" {
1064-
signatureMethod = dsig.RSASHA1SignatureMethod
1065-
}
1066-
1067-
signingContext := dsig.NewDefaultSigningContext(keyStore)
1068-
signingContext.Canonicalizer = dsig.MakeC14N10ExclusiveCanonicalizerWithPrefixList(canonicalizerPrefixList)
1069-
if err := signingContext.SetSignatureMethod(signatureMethod); err != nil {
1037+
signingContext, err := req.signingContext()
1038+
if err != nil {
10701039
return err
10711040
}
10721041

@@ -1084,3 +1053,44 @@ func (req *IdpAuthnRequest) MakeResponse() error {
10841053
req.ResponseEl = responseEl
10851054
return nil
10861055
}
1056+
1057+
// signingContext will create a signing context for the request.
1058+
func (req *IdpAuthnRequest) signingContext() (*dsig.SigningContext, error) {
1059+
// Create a cert chain based off of the IDP cert and its intermediates.
1060+
certificates := [][]byte{req.IDP.Certificate.Raw}
1061+
for _, cert := range req.IDP.Intermediates {
1062+
certificates = append(certificates, cert.Raw)
1063+
}
1064+
1065+
var signingContext *dsig.SigningContext
1066+
var err error
1067+
// If signer is set, use it instead of the private key.
1068+
if req.IDP.Signer != nil {
1069+
signingContext, err = dsig.NewSigningContext(req.IDP.Signer, certificates)
1070+
if err != nil {
1071+
return nil, err
1072+
}
1073+
} else {
1074+
keyPair := tls.Certificate{
1075+
Certificate: certificates,
1076+
PrivateKey: req.IDP.Key,
1077+
Leaf: req.IDP.Certificate,
1078+
}
1079+
keyStore := dsig.TLSCertKeyStore(keyPair)
1080+
1081+
signingContext = dsig.NewDefaultSigningContext(keyStore)
1082+
}
1083+
1084+
// Default to using SHA1 if the signature method isn't set.
1085+
signatureMethod := req.IDP.SignatureMethod
1086+
if signatureMethod == "" {
1087+
signatureMethod = dsig.RSASHA1SignatureMethod
1088+
}
1089+
1090+
signingContext.Canonicalizer = dsig.MakeC14N10ExclusiveCanonicalizerWithPrefixList(canonicalizerPrefixList)
1091+
if err := signingContext.SetSignatureMethod(signatureMethod); err != nil {
1092+
return nil, err
1093+
}
1094+
1095+
return signingContext, nil
1096+
}

identity_provider_go116_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import (
1818
)
1919

2020
func TestIDPHTTPCanHandleSSORequest(t *testing.T) {
21-
test := NewIdentifyProviderTest(t)
21+
test := NewIdentityProviderTest(t, applyKey)
2222
w := httptest.NewRecorder()
2323

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

identity_provider_go117_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import (
1818
)
1919

2020
func TestIDPHTTPCanHandleSSORequest(t *testing.T) {
21-
test := NewIdentifyProviderTest(t)
21+
test := NewIdentityProviderTest(t, applyKey)
2222
w := httptest.NewRecorder()
2323

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

0 commit comments

Comments
 (0)