I'm following the example on the wiki to sign an XML object (either a
SAML2 Assertion or a class that extends AbstractSignableXMLObject).
The code I use is very much like the one on the wiki:
BasicX509Credential stCred = new BasicX509Credential();
stCred.setEntityCertificate(myApp.cert);
Signature signature = (Signature)
Configuration.getBuilderFactory()
.getBuilder(Signature.DEFAULT_ELEMENT_NAME)
.buildObject(Signature.DEFAULT_ELEMENT_NAME);
signature.setSigningCredential(stCred);
signature
.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1);
signature
.setCanonicalizationAlgorithm
(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
myAssertion.setSignature(signature);
try {
Configuration
.getMarshallerFactory
().getMarshaller(myAssertion).marshall(myAssertion);
} catch(MarshallingException e) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, e);
}
try {
Signer.signObject(signature);
} catch(SignatureException e) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, e);
}
If I run this code on an assertion (myAssertion) I get the following
exception:
Exception in thread "main" java.lang.RuntimeException:
org.apache.xml.security.signature.XMLSignatureException: object not
initialized for signature or verification
Original Exception was java.security.SignatureException: object not
initialized for signature or verification
at
org.apache.xml.security.utils.SignerOutputStream.write(Unknown Source)
at
org
.apache
.xml.security.utils.UnsyncBufferedOutputStream.flushBuffer(Unknown
Source)
at
org.apache.xml.security.utils.UnsyncBufferedOutputStream.flush(Unknown
Source)
at
org.apache.xml.security.utils.UnsyncBufferedOutputStream.close(Unknown
Source)
at
org
.apache
.xml
.security
.c14n
.implementations.CanonicalizerBase.engineCanonicalizeSubTree(Unknown
Source)
at
org
.apache
.xml
.security
.c14n
.implementations
.Canonicalizer20010315Excl.engineCanonicalizeSubTree(Unknown Source)
at
org
.apache
.xml
.security
.c14n
.implementations
.Canonicalizer20010315Excl.engineCanonicalizeSubTree(Unknown Source)
at
org.apache.xml.security.c14n.Canonicalizer.canonicalizeSubtree(Unknown
Source)
at
org
.apache.xml.security.signature.SignedInfo.signInOctectStream(Unknown
Source)
at
org.apache.xml.security.signature.XMLSignature.sign(Unknown Source)
at org.opensaml.xml.signature.Signer.signObject(Signer.java:78)
Any idea what went wrong?
If I run the same code on my own class, replacing:
myAssertion.setSignature(signature);
with
ep.EPR.setSignature(signature);
and the marshalling line
Configuration
.getMarshallerFactory
().getMarshaller(myAssertion).marshall(myAssertion);
with:
Configuration
.getMarshallerFactory().getMarshaller(ep.EPR).marshall(ep.EPR);
I get another error (same place - calling Signer.signObject()):
1370 [main] ERROR org.opensaml.xml.signature.Signer - Unable to
compute signature, Signature XMLObject does not have the XMLSignature
created during marshalling.
SEVERE: null
org.opensaml.xml.signature.SignatureException: XMLObject does not have
an XMLSignature instance, unable to compute signature
at org.opensaml.xml.signature.Signer.signObject(Signer.java:75)
That one is also surprising since the EPR class does extend
AbstractSignableXMLObject and does get the signature.
Any hint greatly appreciated!
Hubert
| Hubert Le Van Gong <Hubert.L...@Sun.COM>
Sent by: Hubert.L...@Sun.COM 09/10/2008 10:56 AM
|
|
Hubert Le Van Gong wrote:
> Hi Guys,
>
> I'm following the example on the wiki to sign an XML object (either a
> SAML2 Assertion or a class that extends AbstractSignableXMLObject).
> The code I use is very much like the one on the wiki:
>
>
I don't see anything obviously wrong with the OpenSAML code there. What
versions of the opensaml stack library jars and Apache xmlsec jar are
you using?
As you just posted, this error is similar to an Apache xmlsec issue
which I posted on in some detail:
https://issues.apache.org/bugzilla/show_bug.cgi?id=44204
What all are you doing in your code prior to this being called? Are you
signing and/or verifying multiple things in the same thread? That exact
bug report may not exactly apply here, but the Apache xmlsec code has
some "interesting" optimizations which could cause it to fail here (and
should be fixed, IMHO). You might be doing something to trigger it. It
caches some objects in ThreadLocal storage, and they don't always get
reinitialized properly if you do multiple operations in the same thread,
with the same key, for the same algorithm URI.
> If I run the same code on my own class, replacing:
> myAssertion.setSignature(signature);
> with
> ep.EPR.setSignature(signature);
> and the marshalling line
> Configuration.getMarshallerFactory().getMarshaller(myAssertion).marshall(myAssertion);
>
> with:
> Configuration.getMarshallerFactory().getMarshaller(ep.EPR).marshall(ep.EPR);
>
>
> I get another error (same place - calling Signer.signObject()):
>
> 1370 [main] ERROR org.opensaml.xml.signature.Signer - Unable to
> compute signature, Signature XMLObject does not have the XMLSignature
> created during marshalling.
> SEVERE: null
> org.opensaml.xml.signature.SignatureException: XMLObject does not have
> an XMLSignature instance, unable to compute signature
> at org.opensaml.xml.signature.Signer.signObject(Signer.java:75)
>
> That one is also surprising since the EPR class does extend
> AbstractSignableXMLObject and does get the signature.
>
This sounds like your Signature child isn't getting marshalled when you
marshall it's parent (the ep.EPR). Check your EPR XMLObject's
getOrderedChildren() method - I suspect you have neglected to include
the Signature child in the list of child objects that is returned. See
some of the other XMLObject impl classes if you want an example of what
that method should look like.
--Brent
After double checking I found that I was performing a validity check
on the
certificate used to sign the assertion. I removed it and it seems to
be working
fine now, at least when it comes to signing SAML assertions; I have to
check this with non SAML classes like my EPRs. As you mentioned I'll
need
to add a ContentReference to the signature too.
I presume a URIContentReference set to "" will point at the root of
the EPR, correct?
Thanks again,
Hubert
On Sep 10, 2008, at 10:33 PM, Brent Putman wrote:
>
>
> Hubert Le Van Gong wrote:
>> Hi Guys,
>>
>> I'm following the example on the wiki to sign an XML object (either a
>> SAML2 Assertion or a class that extends AbstractSignableXMLObject).
>> The code I use is very much like the one on the wiki:
>>
>>
>> If I run this code on an assertion (myAssertion) I get the following
>> exception:
>>
>> Exception in thread "main" java.lang.RuntimeException:
>> org.apache.xml.security.signature.XMLSignatureException: object not
>> initialized for signature or verification
>> Original Exception was java.security.SignatureException: object not
>> initialized for signature or verification
>> at
>> org.apache.xml.security.utils.SignerOutputStream.write(Unknown
>> Source)
>> at
>> Configuration
>> .getMarshallerFactory
>> ().getMarshaller(myAssertion).marshall(myAssertion);
>>
>> with:
>>
>> Configuration
>> .getMarshallerFactory().getMarshaller(ep.EPR).marshall(ep.EPR);
>>
>>
Hubert Le Van Gong wrote:
> Thanks Brent,
>
> After double checking I found that I was performing a validity check
> on the
> certificate used to sign the assertion. I removed it and it seems to
> be working
> fine now, at least when it comes to signing SAML assertions;
Ok, good to know.
> I have to
> check this with non SAML classes like my EPRs.
Ok. Just pointing out in case it isn't obvious: The mechanism that
you're implicitly using here is enveloped signature. I'm assuming
enveloped is schema valid for the elements/classes you want to sign? If
this EPR here is WS-Addressing EndpointReference, then I guess it is,
based on its extensible schema (wildcard child elements). Just
something to be aware of. OpenSAML also supports detached signatures
should you need to do that.
> As you mentioned I'll need
> to add a ContentReference to the signature too.
> I presume a URIContentReference set to "" will point at the root of
> the EPR, correct?
Based on my understanding, no. Empty "" URI means (from the Signature
spec):
URI=""
Identifies the node-set (minus any comment nodes) of the XML
resource containing the signature
Which means the entire Document in which the EPR would be contained.
Very likely may not be what you want: You sign it stand-alone, and it
verifies. Then you embed it in another document, and the signature breaks.
You may instead want to use the DocumentInternalIDContentReference.
That assumes that the element(s) you want to sign support an ID-typed
attribute, which can be used as the target of a document fragment
reference. EPR would seem to, since it's also extensible via wildcard
attributes. Again, it's a question of schema validity.
--Brent
> Hubert Le Van Gong wrote:
>> Thanks Brent,
>>
>> After double checking I found that I was performing a validity check
>> on the
>> certificate used to sign the assertion. I removed it and it seems to
>> be working
>> fine now, at least when it comes to signing SAML assertions;
>
> Ok, good to know.
>
>> I have to
>> check this with non SAML classes like my EPRs.
>
> Ok. Just pointing out in case it isn't obvious: The mechanism that
> you're implicitly using here is enveloped signature. I'm assuming
> enveloped is schema valid for the elements/classes you want to
> sign? If
> this EPR here is WS-Addressing EndpointReference, then I guess it is,
> based on its extensible schema (wildcard child elements). Just
> something to be aware of. OpenSAML also supports detached signatures
> should you need to do that.
Yup I had checked it was enveloped signature.
I suppose you haven't seen much demand for enveloping signature?
>> As you mentioned I'll need
>> to add a ContentReference to the signature too.
>> I presume a URIContentReference set to "" will point at the root of
>> the EPR, correct?
>
> Based on my understanding, no. Empty "" URI means (from the Signature
> spec):
>
> URI=""
> Identifies the node-set (minus any comment nodes) of the XML
> resource containing the signature
>
> Which means the entire Document in which the EPR would be contained.
> Very likely may not be what you want: You sign it stand-alone, and it
> verifies. Then you embed it in another document, and the signature
> breaks.
>
> You may instead want to use the DocumentInternalIDContentReference.
> That assumes that the element(s) you want to sign support an ID-typed
> attribute, which can be used as the target of a document fragment
> reference. EPR would seem to, since it's also extensible via wildcard
> attributes. Again, it's a question of schema validity.
You make a good point, although in the present use case I do have an EPR
that is standalone. For the general case using
DocumentInternalIDContentReference
seems better indeed.
Thanks,
Hubert
Our entire reason for this project relates to the difficulty of handling
signatures in the context of existing content that needs to be signed, using
the tools that exist (xml-security alone, Axis, JAXB etc.) If they worked
well, we wouldn't have needed most of OpenSAML, and certainly most of the
xmltooling work.
To "support" enveloping signatures, we'd essentially have to do an XML
Security library ourselves, which wasn't really the point. If you need
enveloping, using xml-security directly would be more sensible (and you
could marshall any XMLObject into a DOM that could be attached to an Apache
or Java Signature object).
-- Scott