Signing multiple objects?
Brad Cox
bradjcox at gmail.com
Tue Nov 1 14:21:29 GMT 2011
Making progress; getting plausible signed envelopes and shooting now for
validation, but need a bit more help decoding the instructions at the very
bottom.
The first sentence is what sent me on the prior wild goose chase. As I read
this, "SAMLObject" means an instance of Envelope (right?). Problem is at
this point exists only as as Element, and I've so far been unable to
marshal that to an Envelope. And in any event Envelope doesn't have a
setSignature() method.
So what I have now works entirely at the DOM level which doesn't seem
right.
public void attachSamlAssertion(Document document)
{
Element soapEnvelope = document.getDocumentElement();
Element soapHeader = DOMUtil.getSoapHeader(soapEnvelope);
Element soapBody = DOMUtil.getSoapBody(soapEnvelope);
try
{
SecurityMarshaller m3 = new SecurityMarshaller();
Element securityElmt = m3.marshall(newSecurity(), document);
soapHeader.appendChild(securityElmt);
Signature signature = newSignature();
SignatureMarshaller sigM = new SignatureMarshaller();
Element signatureElmt = sigM.marshall(signature, document);
securityElmt.appendChild(signatureElmt);
TimestampMarshaller tsm = new TimestampMarshaller();
Element timeStampElmt = tsm.marshall(newTimeStamp(), document);
securityElmt.appendChild(timeStampElmt);
MessageIDMarshaller mim= new MessageIDMarshaller();
Element msgIDElmt = mim.marshall(newMessageID(), document);
securityElmt.appendChild(msgIDElmt);
Assertion assertion = newAssertion();
AssertionMarshaller marshaller = new AssertionMarshaller();
Element assertionElmt = marshaller.marshall(assertion, document);
securityElmt.appendChild(assertionElmt);
log.info("Unsigned Document\n{}", XMLHelper.prettyPrintXML(soapEnvelope));
Signer.signObject(signature);
log.info("Signed Envelope\n{}", XMLHelper.prettyPrintXML(soapEnvelope));
// Worrisome but without it getDocumentElement == null
document.adoptNode(soapEnvelope);
document.appendChild(soapEnvelope);
return;
}
catch (Exception e)
{
throw new XacmlFault(e);
}
}
Next I've been unable to decode Step#5 to generate a KeyInfo which I think
I'll need for validation (right?).
Fails with a null pointer on the line marked NPE -> below
public Signature newSignature()
{
SignatureBuilder bldr = (SignatureBuilder)
factory.getBuilder(Signature.DEFAULT_ELEMENT_NAME);
Signature sig = (Signature) bldr.buildObject();
Credential credential = signer.getCredential();
sig.setSigningCredential(credential);
sig.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
sig.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1);
KeyInfoGeneratorManager kgm = new KeyInfoGeneratorManager();
KeyInfoGeneratorFactory kif = kgm.getFactory(credential);
NPE-> KeyInfoGenerator kig = kif.newInstance();
try
{
KeyInfo ki = kig.generate(credential);
sig.setKeyInfo(ki);
// KeyInfoFactory kFactory = factory.getKeyInfoFactory();
// keyInfo = kFactory.newKeyInfo(Collections.singletonList
(kFactory.newX509Data
// (Collections.singletonList (entry.getCertificate ()))));
}
catch (SecurityException ex)
{
throw new XacmlFault("KeyInfo fault", ex);
}
URIContentReference contentReference = new URIContentReference("");
contentReference.getTransforms().add(SignatureConstants.TRANSFORM_ENVELOPED_SIGNATURE);
contentReference.getTransforms().add(SignatureConstants.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
contentReference.setDigestAlgorithm(SignatureConstants.ALGO_ID_DIGEST_SHA1);
sig.getContentReferences().add(contentReference);
return sig;
}
Here are the instructions I've been trying to follow. (Wouldn't a code
sample be easier?)
The first step in signing a SAMLObject is to create a Signature object and
attach it to the SAMLObject. Since all SAMLObjects that can be signed
implement the interface org.opensaml.common.SignableSAMLObject the code to
sign an object is always the same.
1. Create a Signature object using the
org.opensaml.xml.signature.impl.SignatureBuilder (this is found in
the XMLTooling library). This will likely be obtained from a builder
factory. See Creating SAML Objects from
Scratch<https://wiki.shibboleth.net/confluence/display/OpenSAML/OSTwoUsrManJavaCreateFromScratch>
.
2. Add the Credential containing the signing key using the
Signature#setSigningCredential(Credential) method.
3. Add the signature method algorithm URI with the method
Signature#setSignatureAlgorithm(String). Note that the algorithm URI
is dependent on the type of key contained with the signing credential.
4. Add the canonicalization method algorithm URI with the method
Signature#setCanonicalizationAlgorithm(String). Note that unless
there is good reason to do otherwise, and the ramifications are
understood,
the recommended canonicalization method for SAML signature use cases is
exclusive canonicalization (with or without comments).
5. If desired, add a KeyInfo containing information about the
signature verification key using Signature#setKeyInfo(KeyInfo). The
KeyInfo may be created manually, or may be generated dynamically from
the signing credential using a KeyInfoGenerator, usually obtained
from a KeyInfoGeneratorFactory via a KeyInfoGeneratorManager.
6. Add the Signature to the SAMLObject using the
setSignature(Signature) method. A SAMLObjectContentReference will
automatically be added to the list of signature references exposed via
Signature#getContentReferences(), so you should *NOT* explicitly add
a reference to the signature. Note that the Signature contained
within a signed element in SAML may contain only one Reference in the
SignedInfo, per the SAML signature profile.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://shibboleth.net/pipermail/dev/attachments/20111101/a8fc3700/attachment.html
More information about the dev
mailing list