Help with Sha + Base64 for WSSE encoding


#1

Hello there.

I’ve got a numbers puzzle for someone out there.

I’m currently trying to implement X-WSSE authentication, which
basically means you follow these steps to create a PasswordDigest:

  1. Create a random Nonce(or string)
  2. create the token by doing Base64(sha(nonce + timestamp + password)

Use this string to autenticate. Basically. Now here’s my problem.

I have an example to work from:

Nonce =
MjAwNi0wMi0yM1QxODo1NjozMVogNDdjYzM5NTVlZmY1NzljZGIwMzVkNTljZjI4ZWU3NzE3Y2Y4NmM5Zg==
Timestamp = 2006-02-23T18:56:31Z
password = test

I know the result is supposed to be:
267V1V5JW5xqct0bOAoFEaSDL7Y= (since this works)

But when I use ruby for this:

nonce =
“MjAwNi0wMi0yM1QxODo1NjozMVogNDdjYzM5NTVlZmY1NzljZGIwMzVkNTljZjI4ZWU3NzE3Y2Y4NmM5Zg==”
time = “2006-02-23T18:56:31Z”
password = “test”
puts Base64.encode64(Digest::SHA1.hexdigest(nonce + time +
password)).strip

I get:
MzI2OTQ4YzY4OWQ3MGMxYzMzYTEwZWI2Yzg5MzZiYzMzZGE2ZTJhMg==

 Can anyone see the step I'm missing?

 Thanks,

Gregg P.
Patched Software
www.PatchedSoftware.com


#2

Tom C. wrote:

  1. Create a random Nonce(or string)
  2. create the token by doing Base64(sha(nonce + timestamp + password)

Cool.

puts Base64.encode64(Digest::SHA1.hexdigest(nonce + time +
password)).strip

Hm, do you want to be calling SHA1.hexdigest() here? Or just
SHA1.digest()?

Thanks for the quick reply Tom,

nonce =
“MjAwNi0wMi0yM1QxODo1NjozMVogNDdjYzM5NTVlZmY1NzljZGIwMzVkNTljZjI4ZWU3NzE3Y2Y4NmM5Zg==”
time = “2006-02-23T18:56:31Z”
password = “test”
puts Base64.encode64(Digest::SHA1.digest(nonce + time +
password)).strip

gets me:
MzI2OTQ4YzY4OWQ3MGMxYzMzYTEwZWI2Yzg5MzZiYzMzZGE2ZTJhMg==

Unfortunately this is not closer to:
267V1V5JW5xqct0bOAoFEaSDL7Y=


#3
  1. Create a random Nonce(or string)
  2. create the token by doing Base64(sha(nonce + timestamp + password)

Cool.

puts Base64.encode64(Digest::SHA1.hexdigest(nonce + time +
password)).strip

Hm, do you want to be calling SHA1.hexdigest() here? Or just
SHA1.digest()?

Yours,

Tom


#4
  1. Create a random Nonce(or string)
  2. create the token by doing Base64(sha(nonce + timestamp
  • password)

FWIW, when I used the values in this example:

http://www.xml.com/pub/a/2003/12/17/dive.html

It came out right:

===================
irb(main):020:0> nonce = “d36e316282959a9ed4c89851497a717f”
=> “d36e316282959a9ed4c89851497a717f”
irb(main):021:0> time = “2003-12-15T14:43:07Z”
=> “2003-12-15T14:43:07Z”
irb(main):022:0> Base64.encode64(Digest::SHA1.digest(nonce + time +
“taadtaadpst
csm”)).strip
=> “quR/EWLAV4xLf9Zqyw4pDmfV9OY=”
irb(main):023:0>

So I think we’re close…

Yours,

Tom


#5

gets me: MzI2OTQ4YzY4OWQ3MGMxYzMzYTEwZWI2Yzg5MzZiYzMzZGE2ZTJhMg==

Unfortunately this is not closer to: 267V1V5JW5xqct0bOAoFEaSDL7Y=

Hm, that’s odd, when I do that I get this:

=======================
irb(main):014:0> nonce =
“MjAwNi0wMi0yM1QxODo1NjozMVogNDdjYzM5NTVlZmY1NzljZGIwMz
VkNTljZjI4ZWU3NzE3Y2Y4NmM5Zg==”
=>
“MjAwNi0wMi0yM1QxODo1NjozMVogNDdjYzM5NTVlZmY1NzljZGIwMzVkNTljZjI4ZWU3NzE
3Y2Y4
NmM5Zg==”
irb(main):015:0> time = “2006-02-23T18:56:31Z”
=> “2006-02-23T18:56:31Z”
irb(main):016:0> password = “test”
=> “test”
irb(main):017:0> Base64.encode64(Digest::SHA1.digest(nonce + time +
password)).strip
=> “MmlIxonXDBwzoQ62yJNrwz2m4qI=”
irb(main):018:0>

Yours,

Tom


#6

Gregg P. wrote:

gets me:
MzI2OTQ4YzY4OWQ3MGMxYzMzYTEwZWI2Yzg5MzZiYzMzZGE2ZTJhMg==

Which decodes to 326948c689d70c1c33a10eb6c8936bc33da6e2a2, which is
still hex-encoded.

You need to get the raw binary hash somehow… Not sure how to do that
with Digest, though, and it seems undocumented at
http://www.ruby-doc.org/stdlib/libdoc/digest/rdoc/classes/Digest/Base.html#M000470


#7

Tom C. wrote:

gets me: MzI2OTQ4YzY4OWQ3MGMxYzMzYTEwZWI2Yzg5MzZiYzMzZGE2ZTJhMg==

Unfortunately this is not closer to: 267V1V5JW5xqct0bOAoFEaSDL7Y=

Hm, that’s odd, when I do that I get this:

=======================
irb(main):014:0> nonce =
“MjAwNi0wMi0yM1QxODo1NjozMVogNDdjYzM5NTVlZmY1NzljZGIwMz
VkNTljZjI4ZWU3NzE3Y2Y4NmM5Zg==”
=>
“MjAwNi0wMi0yM1QxODo1NjozMVogNDdjYzM5NTVlZmY1NzljZGIwMzVkNTljZjI4ZWU3NzE
3Y2Y4
NmM5Zg==”
irb(main):015:0> time = “2006-02-23T18:56:31Z”
=> “2006-02-23T18:56:31Z”
irb(main):016:0> password = “test”
=> “test”
irb(main):017:0> Base64.encode64(Digest::SHA1.digest(nonce + time +
password)).strip
=> “MmlIxonXDBwzoQ62yJNrwz2m4qI=”
irb(main):018:0>

Same here. Gregg, are you sure the original data is correct?
Maybe it is using SHA2 or something? Also, if you have OpenSSL
installed, I think Digest delegates to it.

Yours,

Tom

E


#8

Hi,

Gregg P. wrote:

Use this string to autenticate. Basically. Now here’s my problem.

MzI2OTQ4YzY4OWQ3MGMxYzMzYTEwZWI2Yzg5MzZiYzMzZGE2ZTJhMg==

you have to use the base64-decoded nonce, as stated in the specs at
http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf
I’ve implemented Username-Authentication according to the web service
security specifications and also signing and encrytion in the WSS4R lib
at www.rubyforge.org/projects/wss4r. Probably that is what you need?

require “openssl”
require “base64”
include OpenSSL
include Digest

nonce =
“MjAwNi0wMi0yM1QxODo1NjozMVogNDdjYzM5NTVlZmY1NzljZGIwMzVkNTljZjI4ZWU3NzE3Y2Y4NmM5Zg==”
time = “2006-02-23T18:56:31Z”
password = “test”

stamp = Base64::decode64(nonce)+time+password
digester = SHA1.new
digester.update(stamp)
puts("Digest: " + Base64.encode64(digester.digest().strip()))

Regards,

Roland