Copy link to clipboard
Copied
I performed a test comparing the Admin Console API inspector to the PHP serialization class.
When using the exact same request when testing, two different <hmac> values are generated.
Below I'm requesting resources available for a specific distributor uuid.
The call is made to /admin/ManageResourceItem using builtin auth.
Request generated in Admin Console API Inspector, ported directly into PHP:
$request = '<request action="get" auth="builtin" xmlns="http://ns.adobe.com/adept">';
$request .= '<nonce>nf55dgAAAAk=</nonce>';
$request .= '<expiration>2011-01-19T11:47:36-00:00</expiration>';
$request .= '<distributor>urn:uuid:62dbe983-b28b-4910-9a44-c5f55bf152dd</distributor>';
$request .= '<limit><start>0</start><count>24</count></limit>';
$request .= '<hmac>UDH0SOSRlAq3s7Y+haHOFhd7jWU=</hmac>';
$request .= '</request>';
This hardcoded request passed to web service, works 100% and in response I get the proper XML data.
Next remove the <hmac> and provide the $request below to XMLSigningSerializer in PHP:
<request action="get" auth="builtin" xmlns="http://ns.adobe.com/adept">
<nonce>nf55dgAAAAk=</nonce>
<expiration>2011-01-19T11:47:36-00:00</expiration>
<distributor>urn:uuid:62dbe983-b28b-4910-9a44-c5f55bf152dd</distributor>
<limit><start>0</start><count>24</count></limit>
</request>
$xmlObjectPackage = new DOMDocument('1.0', 'UTF-8');
$xmlObjectPackage->formatOutput = true;
$xmlObjectPackage->loadXML($request);
$packageNodes = $xmlObjectPackage->getElementsByTagName('request');
foreach ($packageNodes as $packageNode){
signNode($xmlObjectPackage,$packageNode,$serverPassword);}
The <hmac> element is inserted into the DOM and the signed $request is returned as:
<request action="get" auth="builtin" xmlns="http://ns.adobe.com/adept">
<nonce>nf55dgAAAAk=</nonce>
<expiration>2011-01-19T11:47:36-00:00</expiration>
<distributor>urn:uuid:62dbe983-b28b-4910-9a44-c5f55bf152dd</distributor>
<limit><start>0</start><count>24</count></limit>
<hmac>Hc/jN53W65d3r6EdzGGj9lJ3BtE=</hmac>
</request>
All elements identical, then signed produces:
Admin console : <hmac>UDH0SOSRlAq3s7Y+haHOFhd7jWU=</hmac>
PHP Class : <hmac>Hc/jN53W65d3r6EdzGGj9lJ3BtE=</hmac>
<hmac> produced by the PHP class is not correct and returns: E_ADEPT_DISTRIBUTOR_AUTH
I used the PHP file from the snippets folder as suggested.
Has this file been revised since its original deployment with the ACS4 distribution? Please let me know if a corrected file is available?
Or have I done something wrong during the serialization process?
Thanks in advance
- Anthony
Copy link to clipboard
Copied
Did you check that you are using the correct key, and that you are sending the key into the HMAC appropriately?
The key sent to the HMAC (since you are using "builtin" ) should be the results of a SHA1 hash of the password (that you use in the admin console).
Also you must make sure (and this can be tricky in PHP), that the results of the SHA1 hash is kept in binary form.
Copy link to clipboard
Copied
Hi Jim
Thanks for your response. I'm sure that I'm using the correct key sent to the HMAC.
raw_output is set to TRUE, and 'sha1' is used on the PHP hash() function:
Where $password is the same password used to log into the admin console.
$serverPassword = hash('sha1', $password, TRUE);
Later in the code when signing of the request is done, it is passed to the HMAC like so:
signNode($xmlObjectPackage,$packageNode,$serverPassword);
Further than this, the only place where inconsistency could change the HMAC output has to be within the serialization function itself.
This is why I asked if an updated class file might have been released?
My file details:
XMLSigningSerializer.php
Modified: 12 November 2010.
Size: 7.93 KB
Looking forward to hearing from you.
Thanks
- Anthony
Copy link to clipboard
Copied
I've used the code from this thread to use the XMLSigningSerializer.php script to generate an hmac
Using a responce fro the server I've removed the hmac passed it through the script but the hmac comes up wrong. I've used both the server password and the shared secret to sign the responce but both give me an incorrect hmac.
Can you shed some light on why this is?
Copy link to clipboard
Copied
I am experiencing the same issue. I'm going to start going through XMLSigningSerializer.php line by line and comparing with UploadTest, which I have no doubt y'all have already done, but if anyone has found a solution for this, please post here asap!
Many thanks!
-Julie
Texas
Copy link to clipboard
Copied
Also, I'm not sure if this helps, but here is the debug data for the XML serializer when it's run over the follow XML:
<request action="get" auth="builtin" xmlns="http://ns.adobe.com/adept">
<nonce>KXRwPwAAAAY=</nonce>
<expiration>2011-07-14T16:52:02-00:00</expiration>
<distributorData/>
<limit>
<start>0</start>
<count>24</count>
</limit>
</request>
Like the others, this XML was taken directly from the admin console and the hmac has been removed.
Starting Serialization
Serializing Element: request
Getting name for request namespaceURI -http://ns.adobe.com/adept- prefix -- localName -request- baseURI -file:///C:/wamp/www/acs4/test/-
outString | http://ns.adobe.com/adept| length = 27 byte1 = 0 byte2 = 25 | 25
outString | request| length = 9 byte1 = 0 byte2 = 7 | 7
Serializing Attributes for request
Serializing attribute - action - get
Getting name for action namespaceURI -- prefix -- localName -action- baseURI -file:///C:/wamp/www/acs4/test/-
outString || length = 2 byte1 = 0 byte2 = 0 | 0
outString | action| length = 8 byte1 = 0 byte2 = 6 | 6
outString | get| length = 5 byte1 = 0 byte2 = 3 | 3
Serializing attribute - auth - builtin
Getting name for auth namespaceURI -- prefix -- localName -auth- baseURI -file:///C:/wamp/www/acs4/test/-
outString || length = 2 byte1 = 0 byte2 = 0 | 0
outString | auth| length = 6 byte1 = 0 byte2 = 4 | 4
outString | builtin| length = 9 byte1 = 0 byte2 = 7 | 7
Finished Serializing Attributes: - action get auth builtin -
Inspecting child node #text with Type: 3
Inspecting child node nonce with Type: 1
Serializing Element: nonce
Getting name for nonce namespaceURI -http://ns.adobe.com/adept- prefix -- localName -nonce- baseURI -file:///C:/wamp/www/acs4/test/-
outString | http://ns.adobe.com/adept| length = 27 byte1 = 0 byte2 = 25 | 25
outString | nonce| length = 7 byte1 = 0 byte2 = 5 | 5
Serializing Attributes for nonce
Finished Serializing Attributes: - -
Inspecting child node #text with Type: 3
Node Value for nonce is: KXRwPwAAAAY=
outString | KXRwPwAAAAY=| length = 14 byte1 = 0 byte2 = 12 | 12
Done Serializing Element nonce - serialization: http://ns.adobe.com/adept nonce KXRwPwAAAAY=
Inspecting child node #text with Type: 3
Inspecting child node expiration with Type: 1
Serializing Element: expiration
Getting name for expiration namespaceURI -http://ns.adobe.com/adept- prefix -- localName -expiration- baseURI -file:///C:/wamp/www/acs4/test/-
outString | http://ns.adobe.com/adept| length = 27 byte1 = 0 byte2 = 25 | 25
outString | expiration| length = 12 byte1 = 0 byte2 = 10 | 10
Serializing Attributes for expiration
Finished Serializing Attributes: - -
Inspecting child node #text with Type: 3
Node Value for expiration is: 2011-07-14T16:52:02-00:00
outString | 2011-07-14T16:52:02-00:00| length = 27 byte1 = 0 byte2 = 25 | 25
Done Serializing Element expiration - serialization: http://ns.adobe.com/adept expiration 2011-07-14T16:52:02-00:00
Inspecting child node #text with Type: 3
Inspecting child node distributorData with Type: 1
Serializing Element: distributorData
Getting name for distributorData namespaceURI -http://ns.adobe.com/adept- prefix -- localName -distributorData- baseURI -file:///C:/wamp/www/acs4/test/-
outString | http://ns.adobe.com/adept| length = 27 byte1 = 0 byte2 = 25 | 25
outString | distributorData| length = 17 byte1 = 0 byte2 = 15 | 15
Serializing Attributes for distributorData
Finished Serializing Attributes: - -
Done Serializing Element distributorData - serialization: http://ns.adobe.com/adept distributorData
Inspecting child node #text with Type: 3
Inspecting child node limit with Type: 1
Serializing Element: limit
Getting name for limit namespaceURI -http://ns.adobe.com/adept- prefix -- localName -limit- baseURI -file:///C:/wamp/www/acs4/test/-
outString | http://ns.adobe.com/adept| length = 27 byte1 = 0 byte2 = 25 | 25
outString | limit| length = 7 byte1 = 0 byte2 = 5 | 5
Serializing Attributes for limit
Finished Serializing Attributes: - -
Inspecting child node #text with Type: 3
Inspecting child node start with Type: 1
Serializing Element: start
Getting name for start namespaceURI -http://ns.adobe.com/adept- prefix -- localName -start- baseURI -file:///C:/wamp/www/acs4/test/-
outString | http://ns.adobe.com/adept| length = 27 byte1 = 0 byte2 = 25 | 25
outString | start| length = 7 byte1 = 0 byte2 = 5 | 5
Serializing Attributes for start
Finished Serializing Attributes: - -
Inspecting child node #text with Type: 3
Node Value for start is: 0
outString | 0| length = 3 byte1 = 0 byte2 = 1 | 1
Done Serializing Element start - serialization: http://ns.adobe.com/adept start 0
Inspecting child node #text with Type: 3
Inspecting child node count with Type: 1
Serializing Element: count
Getting name for count namespaceURI -http://ns.adobe.com/adept- prefix -- localName -count- baseURI -file:///C:/wamp/www/acs4/test/-
outString | http://ns.adobe.com/adept| length = 27 byte1 = 0 byte2 = 25 | 25
outString | count| length = 7 byte1 = 0 byte2 = 5 | 5
Serializing Attributes for count
Finished Serializing Attributes: - -
Inspecting child node #text with Type: 3
Node Value for count is: 24
outString | 24| length = 4 byte1 = 0 byte2 = 2 | 2
Done Serializing Element count - serialization: http://ns.adobe.com/adept count 24
Inspecting child node #text with Type: 3
Done Serializing Element limit - serialization: http://ns.adobe.com/adept limit http://ns.adobe.com/adept start 0 http://ns.adobe.com/adept count 24
Inspecting child node #text with Type: 3
Done Serializing Element request - serialization: http://ns.adobe.com/adept request action get auth builtin http://ns.adobe.com/adept nonce KXRwPwAAAAY= http://ns.adobe.com/adept expiration 2011-07-14T16:52:02-00:00 http://ns.adobe.com/adept distributorData http://ns.adobe.com/adept limit http://ns.adobe.com/adept start 0 http://ns.adobe.com/adept count 24
Finished Serialization
Copy link to clipboard
Copied
So I got a solution that work with PHP code, but only via a custom made .jar file.
What I did was take the UploadTest.java document, create my own java project using Eclipse using the source files provided by Adobe, then pared it down so that all it does is take in XML via the command line and return the HMAC using the XMLUtil.java resources. This has worked like a charm for us and our PHP code communicates with it via exec().
Copy link to clipboard
Copied
We ended up doing the same thing. I've been waiting for approval from management to relase the code and jar, I'm unsure if I willl get it.
Copy link to clipboard
Copied
I originally started this thread on Jan 19 2011, it has been over 6 months, and not a word of technical feedback from Adobe.
Jim Lester (no longer with Adobe) was the most helpful with his forum responses, initial troubleshooting, and assistance in testing and discovery of the HMAC signing differences. The PHP Serialization class is clearly non-functional with no alternative than to use the sample java tools or to develop outside of PHP.
I currently package our ebooks using the java sample uploader, logging ACS responses to a log file through a batch script.
We manage the distributors with the feature-lacking ACS admin console, and export the distributor catalogues by copying and pasting from the admin console debug window to obtain a proper HMAC signed XML request. When running a sample store export, obtaining the signed request, into a PHP scripted variable that executes a cURL call to ACS, saving the catalog.xml file for later use.
Why do I do it this way? Because the admin console times out on any catalogue with a filesize above a few megabytes.
At least using PHP I can control the timeout issues and retrieve the data.
This has at least given some semblance of a PHP scripted interface to manage the process partially.
Creating a java wrapper to interact with PHP using exec() is viable but not the way to go.
To create solutions that can be run as standard web service calls from within a hosted environment, we should not need to combine 2 languages.
As Content Server support is no longer being provided by Adobe, I have moved my support query to Data Logics who have been helpful with providing other answers in the past. I am hoping their technical team will be able to obtain answers through a more direct channel.
There has also been a notable growth in the request to have this sorted out if i check the view count on this thread and the few orphan threads appearing with similar support requests. We need answers. We need solutions. We need PHP based auth signing that works so that we can automate what is currently a very tedious workaround process.
Copy link to clipboard
Copied
Expecting a reply from Adobe is simply naive, as is any attempt to reimplement the braindead signing in anything other than the one-true-language. The "algorithm" has been intentionally made so that any attempt to reimplement it is bound to fail.
No. Really. The adobistas expect everyone to learn their preferred language just to be able to upload a file into their beloved, overpriced and undersupported crap. Or ... horrors ... even to assign it to other than the default distributor.
Copy link to clipboard
Copied
It has been almost 5 months since the last post on this thread. Has anyone found a solution?
I have done some digging in the code (looking at the Java code and comparing to the PHP code). There are differences, but I could not find the reason for the PHP serialization to fail.
So far I have identified (for the code in snippets-2010_11_12.zip)
a) The call to usort, to sort the attributes is wrong and generates a warning. The name of the comparison function (second parameter) must be a string, so " " must be added around it. On most cases there are not too many attributes and it will be a problem only if they are not "in order". Exemple: auth and action in a "request".
b) When dealing with 0-length strings, the serialized representation is 0x0000. The code has a $NodeId prefixing the 0x0000 (char(0).char(0)). Here the default PHP action is to the $NodeId to an empty string that is fine.
But those alone are not the reason for the wrong HMAC.
I have manually checked the serialized output and it seems to be correct, at least to the written specs.
Anyone with the "java" serializer, please send me a copy (source??) I plan to dump the serialized representation and compare with the PHP one.
I will also look in reports that it fails for large strings that are broken into pieces. If I can make it work, I will create a fully funcional example and library, with code improvements (there are some really bad PHP code there) and support code.
Copy link to clipboard
Copied
Hello, I am new in ACS and in this comunity. I need ASC 4 for my job. I'm trying to update ebook but I don't get it. I need help please!!
I use this xml code for the update, where XXX is the correct data:
<request xmlns="http://ns.adobe.com/adept" action="update" auth="builtin">
<nonce>XXXXXXXX</nonce>
<expiration>XXXXXXXX</expiration>
<resourceItemInfo>
<resource>XXXXXXXX</resource>
<resourceItem>X</resourceItem>
<metadata>
<title xmlns="http://purl.org/dc/elements/1.1">XXXXX</title>
<creator xmlns="http://purl.org/dc/elements/1.1">XXXXX</creator>
<description xmlns="http://purl.org/dc/elements/1.1">XXXXXX</description>
<languaje xmlns="http://purl.org/dc/elements/1.1">XX</languaje>
<publisher xmlns="http://purl.org/dc/elements/1.1">XXXXXXX</publisher>
</metadata>
</resourceItemInfo>
<hmac>XXXXXX=</hmac>
</request>
but the server responds me this:
<error xmlns="http://ns.adobe.com/adept" data="E_ADEPT_INTERNAL XXXXXXXX/admin/ManageResourceItem null"/>
Anybody knows because the server return this?? And is possible update a packaging ebook??
Thanks in advance
Copy link to clipboard
Copied
Hello,
You can't update metadata! If you want update it, you may
repackaging the book.
Regards
Copy link to clipboard
Copied
Ok, thanks for you reply.
You have been a great help
Copy link to clipboard
Copied
Hi, I have the exact problem as Anthony.
I have downloaded ADBE_ContentServer4_1.zip from store1.adobe.com, inside snippets-2010_11_12.zip
there was this library XMLSigningSerializer.php
I have copied a simple request from /admin/console, something like this:
<request action="get" auth="builtin" xmlns="http://ns.adobe.com/adept">
<nonce>VzNBhgAAAAM=</nonce>
<expiration>2011-02-24T10:55:00-00:00</expiration>
<limit>
<start>0</start>
<count>24</count>
</limit>
<hmac>cQC4fYnJ0dxI/56luJpBW4WEW0c=</hmac>
</request>
Sending this request programmatically though Php/Curl to /packaging/Package works just fine.
If I remove the <hmac> tag and I use XMLSigningSerializer to attach the HMAC,
the request doesn't work anymore and the HMAC created by XMLSigningSerializer is different that the
one found in the original request from above.
The error in this case is:
<error xmlns="http://ns.adobe.com/adept" data="E_ADEPT_DISTRIBUTOR_AUTH http://server:8080/admin/ManageResourceItem urn:uuid:00000000-0000-0000-0000-000000000001"/>
The questions are:
- should i use a different version of XMLSigningSerializer.php ?
Other than the one from snippets-2010_11_12.zip
- do you have a fully working example in PHP for packaging or sending other requests ?
- if I send you the PHP code, will you be able to indicate the errors ?
Copy link to clipboard
Copied
Hi Radu
I am so glad to see another person was able to corroborate my findings. Adobe has not been forthcoming with an answer to this issue.
Adobe have suggested faults in user implementation of the code, such as improper handling of binary safe data, or not passing a proper base64_encoded signature. Critique is perfectly welcome from the Adobe team, and for the most part the forums have assisted me with other minor issues in this way.
However, I would appreciate if a proper demonstration of the sample code is provided.
It would take the lead developer who wrote that class 5 minutes to write this up and post a reply.
Merely suggesting we are doing it wrong - and having us recheck code, does not help anyone move forward.
Perhaps once enough people begin to ask for this, the ACS4 support team will sit up and take notice?
A PHP example is required that actually makes use of the XMLSigningSerializer.php class to sign an XML request and input the <hmac> node.
This to me will prove that the class is functional and we are at fault - also exposing the exact problem in our code, and resolving the issue...
Anyone willing to stand up and take the lead on helping us out over there at Adobe?
Copy link to clipboard
Copied
Hello Anthony, Jim ...
Here is my code that generates an incorrent HMAC:
Jim, it would help us immensely if you could spot the errors in the code.
The XMLSigningSerializer.php was found in snippets-2010_11_12.zip
<?php
require_once 'XMLSigningSerializer.php';
$password = "password";
$serviceUrl = 'http://server:8080/admin/ManageResourceItem';
function signNode( $xmlDoc, $xmlNodeToBeSigned, $secretKey )
{
$ADEPT_NS = 'http://ns.adobe.com/adept';
$serializer = new XMLSigningSerializer( false );
$signingSerialization = $serializer->serialize($xmlNodeToBeSigned);
$hmacData = base64_encode( hash_hmac("sha1", $signingSerialization, $secretKey, true ) );
$hmacNode = $xmlDoc->createElementNS($ADEPT_NS, "hmac", $hmacData );
$xmlNodeToBeSigned->appendChild( $hmacNode );
}
function sendRequest($requestData, $requestURL)
{
$c = curl_init($requestURL);
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
curl_setopt($c, CURLOPT_POST, true);
curl_setopt($c, CURLOPT_POSTFIELDS, $requestData);
curl_setopt($c, CURLOPT_HTTPHEADER, array('Content-type: application/vnd.adobe.adept+xml'));
$html = curl_exec($c);
curl_close($c);
return $html;
}
function request($password) {
$serverPassword = hash("sha1", $password, true);
$request = <<<DOC
<request action="get" auth="builtin" xmlns="http://ns.adobe.com/adept">
<nonce>i03+cQAAAAw=</nonce>
<expiration>2011-03-06T13:44:27-00:00</expiration>
<limit>
<start>0</start>
<count>24</count>
</limit>
</request>
DOC;
/*
* I took the above request from /admin/console
* I have removed the following tag: <hmac>6D4gRi6NF5F0uD4jSOLixNhGbTU=</hmac>
*/
$xmlObjectPackage = new DOMDocument('1.0', 'UTF-8');
$xmlObjectPackage->formatOutput = true;
$xmlObjectPackage->loadXML($request);
$packageNodes = $xmlObjectPackage->getElementsByTagName('request');
foreach ($packageNodes as $packageNode) {
signNode( $xmlObjectPackage, $packageNode, $serverPassword );
}
return $xmlObjectPackage;
}
$xmlObjectPackage = request($password);
print $xmlObjectPackage->saveXML();
die();
/*
* The request looks like this, notice how <hmac> is different:
<?xml version="1.0"?>
<request xmlns="http://ns.adobe.com/adept" action="get" auth="builtin">
<nonce>i03+cQAAAAw=</nonce>
<expiration>2011-03-06T13:44:27-00:00</expiration>
<limit>
<start>0</start>
<count>24</count>
</limit>
<hmac>T0kdAb//TbkcrtaipLh3ko+ySv4=</hmac></request>
*/
#$response = sendRequest($xmlObjectPackage->saveXML(), $serviceUrl);
#print $response;
Copy link to clipboard
Copied
I'm seeing the same thing. Were you able to find a solution? or an updated XMLSigningSerializer.php?
I've also noticed a PHP notice being thrown from the provided file:
PHP Notice: Undefined variable: nodeId in /home/user/hmac/inc/XMLSigningSerializer.php on line 61