Bernd wrote:
> Hey everyone!
>
> I'm currently working on my BA thesis, writing a webservice using the
> official SOAP extension of PHP 5. This is kind of the first time I use
> SOAP, so this stuff is still quite new to me. Today I realised in
> horror that the service provider expects me to use ws-security
> headers. Obviously the SOAP extension does not support wss headers, so
> I'm a litte lost right now. There seems to be some kind of alternative
> SOAP framework for PHP that supports wss, but I already implemented
> most of my application using PHP:SOAP.
>
> So is there any way to "extend" the official SOAP extension to support
> wss? There's not much information on xmlseclibs' Google page, but I
> dim this lib could help me. Is this correct or am I mistaken?
> Unfortunately I could not find any documentation or examples on how to
> use this piece of code.
>
> Eventually my SOAP header should look like this (I stripped some IDs
> and signatures, cuz I think they might be confidential):
>
>
>
I really need to get around to updating the info page with some of this
stuff.
You can find the related WS-* code and some examples here:
http://cdatazone.org/index.php?/pages/source.html
Let me know if you have any problems.
Rob
For the public cert, you can do the following and pipe it to a file:
keytool -alias {asliasname} -export -rfc
PRIVATE_KEY should be the file containing the private key. Unfortunately
keytool doesn't provide a way to export the private key, so you have to
get at it programatically. something like the following:
example code which output is put into file {pkey}
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("keystorefile"), "password".toCharArray());
Key key = ks.getKey("alais", "password".toCharArray());
System.out.write(key.getEncoded())
openssl enc -in {pkey} -a
The private key file would contain:
-----BEGIN PRIVATE KEY-----
{openssl output}
-----END PRIVATE KEY-----
Hope that helps.
Rob
<snip />
>
> The key seems to be okay, even though it's called RSA PRIVATE KEY, not
> PRIVATE KEY as you assumed. Is this a problem or will a RSA key work
> as well?
>
Sorry, typo on my side. That code was from the top of my head and I was
thinking about the constant I use within the xmlseclibs library.
> In your wss example you don't use a passphrase, so I checked lines
> 311-315 in xmlseclibs.php. The passphrase is just mentioned twice in
> the whole script (member declaration and line 314) und is never set
> (correct me, if I am mistaken). Possibly this is a bug or can I set
> the password via cryptParams (guess not)?
>
You can set the passphrase on the XMLSecurityKey object prior to loading
the private key.
For example, based on me WS-* Amazon example:
http://www.cdatazone.org/files/ws-amazon.phps
/* create new XMLSec Key using RSA SHA-1 and type is private key */
$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1,
array('type'=>'private'));
$objKey->passphrase = {passphrase};
/* load the private key from file - last arg is bool if key in file
(TRUE) or is string (FALSE) */
$objKey->loadKey(PRIVATE_KEY, TRUE);
> Anyway, I replaced $this->passphrase with a string containing my
> password for testing purposes and the warning disappeared.
> Unfortunately there still wasn't a signature added to my SOAP header.
> Is this due to my RSA PRIVATE KEY?
>
>
>
What does your code look like? If the private key was bad, you would
have gotten a warning/error that it couldn't load he key, so I would
assume its good.
Rob
Since your connection is HTTP, don't set the local_cert parameter in the
context.
The cert you should be using is the one you made (or the signed one if
you had it signed by an authority) . Basically all that you are doing
with it in the example above is adding your public key in the header so
that the service provider can pull it from the message and use it to
verify the signature. There might be more that the service you are using
offers because all having their cert would allow you to do is encrypt
data which only they could decrypt or verify any signatures they may
return to you.
Rob
Have you compared your cert with the testing cert to make sure they are
both in the same format and look the same?
I would ask the service provider if they check the signature before or
after the credentials. Also if possible if they could just tell you why
the signature is failing on their end.
I usually verify the signature by running it through a different
validator (such as a test server written in .NET or Java); otherwise if
its a bug in the library you wont know since it was the one creating the
signature.
And you are positive that the private key you are using is the one
associated with your cert? I wonder about that because you didnt mention
using a different private key when using the testing cert.
Rob
The id names should not matter unless the provider's devs did some real
bad coding on their end. Order possibly might matter if the provider
requires some specific order (though I dont see any reason they would).
Can you send me the complete SOAP request as well as one of their
complete requests that works?
Who is the service provider if you dont mind me asking? I have run into
a few cases where the provider took some liberties with the XML-DSig
specs so may the problem here. At least they are helping you try to find
where the problem lies, though no idea why it would take them a week
when it could be done form their side in a few minutes.
Rob
Yea you can send me them to me directly. Ah that explains the timeframe.
Was a bit surprised when you said it would be a week :)
Rob
Sorry about that. I am in charge of our OAuth services at work, so the
recent security issue robbed me of all my free time. Now that it has
settled down, I plan on digging back into your issue. I take it the
vendor hasn't been of much help?
The original mhash code should be correct. Can you confirm that line 697
for you is:
$alg = "MHASH_" . strtoupper($alg);
Rob
This is really going to require the provider to look at it and let you
know what's wrong. After going through the messages, the only thing I
could find (and I pray the provider didnt do something as stupid as
using a hard coded namespace prefix - I've seen it before though), is
that they are using soapenv as the prefix while PHP uses SOAP-ENV. Their
use of setting xmlns="" should not matter in the least because there are
no non-namespaced elements so setting a default namespace isn't doing
anything. Sorry I couldn't have been more of a help here.
Rob
Rob
Based on your structure, the timestamp node (which includes all
attributes and children) and the SOAP body (including all attributes and
children) are included in the signature. The XML is canonicalized
(http://www.w3.org/TR/xml-exc-c14n/) so contains much more than just
text content. Based on the complexities, I doubt you would be able to
easily manaully verify this. Do you happen to have access to any other
toolsets (.NET or Java perhaps). You could then use that to do verification.
Rob
> Is the private key/certificate also included in the signature?
> Otherwise maybe I could try to fake the service provider's example and
> check, whether my code creates the same signature based on their data
> (assuming that I hardcode their Timestamp-node)?
>
>
The private key is used for signing and is only required by the signer.
The public key, which is usually included with the document, is what is
used to verify the signature. In order to create the same signature, you
would need their private key they used for the example. I also don't
know if their example is a true example as they use xxx for for the
xmlData and version parameters. It's possible they sanitized those
values after signing.
Rob