Hi Jerome,
If I understand correctly, you want to create a hash value for the string serialization of the document you sent to restxq right?
Currently inside RESTXQ your document is treated as an XML Document, hence:
$body will be of type document-node():
<data> <foo>Hello</foo> <bar>World</bar> </data>
where as crypto:hmac requires a string-type $message:
crypto:hmac($message as xs:string,
Hence your $body will be converted like so:
string(
<data> <foo>Hello</foo> <bar>World</bar> </data> )
Turning it into:
„HelloWorld“
In order to actually compute a hash on the bytes your document contains, do as follows:
Working example here: https://git.basex.io/snippets/63
Treat your document as binary:
%rest:consumes("application/octet-stream“)
And then decode that binary to a string and then compute the hash for the string, using: bin:decode-string#2:
let $str-doc := bin:decode-string($body,'utf-8') (: xs:string :) let $sig-cand := crypto:hmac($str-doc,$secret,'sha1','base64')
Hope this helps :-)
Michael
Am 03.06.2019 um 12:17 schrieb Jerome Chauveau jerome.chauveau@unicaen.fr:
Hi,
I am trying to check XML content (HTTP posted) with an hmac function in a RESTXQ webapp.
My Java client sends an HTTP post request where XML data looks like :
<data><user>doe</user><content><TEI xsi:schemaLocation="http://www.tei-c.org/ns/1.0" xml:id="idtest"
<teiHeader <fileDesc <titleStmt
<title Test</title <author
xml:id="authortest"
XXX</author </titleStmt </teiHeader <text <front </front
<body
xml:space="preserve"
<listPlace <place
type="lieu"
<placeName
xml:lang="la"
Burgunvilla</placeName </place </listPlace
</body </text </TEI </content></data>
This content is HMAC encrypted and the signature is added to the HTTP header :
[...] String secret = "1234"; StringEntity entity = new StringEntity(xml, ContentType.create("text/xml", Consts.UTF_8)); String signature = HTTPUtils.hmacSHA1(xml, secret); httppost.setHeader("Authorization", signature); httppost.setEntity(entity); [...]
Here is my RESTXQ function :
declare %rest:POST("{$body}") %rest:consumes("application/xml", "text/xml") %rest:header-param("Authorization", "{$signature}", "none") %rest:path("/sf/testpost") function sf.test:testPost($signature,$body){ let $secret := 1234 crypto:hmac($body,$secret,'sha1','base64') = $signature }
Equality check always fails with such an XML sequence but works fine when XML does not contain any carriage return : <data><user>doe</user><content><TEI><front></front><text><body>This is a test</body></text></TEI>
It seems to come when "The body of a POST or PUT request is converted to an XQuery item".
I tried to set serializer's options without any success !
How could I retrieve xml (in $body) exactly serialized as sent by the client ?
Tests are running on BaseX922. Thank you for your time.
Jérôme