OpenSAML2 Problem with Signing an Assertion (does not verify)
Johannes Frey
weblinux.de at googlemail.com
Wed Feb 15 08:11:48 GMT 2012
Hi,
I'm having a problem with signing my assertion. I did it like shown in the
User-Manual and my assertion
gets signed (when viewed as text) but the problem is that none of the
Service Providers can verify the signature.
So something seems to be wrong but i really can't find the problem so i
hope you guys can help me a little.
Thanks
Following is some code and the response and metadata files... i hope this
is enough to help me.. if something is unclear please ask, i'll then
provide the information.
in my programm it is called like this:
SAML2ApplicationBinding binding = new SAML2ApplicationBinding(app);
encoded = binding.getBase64EncodedResponse();
samlDocument = binding.getResponseAsString();
Here is the code I use to sign the assertion:
class SAML2ApplicationBinding {
private final String IDP_KEY_FILE = "C:\\Dokumente und
Einstellungen\\some_user\\Eigene Dateien\\certs\\idp.der";
private final String IDP_CERT_FILE = "C:\\Dokumente und
Einstellungen\\some_user\\Eigene Dateien\\certs\\idp.crt";
private SAML2Response response;
public SAML2ApplicationBinding(Application app) throws
NoSuchAlgorithmException, KeyException, SecurityException,
MarshallingException, SignatureException, EncryptionException,
InvalidKeySpecException, CertificateException, IOException {
application = app;
this.response = buildSAML2Response();
}
....
protected SAML2Response buildSAML2Response() throws SecurityException,
MarshallingException, SignatureException, NoSuchAlgorithmException,
KeyException, EncryptionException, InvalidKeySpecException,
CertificateException, IOException {
Assertion assertion = buildSAML2Assertion(getIssuer(),
getSubject(),
getAudienceRestriction(), getAttributes());
response = new SAML2Response(StatusCode.SUCCESS_URI, getIssuer(),
assertion);
if (inResponseTo != null) {
response.setInResponseTo(inResponseTo);
assertion.getSubject().getSubjectConfirmations().get(0).getSubjectConfirmationData().setInResponseTo(inResponseTo);
}
response.signAssertion(getSigningCredentials());
if(isEncrypted()) {
response.encryptAssertion(getEncryptionCredentials());
}
return response;
}
...
protected Credential getSigningCredentials() throws
NoSuchAlgorithmException, InvalidKeySpecException, IOException,
CertificateException {
// enter files for signing
return getCredential(IDP_KEY_FILE, IDP_CERT_FILE);
//BasicX509Credential c = new BasicX509Credential();
//c.setPrivateKey(new EncryptionHelper().getPrivateKey(new
EncryptionHelper().readKeyFromFile(IDP_KEY_FILE)));
//return c;
}
....
protected Credential getCredential(String keyFile, String certFile)
throws NoSuchAlgorithmException, InvalidKeySpecException, IOException,
CertificateException {
EncryptionHelper encHelper = new EncryptionHelper();
PrivateKey pk =
encHelper.getPrivateKey(encHelper.readKeyFromFile(keyFile));
X509Certificate cert =
(X509Certificate)encHelper.getCertificate(certFile);
BasicX509Credential cred = SecurityHelper.getSimpleCredential(cert,
pk);
return cred;
}
public String getBase64EncodedResponse() {
return new String(new
Base64().encode(response.toString().getBytes()));
}
}
class EncryptionHelper {
public byte[] readKeyFromFile(String privateKeyFile) throws IOException{
File privKeyFile = new File(privateKeyFile);
BufferedInputStream bs = new BufferedInputStream(new
FileInputStream(privKeyFile));
byte[] privKeyBytes = new byte[(int)privKeyFile.length()];
bs.read(privKeyBytes);
bs.close();
return privKeyBytes;
}
public RSAPrivateKey getPrivateKey(byte[] privKeyBytes) throws
NoSuchAlgorithmException, InvalidKeySpecException {
PKCS8EncodedKeySpec privKeySpec = new
PKCS8EncodedKeySpec(privKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return (RSAPrivateKey)keyFactory.generatePrivate(privKeySpec);
}
}
class SAML2Response {
....
public void signAssertion(Credential cred) throws SecurityException,
MarshallingException, SignatureException {
Signature sig = SAMLHelper.createElement(Signature.class,
Signature.DEFAULT_ELEMENT_NAME);
sig.setSigningCredential(cred);
sig.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1);
sig.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
assertion.setSignature(sig);
KeyInfoGeneratorFactory kf =
Configuration.getGlobalSecurityConfiguration()
.getKeyInfoGeneratorManager().getDefaultManager()
.getFactory(cred);
KeyInfo ki = kf.newInstance().generate(cred);
sig.setKeyInfo(ki);
Configuration.getMarshallerFactory().getMarshaller(assertion).marshall(assertion);
Signer.signObject(sig);
}
...
public String toString() {
Element saml;
String samlDocument = null;
setRightAssertion();
try {
saml = marshallResponse();
samlDocument = XMLHelper.prettyPrintXML(saml);
} catch (MarshallingException e) {
e.printStackTrace();
}
return samlDocument;
}
protected void setRightAssertion() {
if(encryptedAssertion != null) {
setEncryptedAssertionIfNoneIsSet();
} else {
setAssertionIfNoneIsSet();
}
}
protected void setAssertionIfNoneIsSet() {
if(response.getAssertions().size() == 0)
response.getAssertions().add(assertion);
}
}
public class SAMLHelper {
@SuppressWarnings ("unchecked")
public static <T> T createElement(Class<T> cls, QName qname)
{
return (T) ((XMLObjectBuilder) Configuration.getBuilderFactory
().getBuilder (qname)).buildObject (qname);
}
}
The resulting Assertion (samlDocument variable) looks like this when printed
<?xml version="1.0" encoding="UTF-8"?><saml2p:Response
xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
ID="_cd098162-cb16-4c22-92bf-c8a4a2704328"
IssueInstant="2012-02-14T15:29:07.353Z" Version="2.0">
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
http://localhost:8080</saml2:Issuer>
<saml2p:Status>
<saml2p:StatusCode
Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</saml2p:Status>
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
ID="_cd098162-cb66-4c22-92bf-c8a4a2704328"
IssueInstant="2012-02-14T15:29:07.275Z" Version="2.0">
<saml2:Issuer>http://localhost:8080</saml2:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="
http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="
http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#_cd098162-cb66-4c22-92bf-c8a4a2704328">
<ds:Transforms>
<ds:Transform Algorithm="
http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="
http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="
http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>Isy4SHv6cwVl1FpQB2L60lx2n1g=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>TBndBsclAvi6pBuZFGO1HEiTxmTxNBXiFQ5Byu3j++jKc8zq+mbujlm0TypTFyBzX7n8DZflIErwkm7w8FBFifkJyzH3+Kkn7URJK5N6BuhJ241WZBBZMnbbdcfI0HOKX7wQSS18ThknUk25vDEOKmnCC762lzaOWXezqiqoP8Wcl+yfDG8eADTf/Ko1WfNIH/4MMC9wOQDuyMz1RogQkPmQqz7kyCNWS1yVRv2m9SZW26/hsIV3/fbEhl0+3/AZJoysvH6oEaTpQoJLjWEpM/wiPtviaT/D3av7iIe2pR/aWFlsWGBkBcEI6AFj+74v2GdgA1QmGLGazo4dt/o2DQ==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIDWzCCAkOgAwIBAgIJAPMEpZqGeqqmMA0GCSqGSIb3DQEBBQUAMEQxCzAJBgNVBAYTAkRFMQ8w
DQYDVQQIDAZCYS1XdWUxEjAQBgNVBAcMCUthcmxzcnVoZTEQMA4GA1UECgwHUG9yc2NoZTAeFw0x
MjAyMTQxNTA1MzlaFw0yMjAyMTMxNTA1MzlaMEQxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIDAZCYS1X
dWUxEjAQBgNVBAcMCUthcmxzcnVoZTEQMA4GA1UECgwHUG9yc2NoZTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAOrNmz1j9GyfbhCJ7RdWpeGDumMMGsWHFas9d/3BLA/nAE7OLlf5FHjf
Q5KyCGt98IKEVy3wCyLYw44haBxxJvl1KReuJ4sPZB3L5ahfrr8re6fK6v+znl4oOQY5XMpliRpP
e3nTaxVGPWIy28eFFp5xyeXkFWBZqPTVFolW3I4mf0r6HFLMVjndTdJtUqSxWUYdvxseECoYI6bL
9sjYEtx9nhB2Po1+RWfTZH5t4fRFcFUr/AVVRncAejgE61aX8IVrMScMZ9iH/eXDbfkGYWG9z3S2
yPgc52naPwfofAgtF/pqXH1Ew5iRhRtYrWRXDNt9owmofLqgGG/oJAUygyMCAwEAAaNQME4wHQYD
VR0OBBYEFKuMizdQPCWBXa0IzJ87man5JPD0MB8GA1UdIwQYMBaAFKuMizdQPCWBXa0IzJ87man5
JPD0MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAI9HPwypM2Uo6Nb51CjwGNVhBegm
KzORuS2pVOMVuUoSSPuR6NRZyIhweLibjaxe40P57KErd22i2YYlIA9jSzo8dTgd/yssrbtTg8c/
PthUKaSHujNS4si7CicVcW5pf82F/LocRJ5/2x0pxLXX1DYV3P+ukrY8MgWVOY0z9xWHlvVJCVdw
XmHkxV5+DYeoXK62be2uBHzeVyMzxcr4fLd05YpPIUkIcmSg6RG8ZQG/7Mqk734z0jnLN6LJG/cA
eJvI685Uw3nGG+V5EgDcDtitnwaRECgir3Sm1Nn0K+1aKjnOftJpQZfUN8mble7fj24UWg6ZW2VT
+KltyImTM1M=</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml2:Subject>
<saml2:NameID>test_principal</saml2:NameID>
<saml2:SubjectConfirmation
Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml2:SubjectConfirmationData
NotBefore="2012-02-14T15:29:07.338Z"/>
</saml2:SubjectConfirmation>
</saml2:Subject>
<saml2:Conditions>
<saml2:AudienceRestriction>
<saml2:Audience>saml2SP</saml2:Audience>
</saml2:AudienceRestriction>
</saml2:Conditions>
<saml2:AuthnStatement AuthnInstant="2012-02-14T15:29:07.338Z">
<saml2:AuthnContext>
<saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
</saml2:AuthnContext>
</saml2:AuthnStatement>
<saml2:AttributeStatement>
<saml2:Attribute Name="Nachname">
<saml2:AttributeValue>lastname</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute Name="Abteilung">
<saml2:AttributeValue>unit</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute Name="Firma">
<saml2:AttributeValue>company</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute Name="Vorname">
<saml2:AttributeValue>firstname</saml2:AttributeValue>
</saml2:Attribute>
</saml2:AttributeStatement>
</saml2:Assertion>
</saml2p:Response>
So the signature seems to be there.... but when checked at the other side
(oracle weblogic / simplesamlphp) the certificate in the metadata seem not
to
match the signature or the signature does not match the document... i'm not
100% sure at this point. But what's for sure is that it does not work ;-)
The Metadata I'm using is like this:
<?xml version="1.0"?>
<md:EntityDescriptor
xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
entityID="http://localhost:8080">
<md:IDPSSODescriptor
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>
MIIDWzCCAkOgAwIBAgIJAPMEpZqGeqqmMA0GCSqGSIb3DQEBBQUAMEQxCzAJBgNV
BAYTAkRFMQ8wDQYDVQQIDAZCYS1XdWUxEjAQBgNVBAcMCUthcmxzcnVoZTEQMA4G
A1UECgwHUG9yc2NoZTAeFw0xMjAyMTQxNTA1MzlaFw0yMjAyMTMxNTA1MzlaMEQx
CzAJBgNVBAYTAkRFMQ8wDQYDVQQIDAZCYS1XdWUxEjAQBgNVBAcMCUthcmxzcnVo
ZTEQMA4GA1UECgwHUG9yc2NoZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAOrNmz1j9GyfbhCJ7RdWpeGDumMMGsWHFas9d/3BLA/nAE7OLlf5FHjfQ5Ky
CGt98IKEVy3wCyLYw44haBxxJvl1KReuJ4sPZB3L5ahfrr8re6fK6v+znl4oOQY5
XMpliRpPe3nTaxVGPWIy28eFFp5xyeXkFWBZqPTVFolW3I4mf0r6HFLMVjndTdJt
UqSxWUYdvxseECoYI6bL9sjYEtx9nhB2Po1+RWfTZH5t4fRFcFUr/AVVRncAejgE
61aX8IVrMScMZ9iH/eXDbfkGYWG9z3S2yPgc52naPwfofAgtF/pqXH1Ew5iRhRtY
rWRXDNt9owmofLqgGG/oJAUygyMCAwEAAaNQME4wHQYDVR0OBBYEFKuMizdQPCWB
Xa0IzJ87man5JPD0MB8GA1UdIwQYMBaAFKuMizdQPCWBXa0IzJ87man5JPD0MAwG
A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAI9HPwypM2Uo6Nb51CjwGNVh
BegmKzORuS2pVOMVuUoSSPuR6NRZyIhweLibjaxe40P57KErd22i2YYlIA9jSzo8
dTgd/yssrbtTg8c/PthUKaSHujNS4si7CicVcW5pf82F/LocRJ5/2x0pxLXX1DYV
3P+ukrY8MgWVOY0z9xWHlvVJCVdwXmHkxV5+DYeoXK62be2uBHzeVyMzxcr4fLd0
5YpPIUkIcmSg6RG8ZQG/7Mqk734z0jnLN6LJG/cAeJvI685Uw3nGG+V5EgDcDtit
nwaRECgir3Sm1Nn0K+1aKjnOftJpQZfUN8mble7fj24UWg6ZW2VT+KltyImTM1M=
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:NameIDFormat>
urn:oasis:names:tc:SAML:2.0:nameid-format:transient
</md:NameIDFormat>
<md:SingleSignOnService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="http://localhost:8080/testSaml/getTestSaml"/>
</md:IDPSSODescriptor>
<md:Organization>
<md:OrganizationName xml:lang="en">
SAML2 Demo Provider
</md:OrganizationName>
<md:OrganizationDisplayName xml:lang="en">
SAML2 Demo Identity Provider @ localhost
</md:OrganizationDisplayName>
<md:OrganizationURL xml:lang="en">
http://localhost:8080
</md:OrganizationURL>
</md:Organization>
<md:ContactPerson contactType="technical">
<md:SurName>some-lastname</md:SurName>
<md:EmailAddress>some at email.de</md:EmailAddress>
</md:ContactPerson>
</md:EntityDescriptor>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://shibboleth.net/pipermail/dev/attachments/20120215/86658b91/attachment-0001.html
More information about the dev
mailing list