Hi Michael,

It seems to work ... perfectly !

Thank you so much for that clear and quick answer :-)

Jérôme





De: "Michael Seiferle" <ms@basex.org>
À: "jerome chauveau" <jerome.chauveau@unicaen.fr>
Cc: "basex-talk" <basex-talk@mailman.uni-konstanz.de>
Envoyé: Lundi 3 Juin 2019 16:39:07
Objet: Re: [basex-talk] XML in HTTP request body

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