Xml Signature in Java but only on elements where attribute authenticate='true' - java

I have been able to sign and verify my XML signature when using Apache Santuario, but now I want to only apply the signature to fields where the attribute authenticate="true"
For example:
<Document>
<DoNotSign></DoNotSign>
<DoSign authenticate="true"></DoSign>
<Something>
<SomethingElse authenticate="true"></SomethingElse>
</Someting>
</Document>
Can anyone help me understand how to achieve it?
I add the reference URI like so:
xmlSignature.addDocument("#xpointer(//*[#authenticate='true'])", transforms, Constants.ALGO_ID_DIGEST_SHA1);
And just get an exception:
Original Exception was org.apache.xml.security.utils.resolver.ResourceResolverException:
Could not find a resolver for URI #xpointer(//*[#authenticate='true'])
I have tried adding the following:
transforms.addTransform(Transforms.TRANSFORM_XPOINTER);
xmlSignature.getSignedInfo().addResourceResolver(new ResolverXPointer());
This returns me an exception when adding the XPOINTER transform.
The ResolverXPointer seems to have no effect.
TransformationException: Unknown transformation.
No handler installed for URI http://www.w3.org/TR/2001/WD-xptr-20010108
The complete method is below:
final var transforms = new Transforms(document);
transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
transforms.addTransform(Transforms.TRANSFORM_XPOINTER);
xmlSignature.addDocument("#xpointer(//*[#authenticate='true'])", transforms, Constants.ALGO_ID_DIGEST_SHA1);
xmlSignature.addKeyInfo(signingCertificate);
xmlSignature.sign(signingKey);

To solve this issue I created a custom ResourceResolverSPI and added it
ResourceResolver.register(new XPathResourceResolver(), true);
That solved the issue, the custom resolver just uses XPath to create a Set for signing.

Related

Rythm use transformers and nested tags with #i18n tag

First of all I'm very happy with Rythm! Excellent work for something that is free.
Recently I have begun internationalization of my templates with Rythm and some things seem more cumbersome than needed. I'm wondering if there is any better way of doing what I'm trying to do.
1. Chain tag onto #i18n()
This does not work:
#i18n("about.text").nl2br()
#i18n("about.text").mytransformer()
The workaround for this is:
#assign(newvar){#i18n("about.text")}
#newvar.nl2br()
This works but is is not pretty.
2. #i18n() escaped in javascript
If I have a section
<script>
var s = '#description';
</script>
then Rythm will nicely escape any ' or " in that description. However when I use:
<script>
var s = '#i18n("description")';
</script>
escaping is not done. I also tried doing:
var s = '#i18n("description").escape("js")';
and
var s = '#escapeJS(){#i18n("description")}';
but both do not work (see above). What does work again is using
#assign(desc){#i18n("description")}
...
var s = '#desc';
3. Use of tag inside #i18n() as argument
Sometimes I need a link inside a translated string like so:
about.text=See my profile here {1}
I would like to use this in the template as follows:
#i18n("about.txt",#genlink("person",person.getId()),person)
Note: person here is an template argument of type Person. #genlink is a convenience template(or tag) to generate a link using a lookup.
The solution I currently use is:
#assign(lnk){<a href='#genlink("person",person.getId())'>#person</a>}
#i18n("about.txt",lnk)
Note that the language resource has changed to: about.text=See my profile here {0}
This is probably the better way to write the resource string anyway, but it would be nice if I could get rid of the #assign() somehow and write this:
#i18n("about.text","<a href='#genlink("person",person.getId())'>#person</a>")
Edit:
I tried your suggestions and was only partially successful.
Chain tag onto #i18n()
doing #("about.text".i18n()) works whereas doing #("about.text".i18n().nl2br()) doesn't work and complains about a missing parameter for #i18n(). If I add the missing parameter like so: #("about.txt".i18n("").nl2br()) it complains that nl2br() is not defined for String
What did work for me was: #s().i18n("about.txt").nl2br()
Even weirder so, when I run your fiddle on Chrome it works perfectly. When I run it on Mac/Safari I get the same error as I just described: see screenshot:
#i18n() escaped in javascript
Works as you explained!
Use of tag inside #i18n() as argument
understood. The current solution with #assign() is fine for one-offs. Using #def() is a nicer generic solution.
Chain tag onto #i18n()
Try to use .i18n() transformer instead of #i18n() tag.
Say change #i18n("about.text").nl2br() to #("about.text".i18n().nl2br())
Note you need the () pair to enclose the entire expression if you feed into a string literal like "about.text", however if you do the same thing for a variable then that () can be opt out, e.g #foo.i18n().nl2br()
#i18n() escaped in javascript
Again, use .i18n() transformer
Use of tag inside #i18n() as argument
Tag processing is very hard to put into another tag or transformer. In your case I recommend you to use inline tag
The demonstration of all above three points could be found at http://fiddle.rythmengine.org/#/editor/0c426d5332334db3870b6bd8c0806e66

Thymeleaf add custom data attribute with message resource value

I have a requirement where I need to insert the value to custom data tag using thymeleaf. The code for doing it using
data-th-attr="${data-custom=#messages.msg('test')}"
as well as
th:attr="data-custom=${#messages.msg('test')}"
I am unable to get the value in both the cases.
ultimately the parsing should be like data-custom="test"
here test is key for the value test in a properties file
By using the
data-th-attr="data-custom=#{test}"
or By using
th:attr="data-custom=#{test}"
helped me out, here test is the key for the value in message resource the issue was with the intellij IDEA IDE, it was having a bug that was showing me an unnecessary error.
Use th:attr="data-custom=#{key.for.message}" , this should work.
then after parsing the Expression,
data-custom="value.for.message"

XML Signature Reference digest uses parent namespace

I need to sign an XML-File in Java, which needs to contain 3 References.
While 2 of them are valid (expected digest == actual digest), one is invalid.
The relevant part of the XML Looks like:
<QualifyingProperties xmlns="http://uri.etsi.org/01903/v1.3.2#" Target="Signature1">
<SignedProperties Id="SignedProperties_1">
<SignedSignatureProperties>
<SigningTime>2014-11-27T13:49:36</SigningTime>
</SignedSignatureProperties>
</SignedProperties>
</QualifyingProperties>
The Reference only references the Element "SignedProperties" and its children.
As you can see the "QualifyingProperties" Element defines a namespace (xmlns="http://uri.etsi.org/01903/v1.3.2#") and i guess thats the problem:
After having a look at the log i found, that the "Pre-Digest" Value looks like:
<SignedProperties xmlns="http://uri.etsi.org/01903/v1.3.2#" Id="SignedProperties_1">
<SignedSignatureProperties>
<SigningTime>2014-11-27T13:49:36</SigningTime>
</SignedSignatureProperties>
</SignedProperties>
While the "SignedProperties" Element in the real file does not contain the namespace, but its parent does.
I found out, that the actual digest matches the SHA-256 of the "Pre-Digest" value, while the expected digest matches the SHA-256 of the real file (without the namespace).
The Reference is created with the following code:
Reference sigPropRef = fac.newReference("#SignedProperties_1", fac.newDigestMethod(DigestMethod.SHA256, null),
Collections.singletonList(sigPropTransform), "http://uri.etsi.org/01903#SignedProperties", "reference-signedpropeties"
);
Where the sigPropTransform is a CanonicalizationMethod.EXCLUSIVE Transform.
My question is, how can i solve the problem, i.e. how can i prevent the namespace to be added to the "SignedProperties" Element, before calculating the digest?
If you need any other informations please leave a comment, i am pretty new to this theme, so i am not sure which informations are relevant and which not.
Thanks a lot!
EDIT: After playing arround a bit, it seems to me, that the "actual digest" is the digest, the validator calculated, while the "expected digest" is the digest inside the "DigestValue" Element.
That means, that the digest value inside my file matches the SHA-256 of the referenced filepart, but the validator for some reason calculates the digest WITh the parents namespace.
So i guess what i need is to include the parents namespace in my digest calculation.
EDIT: I continued playing arround and now i have not only the Pre-Digest value of the validator but also the one of my "digest calculation".
That one gives me:
<SignedProperties Id="SignedProperties_1"><SignedSignatureProperties><SigningTime>2014-11-27T15:51:26</SigningTime></SignedSignatureProperties></SignedProperties>
when i give it the following Transform:
Transform sigPropTransform = fac.newTransform(CanonicalizationMethod.EXCLUSIVE, (ExcC14NParameterSpec)null);
And:
<SignedProperties xmlns:ds="some-url" xmlns:msg="some-other-url" Id="SignedProperties_1"><SignedSignatureProperties><SigningTime>2014-11-27T15:52:49</SigningTime></SignedSignatureProperties></SignedProperties>
when i don't give it any Transform.
The namespace xmlns="http://uri.etsi.org/01903/v1.3.2#" is never included.
How do i include it?
I'm afraid that you cannot prevent adding a namespace - it's being add during canonicalizaton.
This one helped me when i had identical issue ;)
After a few more tries i finally found the actuall problem, as well as the solution:
As i allready stated in the question, the digest calculation did not use the parents namespace, defined as xmlns="http://uri.etsi.org/01903/v1.3.2#".
This was, because i did never "register" it as a namespace, but i only added it as a normal Attribute.
To "register" the namespace i need to call setAttributeNS instead of setAttribute.
The code then looks something like:
Element eQualifyingProperties= doc.createElement("QualifyingProperties");
eQualifyingProperties.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "http://uri.etsi.org/01903/v1.3.2#");
The first parameter is the namespace-uri of the Attribute and since the Attribute is a namespace it is the URI of the XML-Namespaces.
The second parameter is the attribute-name, since it should not have any praefix it is simply "xmlns".
The third parameter is the actual attibute-value, which is the namespace-uri i want to "register".
The Element eQualifyingProperties is the parent of the "SignedProperties" Element.
After registering the namespace as a real namespace (not as an attribute), the defined Transform
Transform sigPropTransform = fac.newTransform(CanonicalizationMethod.EXCLUSIVE, (ExcC14NParameterSpec)null);
includes it in the digest calculation.
I found this solution in this answer on SO.

Java DOM XML Parser with chaning namespaces

I do REST calls to a WebService and receive always XML as response. Then i'm parsing that XML und filling Java objects with those informations.
The Problem is that the element-tags could have different namespaces, like this:
<ns:title>....</ns:title>
or
<ns2:title>....<ns2:title>
or
<title>...<title>
EDIT:
And the namespace URIs look like this:
<ns2:feed xmlns="http://www.example.com/routing1/routing2"
xmlns:ns2="http://www.w3.org/../Atom"
xmlns:ns3="http://www.example.com/routing1/routing2"
xmlns:ns4="http://purl.org/routing1/routing2/1.0">
So therefore i changed the method element.getElementsByTagNameNS("specifiedNamespace", "title") to element.getElementsByTagNameNS("*", "title").
Is that okay to match all namespace, because i have also the case that the element-tag doesn't have a namespace like the third example <title>..</title>..
Is there a better procedure, to solve that problem? Or is it okay to solve it like, how i do it?
Thanks.
EDIT: 2 response examples
1.
<ns2:feed xmlns="http://www.example.com/routing1/routing2" xmlns:ns2="http://www.w3.org/../Atom" xmlns:ns3="http://www.example.com/routing1/routing2" xmlns:ns4="http://purl.org/routing1/routing2/1.0">
...
<ns2:someTag1>..</ns2:someTag1>
<ns2:title>title</ns2:title>
<entry>...</entry>
....
</ns2:feed>
2
<ns2:feed xmlns="http://www.w3.org/../Atom" xmlns:ns2="http://www.example.com/routing1/routing2" xmlns:ns3="http://www.example.com/routing1/routing2" xmlns:ns4="http://purl.org/routing1/routing2/1.0">
...
<someTag1>..<someTag1>
<title>title<title>
<ns2:entry>...</ns2:entry>
....
</ns2:feed>
Your title elements have the same namespace in both of your examples.
In the first example, you have:
xmlns:ns2="http://www.w3.org/../Atom"
and
<ns2:title>title</ns2:title>
so this means that title is in the http://www.w3.org/../Atom namespace.
In the second example, you have:
xmlns="http://www.w3.org/../Atom"
and
<title>title<title>
so here again title is in the http://www.w3.org/../Atom namespace.
The prefixes are different (the second example isn't using a prefix for title), but the namespace is the same.
This means that you should be able to use:
element.getElementsByTagNameNS("http://www.w3.org/../Atom", "title")
and it should successfully select the title element, even if the prefixes change.

Exception while creating custom object using Salesforce CRUD Metadata API

I am getting the following exception when I try to create a Custom Object in Salesforce, using CRUD Matadata API.
com.sforce.ws.SoapFaultException: Must specify a {http://www.w3.org/2001/XMLSchema-instance}
type attribute value for the {http://soap.sforce.com/2006/04/metadata}metadata element
at com.sforce.ws.transport.SoapConnection.createException(SoapConnection.java:205)
at com.sforce.ws.transport.SoapConnection.receive(SoapConnection.java:149)
at com.sforce.ws.transport.SoapConnection.send(SoapConnection.java:98)
at com.sforce.soap.metadata.MetadataConnection.create(MetadataConnection.java:273)
at com.sfo.service.SalesforceObjectBootstrap.createCustomObject(SalesforceObjectBootstrap.java:226)
I am using the code from this link, The only thing that I changed were the name of the Custom Object
http://www.salesforce.com/us/developer/docs/api_meta/Content/meta_calls_intro.htm
The exception occurs at this step
AsyncResult[] asyncResults = metadataConnection.create(new CustomObject[]{customObject});
The Custom object just before invoking the create method above has the following parameter values.
[CustomObject [Metadata fullName='lead_5273_custom_reg__c'
]
actionOverrides='{[0]}'
articleTypeChannelDisplay='null'
businessProcesses='{[0]}'
customHelp='hey there help me'
customHelpPage='null'
customSettingsType='null'
customSettingsVisibility='null'
deploymentStatus='Deployed'
deprecated='false'
description='Created from backend Webcast API : Lead 5273 Custom Reg'
enableActivities='false'
enableDivisions='false'
enableEnhancedLookup='false'
enableFeeds='false'
enableHistory='false'
enableReports='false'
fieldSets='{[0]}'
fields='{[0]}'
gender='null'
household='false'
label='Lead 5273 Custom Reg'
listViews='{[0]}'
nameField='[CustomField [Metadata fullName='lead_5273_custom_reg__c'
]
caseSensitive='false'
customDataType='null'
defaultValue='null'
deleteConstraint='null'
deprecated='false'
description='field name for a metadata custom object'
displayFormat='null'
escapeMarkup='false'
externalDeveloperName='null'
externalId='false'
formula='null'
formulaTreatBlanksAs='null'
inlineHelpText='null'
label='Lead 5273 Custom Reg'
length='0'
maskChar='null'
maskType='null'
picklist='null'
populateExistingRows='false'
precision='0'
referenceTo='null'
relationshipLabel='null'
relationshipName='null'
relationshipOrder='0'
reparentableMasterDetail='false'
required='false'
restrictedAdminField='false'
scale='0'
startingNumber='0'
stripMarkup='false'
summarizedField='null'
summaryFilterItems='{[0]}'
summaryForeignKey='null'
summaryOperation='null'
trackFeedHistory='false'
trackHistory='false'
type='Text'
unique='false'
visibleLines='0'
writeRequiresMasterRead='false'
]
'
namedFilters='{[0]}'
pluralLabel='Lead 5273 Custom Regs'
recordTypeTrackFeedHistory='false'
recordTypeTrackHistory='false'
recordTypes='{[0]}'
searchLayouts='null'
sharingModel='ReadWrite'
sharingReasons='{[0]}'
sharingRecalculations='{[0]}'
startsWith='null'
validationRules='{[0]}'
webLinks='{[0]}'
]
I used the method mentioned here to generate the WSDL files and its java skeleton.
http://www.salesforce.com/us/developer/docs/api_meta/Content/meta_quickstart.htm#topic-title-sample-code
My code exactly matches the example provided above. I simply copy pasted the whole thing.
I found this link, which mentioned the same exception. But this link is relating to creating a Folder.
http://boards.developerforce.com/t5/Java-Development/Metadata-API-errors-Must-specify-a-type-attribute-value-for-the/td-p/175253
Please let me know how to solve this problem.
I've not played with this myself, but from the looks of the exception, the MetaData block here:
[CustomObject [Metadata fullName='lead_5273_custom_reg__c']
needs to contain the object type, which I'm assuming in this case is CustomObject__c (all custom objects have the __c suffix), so maybe try the following:
[CustomObject [Metadata fullName='lead_5273_custom_reg__c' type='CustomObject__c']
Unless of course, fullname is actually the object name, which could be a possibility.

Categories