I have the following SAML request that I want to digitally sign:
<samlp:AuthnRequest Version="2.0" ID="_9FE393FB-1C9C-4EDD-86A5-1AE9F2192A60" IssueInstant="2014-10-22T11:22:56.676Z" Destination="https://idp.ssocircle.com:443/sso/SSOPOST/metaAlias/ssocircle" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<saml:Issuer>http://app.localhost</saml:Issuer>
<samlp:NameIDPolicy AllowCreate="true" />
</samlp:AuthnRequest>
I use the following coffeescript code which relies on the nodejs xmlbuilder and xmlcrypto modules:
request = @xmlbuilder.create
'samlp:AuthnRequest':
'@xmlns:samlp':'urn:oasis:names:tc:SAML:2.0:protocol'
'@xmlns:saml': 'urn:oasis:names:tc:SAML:2.0:assertion'
'@Version': '2.0'
'@ID': requestId
'@IssueInstant': (new Date()).toISOString()
'@Destination': idpUrl
'saml:Issuer': '@@spEntityId'
,null
,headless: true
request.comment 'insert-signature-here'
request.element 'samlp:NameIDPolicy':
'@AllowCreate': 'true'
saml = request.end()
@fs.readFile "certs/my-cert.pem", (err, certificate)=>
return next @errorService.readFileError certFilePath, err if err?
signer = new @xmlcrypto.SignedXml()
signer.signingKey = certificate
signer.addReference "//*[local-name(.)='AuthnRequest']", ['http://www.w3.org/2000/09/xmldsig#enveloped-signature']
signer.keyInfoProvider = new =>
getKeyInfo: (key)=>
public_key = /-----BEGIN CERTIFICATE-----([^-]*)-----END CERTIFICATE-----/g.exec(key)[1].replace /[\r\n|\n]/g, ''
"<X509Data><X509Certificate>#{public_key}</X509Certificate></X509Data>"
signer.computeSignature saml
signature = signer.getSignatureXml()
signed = saml.replace '<!-- insert-signature-here -->', signature
console.log signed
Which generates the following digitally signed SAML request:
<samlp:AuthnRequest Version="2.0" ID="_5FEB2162-F4D0-4900-BC28-F2940188E45B" IssueInstant="2014-10-28T13:07:14.007Z" Destination="https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<saml:Issuer>http://app.localhost9de83841</saml:Issuer>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<Reference URI="#_5FEB2162-F4D0-4900-BC28-F2940188E45B">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>47MSlH9IpJf8vs37T3DnhZMZ7mo=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>T0Uw...KZkm00A==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIDg...OgMMxZ</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
<samlp:NameIDPolicy AllowCreate="true" />
</samlp:AuthnRequest>
This appears to be valid.
However when I test this with SSOCircle and TestShib they both report that the digest value does not match.
The certificate I am using is a self-signed certificate (pem) with an unencrypted private key.
I have double checked to categorically ensure that the public key supplied in the sp-metadata was taken from the same pem file used to digitally sign the SAML.
Does the private key need to be encrypted?
If not then can you suggest why the signature check should fail?
Thanks.