XML Signature Reference digest uses parent namespace - java

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.

Related

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

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.

C_FindObjectsInit(..) from PKCS11 class exception

To sign data, I am using signserver open-source code. I was exploring a legacy code where
it gives error at this place:
Module.getPKCS11Module().C_FindObjectsInit(session.getSessionHandle(), attributes,true);
where the Module class is from iaikpkcs11Wrapper.jar (package: iaik.pkcs.pkcs11)
As I navigate further, PKCS11 interface has this method void C_FindObjectsInit(long var1, CK_ATTRIBUTE[] var3, boolean var4) mentioned above.
Moreover, the attributes param is constructed like below:
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTEKeyStoreContainerBase[2];
attributes[0] = new CK_ATTRIBUTE();
attributes[0].type = PKCS11Constants.CKA_CLASS;
attributes[0].pValue = new Long(PKCS11Constants.CKO_SECRET_KEY);
attributes[1] = new CK_ATTRIBUTE();
attributes[1].type = PKCS11Constants.CKA_ID;
attributes[1].pValue = id; //id is byteArray. For this param's value the error is causing
My question is, do I need to store any kind of key/certificate from where C_FindObjectsInit(..) will read or match as it says that it couldn't find any key? Where does this method search the key or how to resolve this issue?
Btw, I have read C_FindObjectsInit-JavaDoc and couldn't understand this line properly, that's why I am here:
pTemplate - the object's attribute values to match and the number of
attributes in search template (PKCS#11 param: CK_ATTRIBUTE_PTR
pTemplate, CK_ULONG ulCount)
[this may sound peculiar question, but I am really blank and stuck for few days]
PKCS#11 specification don't force us to use some strictly composed data.
But in most implementations I saw it was binary encoded OID field.
Also check for 0 (null) bytes in sequence.

Add extension to CertificateRequestMessage

I'm trying to put a custom element (a template name to use for the PKI) in my Certificate request that I generate using bouncycastle library.
The RFC says that you can use an extension that follows :
id-regInfo-utf8Pairs OBJECT IDENTIFIER ::= { id-regInfo 1 }
--with syntax UTF8Pairs ::= UTF8String
The few lines of code concerning this are
CertificateRequestMessageBuilder msgbuilder = new
CertificateRequestMessageBuilder(BigInteger.valueOf(reqId));
msgbuilder.addExtension(new ASN1ObjectIdentifier("1.3.6.1.5.5.7.7.5.2.1"), false, ???);
I can't find any information on what to put in that addExtension function, nor any example to adapt from.
I guess the new ASN1ObjectIdentifier("1.3.6.1.5.5.7.7.5.2.1") is close to what is expected, but the following ASN1Encodable that is supposed to be the value of that field is a mystery to me.
I just want to get something along template:encipherment in that field.
This seems like a pretty simple thing to do but the lack of documentation coupled to my lack of experience with BouncyCastle causes me a lot of problems.
The questions are :
Am I doing what I want the correct way ? (Using the extensions of the CRMF to convey my custom field)
If I do, how do I make this work ?

Selenium/ Java how to verify the this complex text on page

I want to verify below text(HTML code) is present on page which as // characters , etc using selenium /jav
<div class="powatag" data-endpoint="https://api-sb2.powatag.com" data-key="b3JvYmlhbmNvdGVzdDErYXBpOjEyMzQ1Njc4" data-sku="519" data-lang="en_GB" data-type="bag" data-style="bg-act-left" data-colorscheme="light" data-redirect=""></div>
Appreciate any help on this
I believe you're looking for:
String textToVerify = "some html";
boolean bFoundText = driver.getPageSource.contains(textToVerify)
Assert.assertTrue(bFoundText);
Note, this checks the page source of the last loaded page as detailed here in the javadoc. I've found this to also take longer to execute, especially when dealing with large source codes. As such, this method is more prone to failure than validating the attributes and values and the answer from Breaks Software is what I utilize when possible, only with an xpath selector
As Andreas commented, you probably want to verify individual attributes of the div element. since you specifically mentioned the "//", I'm guessing that you are having trouble with the data-endpoint attribute. I'm assuming that your data-sku attribute will bring you to a unique element, so Try something like this (not verified):
String endpoint = driver.findElement(
new By.ByCssSelector("div[data-sku='519']")).getAttribute("data-endpoint");
assertTrue("https://api-sb2.powatag.com", endpoint);

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.

Categories