Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / ASP.NET / Web Services / February 2005

Tip: Looking for answers? Try searching our database.

UserNameToken with SendNone on Password

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
James Hancock - 09 Feb 2005 19:43 GMT
Ok, so I have been looking and looking for a solution that is simple and
eligent and easy to mainatain (see previous post) that replaces the WSE 1.0
shared secret stuff. I have read through the post about using UserNameToken
and just not passing the password and thus both sides basically use the
password as the shared secret.

However, I cannot get this to work. If I set it to SendNone with the
password, then I get an error telling me that the soap message encryption
isn't the same (basically that's the message).

What am I doing wrong?

I put the password into the constructor for the UserNameToken, and sendNone
and on the other side I've overriden the tolken manager and on
authentication I return the real password as plain text.

Thanks!

(Sidd: thanks for your comments, if MS had a nice sample for doing shared
secret correctly in the help or online all of this stuff would be solved and
I would be happy :)... sounds like there are a lot of others in here with
the same problem)
William Stacey [MVP] - 10 Feb 2005 04:27 GMT
IMO, you don't want to use UsernameTokens (UT) with send none, send hashed,
or send clear - period.  What you want to use is SecurityContextTokens
(SCT).  If you only use UT, you can ~easily figure out the password via the
hash or the signature.   Get a SCT and sign and encrypt your body with a
SCT - you then don't need UTs.  Only except soap bodies with signatures in
your server methods.  Also use a DerivedToken of your SCT to mix it up after
each call.  You can get a SCT via std WSE HTTP or soap.tcp.  I have a blog
on getting SCT using soap.tcp using public key at
http://spaces.msn.com/members/staceyw/Blog/cns!1pnsZpX0fPvDxLKC6rAAhLsQ!303.entry

Signature

William Stacey, MVP
http://mvp.support.microsoft.com

> Ok, so I have been looking and looking for a solution that is simple and
> eligent and easy to mainatain (see previous post) that replaces the WSE 1.0
[quoted text clipped - 18 lines]
> I would be happy :)... sounds like there are a lot of others in here with
> the same problem)
SA - 11 Feb 2005 00:59 GMT
William:

In WSE 2.0 SP 1, for me, creating a derived key from an SCT based on a
UsernameToken fails...

Is this me, or is this indeed a known problem?

Signature

Sven.

> IMO, you don't want to use UsernameTokens (UT) with send none, send hashed,
> or send clear - period.  What you want to use is SecurityContextTokens
[quoted text clipped - 4 lines]
> each call.  You can get a SCT via std WSE HTTP or soap.tcp.  I have a blog
> on getting SCT using soap.tcp using public key at

http://spaces.msn.com/members/staceyw/Blog/cns!1pnsZpX0fPvDxLKC6rAAhLsQ!303.entry

> > Ok, so I have been looking and looking for a solution that is simple and
> > eligent and easy to mainatain (see previous post) that replaces the WSE
[quoted text clipped - 22 lines]
> > I would be happy :)... sounds like there are a lot of others in here with
> > the same problem)
William Stacey [MVP] - 11 Feb 2005 05:04 GMT
I have SP2 so can't tell if it is a SP1 issue.  I would probably just
install SP2 so you have less variables to test.
Then just sign a message using SCT to see if that works first.  If that
works, then use a derived token from the SCT to see if that works.  If not,
please post the error and the client web method code.  TIA.

Signature

William Stacey, MVP
http://mvp.support.microsoft.com

> William:
>
[quoted text clipped - 14 lines]
> > each call.  You can get a SCT via std WSE HTTP or soap.tcp.  I have a blog
> > on getting SCT using soap.tcp using public key at

http://spaces.msn.com/members/staceyw/Blog/cns!1pnsZpX0fPvDxLKC6rAAhLsQ!303.entry

> > > Ok, so I have been looking and looking for a solution that is simple and
> > > eligent and easy to mainatain (see previous post) that replaces the WSE
[quoted text clipped - 25 lines]
> with
> > > the same problem)
James Hancock - 13 Feb 2005 16:25 GMT
William could you do me a favour and post a full sample application with
what you've done with the latest code somewhere? Because I'm getting all
kinds of compile errors and getting confused as to which version requires
which and I can't find the methods like Utils.RijndaelEncrypt in any of the
sample stuff you put up etc.  This defintely looks like the best possible
solution to the problem, I just need a little more help to get it working :)

Thanks!

And MS: Please put something like this directly into WSE as a good
replacement for shared secret that you took out of WSE 1.0

Thanks!
James Hancock

>I have SP2 so can't tell if it is a SP1 issue.  I would probably just
> install SP2 so you have less variables to test.
[quoted text clipped - 60 lines]
>> with
>> > > the same problem)
William Stacey [MVP] - 14 Feb 2005 04:31 GMT
Here are those two methods:

public static byte[] RijndaelEncrypt(ICryptoTransform encryptor, byte[]
data)
{
   if ( encryptor == null )
 throw new ArgumentNullException("encryptor");
if ( data == null )
 throw new ArgumentNullException("data");

//Encrypt the data.
using(MemoryStream msEncrypt = new MemoryStream())
using(CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor,
CryptoStreamMode.Write))
{
 //Write all data to the crypto stream and flush it.
 csEncrypt.Write(data, 0, data.Length);
 csEncrypt.FlushFinalBlock();

 //Get encrypted array of bytes.
 byte[] encrypted = msEncrypt.ToArray();
 return encrypted;
}
}

public static byte[] RijndaelDecrypt(ICryptoTransform decryptor, byte[]
encrypted)
{
if ( decryptor == null )
 throw new ArgumentNullException("decryptor");
if ( encrypted == null )
 throw new ArgumentNullException("encrypted");

using(MemoryStream msDecrypt = new MemoryStream(encrypted))
using(CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor,
CryptoStreamMode.Read))
{
 byte[] fromEncrypt = new byte[encrypted.Length];

 int read = csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
 if ( read < fromEncrypt.Length )
 {
  byte[] clearBytes = new byte[read];
  Buffer.BlockCopy(fromEncrypt, 0, clearBytes, 0, read);
  return clearBytes;
 }
 return fromEncrypt;
}
}

Signature

William Stacey, MVP
http://mvp.support.microsoft.com

> William could you do me a favour and post a full sample application with
> what you've done with the latest code somewhere? Because I'm getting all
[quoted text clipped - 40 lines]
> > blog
> >> > on getting SCT using soap.tcp using public key at

http://spaces.msn.com/members/staceyw/Blog/cns!1pnsZpX0fPvDxLKC6rAAhLsQ!303.entry

> >> > > Ok, so I have been looking and looking for a solution that is simple
> > and
[quoted text clipped - 29 lines]
> >> with
> >> > > the same problem)
SA - 14 Feb 2005 20:44 GMT
William, others:

I have created a full working sample using the method you described in your
blog.

It is available from

http://www.adduxis.com/play/SecureUTSCTSample.zip

To keep everyone happy, it's partially in C# and partially in VB.NET ;o)

Because there is no actual code in my web project, I didn't include it. The
only thing I included is the web.config. You can create a web project in the
solution and then add a reference to the ServiceInterface project to this
new web project. Then replace the web.config with the one included in the
sample.

Also, the sample relies on a shared library I developed. The library is
included, but I can't distribute the source code. Nothing too fancy anyway,
just hashing, Rijndael, and RSA helper classes.

Some changes from William's implementation:

* I use the machine key store to store the RSA key pair. A program is
included that will allow you to create an RSA key pair and store it in the
machine key store.

* I have split the SCTMessage class in 2: a request class and a response
class.

* I include the length of the salt string in the request message.

* In order to keep the code clean, I do not actually verify the
username/password against the windows database or any other credential
store. There is plenty of info available about those things, I don't see the
need to add another example.

An architecture document is available in Visio 2003 format in the sample
main folder.

I am looking forward to any feedback this sample generates! Sorry, no blog
at this time, please post to this group. Sorry, no docs available at this
time, code should be sufficiently commented.

Next, I would like some input on how to actually create a custom
TokenIssuer, so that this can be used declaratively. I am assuming I'll need
to start by deriving the SctRequestMessage class from XmlToken?

HTH,

Signature

Sven.

> Here are those two methods:
>
[quoted text clipped - 96 lines]
> > > blog
> > >> > on getting SCT using soap.tcp using public key at

http://spaces.msn.com/members/staceyw/Blog/cns!1pnsZpX0fPvDxLKC6rAAhLsQ!303.entry

> > >> > > Ok, so I have been looking and looking for a solution that is
> simple
[quoted text clipped - 32 lines]
> > >> with
> > >> > > the same problem)
William Stacey [MVP] - 15 Feb 2005 02:38 GMT
> I have created a full working sample using the method you described in your
> blog.

Great.

> To keep everyone happy, it's partially in C# and partially in VB.NET ;o)

I would rather have all in one or the other myself.  Or complete projects in
each if you wanted to show both.

> Nothing too fancy anyway, just hashing, Rijndael, and RSA helper classes.

So why not just include them in your Utils class as static methods?  That is
what I did, then I don't need another class for those simple methods.

> * I use the machine key store to store the RSA key pair. A program is
> included that will allow you to create an RSA key pair and store it in the
> machine key store.

You can use the machine store, or *.snk file, or embedded string.  The
client only needs the public key.  If you are using SN assems, then the
public key in the Assembly is convient as you have the public key you know
the server has a private key for.  You can also embed the public key string
in the client so a simple sn -R will not work to do a MITM attack.  On the
server side, you could use key store or load from .snk.

> * I have split the SCTMessage class in 2: a request class and a response
> class.

I had thought about that originally, but any null values, by default, don't
serialize so the effect is the same if using one doc class and you can drop
another class.  No value type fields, so we can pull this off kinda neat.
If I had more fields and/or value type fields, I would probably go with
another class as well.

> * I include the length of the salt string in the request message.

I wanted to include only that which was required or added security.  I don't
see the salt length as adding security.  The RSA recommendation is that it
be random and >= 64 bits.  So 8 or more bytes should do fine.  Then just
remove that many and you can drop another field from the protocol.  The salt
is there to make it harder to do dictionary attacks on the username or
password encrypted fields.  To pull that off, you would need to guess or
brute force the correct key, IV, salt, and password at the *same time.   I
just added it to the username field as it is cheap and pretty simple.  And
if you think about it.  The username can be just as important to keep secret
as its plain text can be valuable information to an attacker.

> * In order to keep the code clean, I do not actually verify the
> username/password against the windows database or any other credential
> store. There is plenty of info available about those things, I don't see the
> need to add another example.

I might go ahead and include that logic for others as it is important to the
protocol.  You should only return a SCT if you authenticate with correct
username/password combo.  So that integration is at heart of the solution.
Your web methods should also require all soap bodies signed with a SCT.
That is how you force a prior authentication and the other side has an
*authenticated SCT.  For example, your IsCustomerValid() web method should
have the logic to require an authenticated SCT signed the soap body.  As it
is, any client could call that method without including any token (unless I
missed something.)  Cheers.

Signature

William Stacey, MVP
http://mvp.support.microsoft.com

SA - 15 Feb 2005 17:31 GMT
> I would rather have all in one or the other myself.  Or complete projects in
> each if you wanted to show both.

I could have done that, however, I wrote the sample for myself in the first
place :o) I decided to share it because I think your idea is solid and
deserves attention.

> So why not just include them in your Utils class as static methods?  That is
> what I did, then I don't need another class for those simple methods.

No offense, but that code was written for my company and is therefore
intellectual property... I don't think it takes away from the usefulness of
the sample. That should be the principle behind component re-use, it's
black-box stuff.

> > * I use the machine key store to store the RSA key pair. A program is
> > included that will allow you to create an RSA key pair and store it in the
[quoted text clipped - 6 lines]
> in the client so a simple sn -R will not work to do a MITM attack.  On the
> server side, you could use key store or load from .snk.

OK, the goal for me is to have a way of distributing the software so that
every customer can have their own key pair, and (specific project
requirements) one client could connect to multiple servers from different
sites (with different key pairs in that case).

> > * I have split the SCTMessage class in 2: a request class and a response
> > class.
[quoted text clipped - 4 lines]
> If I had more fields and/or value type fields, I would probably go with
> another class as well.

I just think it's good design practice. They are in essence two different
documents and should therefore be treated as such.

> > * I include the length of the salt string in the request message.
>
[quoted text clipped - 8 lines]
> if you think about it.  The username can be just as important to keep secret
> as its plain text can be valuable information to an attacker.

I only include the length of the salt to make the whole scheme more
flexible, not for added security. Actually, I have wondered if adding the
salt length to the message might give the hacker to much info?

> > * In order to keep the code clean, I do not actually verify the
> > username/password against the windows database or any other credential
[quoted text clipped - 11 lines]
> is, any client could call that method without including any token (unless I
> missed something.)  Cheers.

The code clearly indicates where the validation should take place.
Personally, I feel that adding any type of validation code would make the
sample specific to any chosen authentication method. Whether using Azman,
ADAM, windows logon methods, or some home-grown database implementation, the
idea is to authenticate the user.

I omitted the token validation from the sample, my mistake. One reason is
that I would really rather have a custom TokenIssuer so that WS-Policy can
then be used to validate incoming messages. I should not have distributed
the sample without that check though.
William Stacey [MVP] - 15 Feb 2005 18:40 GMT
> No offense, but that code was written for my company and is therefore
> intellectual property... I don't think it takes away from the usefulness of
> the sample. That should be the principle behind component re-use, it's
> black-box stuff.

None taken. :-) Hope you did not take offense to that either.  I just
thought it strange to included all the hard stuff that most would concider
IP, but then say a simple thing like a ByteArrayComparer is IP?  O well.
Does not really matter.  Glad fokes are finding some value.

> OK, the goal for me is to have a way of distributing the software so that
> every customer can have their own key pair, and (specific project
> requirements) one client could connect to multiple servers from different
> sites (with different key pairs in that case).

OK.  I just want to understand the why of it.  Just interested.  At the
moment, I don't see the value of each client having a unique private key for
a couple reasons.  1) you need to figure out a way to protect it and 2) If
they get a SCT with a username/password, isn't that enouph to prove who they
are (assuming your passwords are strong and not known.)  Unless your doing
some other two-factor authentication such as One-Time-Password or something.

> I just think it's good design practice. They are in essence two different
> documents and should therefore be treated as such.

Cool.  I just have a different opinion for this usage.

> I only include the length of the salt to make the whole scheme more
> flexible, not for added security. Actually, I have wondered if adding the
> salt length to the message might give the hacker to much info?

Well not sure it helps either way.  If you don't include it, the fixed salt
len can be derived from the code or possibly infered from capture of message
of a known password (say his own SCT session).  If you explicitly include
it, then you don't need to infer it as it is plain.  I am just struggling
with finding the value in it as it would seem to be an unneeded element at
this point.

> I omitted the token validation from the sample, my mistake. One reason is
> that I would really rather have a custom TokenIssuer so that WS-Policy can
> then be used to validate incoming messages. I should not have distributed
> the sample without that check though.

No problem.  Just pointing out for others.  I posted an example SCT check
logic in another post on this thread.
Cheers!

Signature

William Stacey, MVP
http://mvp.support.microsoft.com

SA - 15 Feb 2005 19:10 GMT
> None taken. :-) Hope you did not take offense to that either.  I just
> thought it strange to included all the hard stuff that most would concider
> IP, but then say a simple thing like a ByteArrayComparer is IP?  O well.
> Does not really matter.  Glad fokes are finding some value.

You did the hard stuff :o) I just added some code to it. My
ByteArrayComparer is obviously easy. Even the RSA and Rijndael classes are
easy enough, but take some time, it's just that that's policy...

> > OK, the goal for me is to have a way of distributing the software so that
> > every customer can have their own key pair, and (specific project
[quoted text clipped - 7 lines]
> are (assuming your passwords are strong and not known.)  Unless your doing
> some other two-factor authentication such as One-Time-Password or something.

If every customer has the same private key, a hacker would merely need to
purchase the product to hack into other people's passwords, sessions, etc.
(Or am I wrong here?)

> > I just think it's good design practice. They are in essence two different
> > documents and should therefore be treated as such.
>
> Cool.  I just have a different opinion for this usage.

No doubt yours works just as well.

> > I only include the length of the salt to make the whole scheme more
> > flexible, not for added security. Actually, I have wondered if adding the
[quoted text clipped - 6 lines]
> with finding the value in it as it would seem to be an unneeded element at
> this point.

Not if you would say that you might allow the salt value to be a
configuration option? Again, I am thinking commercial software.

> > I omitted the token validation from the sample, my mistake. One reason is
> > that I would really rather have a custom TokenIssuer so that WS-Policy can
[quoted text clipped - 4 lines]
> logic in another post on this thread.
> Cheers!

Wondering if you'd be interested pursuing writing this as a custom
TokenIssuer and then writing an article for publication, perhaps in MSDN
Magazine?

Thanks for the feedback!

Sven.
William Stacey [MVP] - 15 Feb 2005 19:52 GMT
> If every customer has the same private key, a hacker would merely need to
> purchase the product to hack into other people's passwords, sessions, etc.
> (Or am I wrong here?)

Can't say wrong or right in terms of what additional things you may be
thinking.  However, in terms of just the SCT thing I posted, you don't need
private PKI key on clients at all.  Only the *public key on the client, the
server(s) maintain the private key.  If you have multiple servers (say a
farm), then each server can access same private key pair using any method
you prefer (i.e. db, shared file, key store, etc)  Using this public PKI
method, a hacker can not hack into other people's passwords off the wire as
they can not decrypt the AES session key that was encrypted with the public
key.  The hacker can send his own requests using the public key, but can not
decrypt any other messages from others, even if they use the same public
key.   So a hacker can not figure out your session key or password and the
session is safe within the context of the AES session.  To crack, he would
need to crack PKI and/or AES using brute force - so we are safe as PKI/AES
can be (which is not to say PKI or AES can not be cracked given time and
resources).  So to get back to your point.  I don't see what unique private
PKI key on each client is adding here as we are not using a private key for
the SCT request.  Unless your talking about some other method in addition to
the SCT session.  If so, I would love to hear about your ideas.

All that said, there is still one weakness here.  Even thou the public key
is public and not secret, we still need to protect it from
change/replacement somehow.  As a hacker who gets access to your machine may
be able to replace your public key with a public key he created from a new
key pair.  Now he could Man-In-The-Middle the session.  You would send
encrypted request using "his" public key, and he could decrypt with the
matching private key is knows already.  Then just drop the session as he has
the password or continue being in the middle and forwarding requests.  This
would be a hard attack to pull off that would require access to client
machine and some network access - but something to think about.  I think
even public Certs would be vulnerable to this type of attack given the same
access to machine and network (say an Inside-Job).

The only thing I can think of to head off that kind of attack is SN sign
your client assem with key pair *and encrypt the same public key string in
the assem (and obfuscate) and compare the two keys at some point.  This
pretty much would force a decompile to remove the key compare logic or
change the public key.  The double check also would guard against any
minor/major change to the code or resources as the loader would fail to load
the assem.  Moreover, they could not just resign the assem as the double
check using the embedded version would fail.  Raises the bar a bit more.

> Not if you would say that you might allow the salt value to be a
> configuration option? Again, I am thinking commercial software.

I like config options as well.  However, I still don't see what value this
could add to commercial software or otherwise.  I am racking my head to find
a value, but am not able to at this point.

> Wondering if you'd be interested pursuing writing this as a custom
> TokenIssuer and then writing an article for publication, perhaps in MSDN
> Magazine?

Sure.  You have any connections into MSDN mag?  Cheers!

Signature

William Stacey, MVP
http://mvp.support.microsoft.com

SA - 15 Feb 2005 21:11 GMT
> > If every customer has the same private key, a hacker would merely need to
> > purchase the product to hack into other people's passwords, sessions, etc.
[quoted text clipped - 18 lines]
> the SCT request.  Unless your talking about some other method in addition to
> the SCT session.  If so, I would love to hear about your ideas.

OK, apparently I did not make it clear: the server product is the product
being sold (clients too, of course)! So, if every installation with every
customer has the same key pair, the hacker has the private key by purchasing
the product.

> All that said, there is still one weakness here.  Even thou the public key
> is public and not secret, we still need to protect it from
[quoted text clipped - 8 lines]
> even public Certs would be vulnerable to this type of attack given the same
> access to machine and network (say an Inside-Job).

Right. See my first comment. Would need access to the machine (client or
server) in order to do so.

> The only thing I can think of to head off that kind of attack is SN sign
> your client assem with key pair *and encrypt the same public key string in
[quoted text clipped - 4 lines]
> the assem.  Moreover, they could not just resign the assem as the double
> check using the embedded version would fail.  Raises the bar a bit more.

That's a good idea. Of course, in my situation, where we'll have different
private/public key pairs for different installations, that would not work,
as you can only have one public key embedded in the assembly.

> > Not if you would say that you might allow the salt value to be a
> > configuration option? Again, I am thinking commercial software.
>
> I like config options as well.  However, I still don't see what value this
> could add to commercial software or otherwise.  I am racking my head to find
> a value, but am not able to at this point.

I may have taken this idea too far.

> > Wondering if you'd be interested pursuing writing this as a custom
> > TokenIssuer and then writing an article for publication, perhaps in MSDN
> > Magazine?
>
> Sure.  You have any connections into MSDN mag?  Cheers!

Except for the fact that I have a subscription, no... If you'd like to take
this more private, visit http://www.adduxis.com and get my e-mail address of
the contacts page.

Thanks.
William Stacey [MVP] - 15 Feb 2005 21:42 GMT
> OK, apparently I did not make it clear: the server product is the product
> being sold (clients too, of course)! So, if every installation with every
> customer has the same key pair, the hacker has the private key by purchasing
> the product.

ahh.  Makes perfect sense then.  Thanks SA.

Signature

William Stacey, MVP
http://mvp.support.microsoft.com

James Hancock - 14 Feb 2005 21:00 GMT
Thanks! Do you have the GetBytes and in the GETSCTNew I can't find the
SnkUtil.GetRSAFromSnkFile function or the definition for sha.ComputeHash
(sha is never defined)..

Thanks again,
James Hancock

> Here are those two methods:
>
[quoted text clipped - 138 lines]
>> >> with
>> >> > > the same problem)
William Stacey [MVP] - 15 Feb 2005 02:41 GMT
The full SnkUtil class is in one of my blogs at
http://spaces.msn.com/members/staceyw

sha.ComputeHash() is a method of the SHA1 class in the framework.

Signature

William Stacey, MVP
http://mvp.support.microsoft.com

> Thanks! Do you have the GetBytes and in the GETSCTNew I can't find the
> SnkUtil.GetRSAFromSnkFile function or the definition for sha.ComputeHash
[quoted text clipped - 104 lines]
> >> > blog
> >> >> > on getting SCT using soap.tcp using public key at

http://spaces.msn.com/members/staceyw/Blog/cns!1pnsZpX0fPvDxLKC6rAAhLsQ!303.entry

> >> >> > > Ok, so I have been looking and looking for a solution that is
> > simple
[quoted text clipped - 34 lines]
> >> >> with
> >> >> > > the same problem)
James Hancock - 14 Feb 2005 21:05 GMT
Also need ArraysEqual and ToUTCDateTime and
SnkUtil.GetPublicKeyFromAssembly

And where was base.SendRequestResponse come from?  I.e. what class does the
Client method go into and what does that class inherit from?

Thanks again!

> Here are those two methods:
>
[quoted text clipped - 138 lines]
>> >> with
>> >> > > the same problem)
SA - 14 Feb 2005 21:48 GMT
James,

I suggest you look at my sample, hopefully that will help out.

.SendRequestResponse is inherited from SoapClient
(Microsoft.Web.Services2.Messaging namespace).

Signature

Sven.

> Also need ArraysEqual and ToUTCDateTime and
> SnkUtil.GetPublicKeyFromAssembly
[quoted text clipped - 105 lines]
> >> > blog
> >> >> > on getting SCT using soap.tcp using public key at

http://spaces.msn.com/members/staceyw/Blog/cns!1pnsZpX0fPvDxLKC6rAAhLsQ!303.entry

> >> >> > > Ok, so I have been looking and looking for a solution that is
> > simple
[quoted text clipped - 34 lines]
> >> >> with
> >> >> > > the same problem)
James Hancock - 15 Feb 2005 01:13 GMT
Ok, so I don't want to use this with soap stuff really, I only want to use
it for Web Services.  Do I have to use pure soap messaging or can I do it
with a pure web service?

> James,
>
[quoted text clipped - 172 lines]
>> >> >> with
>> >> >> > > the same problem)
William Stacey [MVP] - 15 Feb 2005 01:46 GMT
You could it with sockets and no xml if you wanted.  However SCTs are a WSE
thing.  If you not using WS-*, then probably no need for this.  You could
use the same idea however to do a shared key exchange.  I would probably use
Diffie-Hellman at that point or SRP.

Signature

William Stacey, MVP
http://mvp.support.microsoft.com

> Ok, so I don't want to use this with soap stuff really, I only want to use
> it for Web Services.  Do I have to use pure soap messaging or can I do it
[quoted text clipped - 131 lines]
> >> >> > blog
> >> >> >> > on getting SCT using soap.tcp using public key at

http://spaces.msn.com/members/staceyw/Blog/cns!1pnsZpX0fPvDxLKC6rAAhLsQ!303.entry

> >> >> >> > > Ok, so I have been looking and looking for a solution that is
> >> > simple
[quoted text clipped - 38 lines]
> >> >> >> with
> >> >> >> > > the same problem)
James Hancock - 15 Feb 2005 14:58 GMT
Ok. I'm getting totally confused. Here's what I want to do:

I have a web service.  It uses WSE 1.0 right now with shared secret to
encrypt the transactions that go over the wire to ensure data security.  All
I want to do is upgrade to WSE 2.0 to fix all of the bloody bugs with WSE
1.0's attachment implimentation.

However of course, WSE 2.0 took out the shared secret encryption for some
god forsaken reason and didn't bother to put in an equivalent easily.

So right now I've got it using UserNameToken and sending the password as
plain text.  Needless to say I don't like this at all.  What I wanted to do
is SendNone with my username tolken thus basically creating a shared secret
because the server already knows the password and can return it to the
authenticaltoken command thus leaving the (incredibly strong) password out
of the equation.

Anyhow, I like your solution better, but I'm getting confused and
frustrated.  GETSCTNew aparently needs a class that is inherited from
SoapClient.  Well of course this isn't a soap communication beyond the fact
that it's a web service so it's using soap stuff under neath.  At that point
I get confused, becuase how the heck do I send this stuff?

Right now I do this:

us.CookieContainer = cookieJar;

us.Timeout = 1800000;

us.Url = URL;

Microsoft.Web.Services2.Security.Tokens.UsernameToken tok = new
Microsoft.Web.Services2.Security.Tokens.UsernameToken(Licience,
Common.EncryptString(Key),
Microsoft.Web.Services2.Security.Tokens.PasswordOption.SendPlainText);

//Sync.RequestSoapContext

SoapContext requestContext = us.RequestSoapContext;

requestContext.Security.Timestamp.TtlInSeconds = -1;

requestContext.Security.Tokens.Add(tok);

MessageSignature sig = new MessageSignature(tok);

requestContext.Security.Elements.Add(sig);

requestContext.Security.Elements.Add(new EncryptedData(tok));

Which signs and encrypts the communication nicely.

us = a web service that is in my web references.

On the server side I have it setup in my web.config so that it knows about
my implimentation of usernametoken and I do my own authentication in that
class and then every web method I then check the soap contents to make sure
that it is encrypted, signed and has a valid usernametoken on it.

Add to that a ton of functions that I can't find that you use all over the
place and I'm really lost. (hence why I asked how to use SendNone on
UserNameTokens so that I could do this the easy way)

Man I hope they make this stuff easier in Indigo... I thought Avalon was
going to be great, but now I am convinced that Indigo is going to be where
it's at if they finally fix this and make encryption without certificates
easy.

James Hancock

> You could it with sockets and no xml if you wanted.  However SCTs are a
> WSE
[quoted text clipped - 206 lines]
>> >> >> >> with
>> >> >> >> > > the same problem)
William Stacey [MVP] - 15 Feb 2005 17:28 GMT
> However of course, WSE 2.0 took out the shared secret encryption for some
> god forsaken reason and didn't bother to put in an equivalent easily.

Effectivily, UsernameTokens(UT) is using a shared secret.  The shared secret
is the password.  The encryption key is derived from the password.  More on
that below.

> So right now I've got it using UserNameToken and sending the password as
> plain text.  Needless to say I don't like this at all.  What I wanted to do
> is SendNone with my username tolken thus basically creating a shared secret
> because the server already knows the password and can return it to the
> authenticaltoken command thus leaving the (incredibly strong) password out
> of the equation.

The problem with using just UTs and either SendNone, SendHashed or SendPlain
is if you sign a request, you may have all the data you need to perform a
dictionary attack on the signature to get the password used to sign the
data.  Depending on the data sent, you could also do a dictionary attack on
the encrypted body to figure out what password was used to encrypt it.  If
your password is a cryptographically strong random bytes and >= 16 bytes,
then that may be ok as that is like trying to brute force an AES 16 byte
random key.  If you go that route, I would use SendNone, a 16 (or 32) byte
*random password, and encrypt and sign all requests. Also note, you can't
use DerivedKeyTokens with UTs, so that is another down side of using UTs.

> Anyhow, I like your solution better, but I'm getting confused and
> frustrated.  GETSCTNew aparently needs a class that is inherited from
> SoapClient.

GetSCTNew is a just a soap method like any other.  Yes the class derives
from SoapClient.  Are you having issues with get a SoapClient proxy working
with your SoapService?  My SCT method just returns a SCT token if you pass
the correct username/pw.  Then you can use the SCT to sign and encrypt
messages without a UT.  If you using 16 byte random password, then it is
probably still not as strong as using a SCT, but maybe good enouph for your
purposes and easier as you said.  I attached code of client class at end of
this post.

> Add to that a ton of functions that I can't find that you use all over the
> place and I'm really lost. (hence why I asked how to use SendNone on
> UserNameTokens so that I could do this the easy way)

> Man I hope they make this stuff easier in Indigo... I thought Avalon was
> going to be great, but now I am convinced that Indigo is going to be where
> it's at if they finally fix this and make encryption without certificates
> easy.

Looks like Indigo will make things much easier.  Here is client side class.

using System;
using System.Collections;
using System.Security.Cryptography;
using System.IO;
using System.Text;
using System.Diagnostics;
using Microsoft.Web.Services2;
using Microsoft.Web.Services2.Addressing;
using Microsoft.Web.Services2.Messaging;
using Microsoft.Web.Services2.Security.Tokens;
using Microsoft.Web.Services2.Security;
using System.Xml;
using Microsoft.Web.Services2.Security.Policy;
using Microsoft.Web.Services2.Security.Cryptography;
using System.Globalization;
using System.Reflection;

namespace WSESimpleTCPDLL
{
public sealed class ServiceClient : SoapClient
{
 private System.Security.Cryptography.RSACryptoServiceProvider rsaPub;
 private readonly Hashtable sctList = new Hashtable( new
CaseInsensitiveHashCodeProvider(), new CaseInsensitiveComparer() );
 private readonly object syncRoot = new object();
 private static SHA1 sha = SHA1.Create();

 public ServiceClient( EndpointReference endpoint ) : base( endpoint )
 {
  string xml = GetPublicKey();
  rsaPub = new System.Security.Cryptography.RSACryptoServiceProvider();
  rsaPub.FromXmlString(xml);

  sctList = new Hashtable( new CaseInsensitiveHashCodeProvider(), new
CaseInsensitiveComparer() );
  sctList = Hashtable.Synchronized(sctList);
 }

 private ServiceClient() : base()
 {
 }

 private System.Security.Cryptography.RSACryptoServiceProvider RSAPubKey
 {
  get { return rsaPub; }
 }

 public SecurityContextToken GetSCTNew(string userName, string password)
 {
  SecurityContextToken curSCT = (SecurityContextToken)sctList[userName];
  if ( curSCT != null )
  {
   if ( curSCT.IsCurrent )
    return curSCT;
   // Else, remove curSCT and continue for new one.
   sctList.Remove(userName);
  }
  // Load server's public RSA key. Could get from Assembly, file, etc.
  System.Security.Cryptography.RSACryptoServiceProvider pubRSA =
   SnkUtil.GetPublicKeyFromAssembly(Assembly.GetExecutingAssembly());

  // Create SCT Request.
  SCTMsg ki = new SCTMsg();
  byte[] key = Utils.GetRandomBytes(64); // 64 bytes each side.
  byte[] sKey = Utils.GetBytes(key, 32); // 32 bytes AES key.
  byte[] iv = Utils.GetBytes(key, 16); // Is this secure?
  // Add some random salt to the username and pw to make it so much
  // harder to figure out via a brute force attack on AES.  Nice thing
  // about use AES instead of PKI is we don't have to worry about size
  // of username or password.
  string salt =
Convert.ToBase64String(Utils.GetRandomBytes(10)).Substring(0, 10);
  string saltun = salt + userName;
  string saltpw = salt + password;
  byte[] unBytes = Encoding.UTF8.GetBytes(saltun);
  byte[] pwBytes = Encoding.UTF8.GetBytes(saltpw);
  ki.Key = pubRSA.Encrypt(key, false);
  RijndaelManaged rm = new RijndaelManaged();
  rm.Key = sKey;
  rm.IV = iv;
  ICryptoTransform encryptor = rm.CreateEncryptor();
  ki.Username = Utils.RijndaelEncrypt(encryptor, unBytes);
  ki.Password = Utils.RijndaelEncrypt(encryptor, pwBytes);
  // Add signature.  This is the msg digest encrypted with AES.
  // Note we are using the actual 64 key in the hash and not
  // the "wire" version.  Now the message itself does not
  // contain the raw data needed to brute force the hash.
  byte[] hashData =
   Encoding.UTF8.GetBytes(
   Convert.ToBase64String(key) +
   Convert.ToBase64String(ki.Username) +
   Convert.ToBase64String(ki.Password));
  byte[] msgHash = sha.ComputeHash(hashData);
  ki.Signature = Utils.RijndaelEncrypt(encryptor, msgHash);

  // Send request.
  SoapEnvelope se = new SoapEnvelope();
  se.SetBodyObject(ki);
  SCTMsg rki = (SCTMsg)base.SendRequestResponse("GetSCTNew",
se).GetBodyObject(typeof(SCTMsg));

  // Verify Signature.  Digest signed by the server's private key.
  hashData = Encoding.UTF8.GetBytes(
   Convert.ToBase64String(key) + // Server used 64 byte key.
   rki.SCTIdentifier +
   rki.SCTExpires);
  if ( ! pubRSA.VerifyData(hashData, new SHA1CryptoServiceProvider(),
rki.Signature) )
   throw new Exception("Could not verify hash.");

  // Create SCT.  Note we are not wrapping a UT on this version.
  // Not sure it is needed.  Do we have a reason?
  SecurityContextToken sct = new SecurityContextToken(rki.SCTIdentifier);
  sct.KeyBytes = iv; // SCTs require 16 byte Keys.
  DateTime expires = Utils.FromUTCDateTimeString(rki.SCTExpires);
  expires = expires.ToLocalTime();
  sct.LifeTime = new LifeTime(expires);

  // Add SCT to static Hashtable for this username.
  // This hashtable is not required if you just want to hold onto the SCT
  // yourself.
  sctList[userName] = sct;
  return sct;
 }

 // Some other web method. Anyone can call.
 [SoapMethod("Ping")]
 public string Ping(string msg)
 {
  return (string)base.SendRequestResponse("Ping",
msg).GetBodyObject(typeof(string));
 }

 // Some other web method.  Server requires authenticated SCT.
 [SoapMethod("GetDateString")]
 public string GetDateString()
 {
  SoapEnvelope se = new SoapEnvelope();
  SecurityContextToken sct = GetSCTNew("staceyw", "1234");
  DerivedKeyToken dt = new DerivedKeyToken((IDerivableToken)sct);
  se.Context.Security.Tokens.Add(sct);
  se.Context.Security.Tokens.Add(dt);
  se.Context.Security.Elements.Add(new MessageSignature(dt));
  string r = (string)base.SendRequestResponse("GetDateString",
se).GetBodyObject(typeof(string));
  return r;
 }

 }
}

//
// Server method may look like:
//
 [SoapMethod("GetDateString")]
 public string GetDateString(string data)
 {
    if ( ! AccessIsAllowed(@"mvptools\newgroup") )
      throw new Exception("Security exception.");
    Debug.WriteLine("Is in Role: true");
    return DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ",
CultureInfo.InvariantCulture);
 }

 /// <summary>
 /// Require message is signed by SCT or Derived SCT *and it is
 /// Authenticated.
 /// </summary>
 /// <param name="role"></param>
 /// <returns></returns>
 private bool AccessIsAllowed(string role)
 {
  SecurityElementCollection elements =
RequestSoapContext.Current.Security.Elements;

  // Loop through all of the security tokens (could be more than one).
  foreach( ISecurityElement securityElement in elements )
  {
   if( securityElement is MessageSignature )
   {
    MessageSignature sig = (MessageSignature)securityElement;
    if( (sig.SignatureOptions & SignatureOptions.IncludeSoapBody) != 0 )
    {
     SecurityToken sigToken = sig.SigningToken;
     // Find the token used to sign this message
     if ( sigToken is SecurityContextToken ||
      sigToken is DerivedKeyToken )
     {
      if ( sigToken.Principal.Identity.IsAuthenticated )
      {
       if ( role == null )
        return true; // Allow any role.
       if ( sigToken.Principal.IsInRole(role) )
        return true; // Allow only users in "role".
       else
        return false; // Not member.
      }
      else
       return false;  // Not authenticated.
     }
     else
      return false;   // Not one of tokens we allow.
    }
   }
  }
  return false;
 }

Signature

William Stacey, MVP
http://mvp.support.microsoft.com

SA - 15 Feb 2005 17:31 GMT
James,

let's see if we can address some of your concerns.

> Anyhow, I like your solution better, but I'm getting confused and
> frustrated.  GETSCTNew aparently needs a class that is inherited from
> SoapClient.  Well of course this isn't a soap communication beyond the fact
> that it's a web service so it's using soap stuff under neath.  At that point
> I get confused, becuase how the heck do I send this stuff?

It depends. On the client side, the service proxy inherits from SoapClient.
On the server-side, the service interface inherits from SoapService.

I don't see why you are saying that's not SOAP communication... It
definitely is sending SOAP messages back and forth. I implement all my web
services that way. I need to write my own proxies rather than relying on
wsewsdl2.exe (or whatever that tool is called...), but it gives me much more
control for very little effort.

Please try the sample I supplied. Let me/us know if you have any questions
about it, after walking through it with the debugger.

> Right now I do this:

<snip>

> Which signs and encrypts the communication nicely.
>
> us = a web service that is in my web references.

Actually, "us" is just a class that's auto-generated by the WSDL tool. It is
not a web service, it's a web service proxy.

So basically, you'd write your own "us" class. That will be a class that
inherits from SoapClient. That class' interface will resemble your server
class' interface (just like "us" does now).

> On the server side I have it setup in my web.config so that it knows about
> my implimentation of usernametoken and I do my own authentication in that
> class and then every web method I then check the soap contents to make sure
> that it is encrypted, signed and has a valid usernametoken on it.

OK, so you basically have a custom UsernameTokenManager. You won't need that
any longer with this implementation. Much has been written about that
lately, but the conclusion is always that unless you use SSL every time, all
the time, there is no secure way to use UsernameTokens.

> Add to that a ton of functions that I can't find that you use all over the
> place and I'm really lost. (hence why I asked how to use SendNone on
> UserNameTokens so that I could do this the easy way)

OK, walk through the sample with a debugger. Take the encryption and hashing
stuff for granted. (That's black box stuff, it really has nothing to do with
this sample...) The only thing you need to understand is where a
public/private key pair is used and where a shared session key is used. If
you see RSA encryption, then it's PKI. If you see Rijndael, then that refers
to the shared session key.

If there are any non-encryption related functions you can't seem to find,
check the WSE documentation first. More than likely, there inherited from
SoapClient or SoapService, or static (Shared) methods of WSE 2.0 classes. If
you still don't seem to find the function, let me/us know.

Also review the architecture document that's included. If you don't have a
means to open Visio files (there's a free viewer available from Microsoft at
[1], but I understand if you don't want to install that), I will create  a
PDF from that file. Print it, and annotate is you like when going through
the sample.

> Man I hope they make this stuff easier in Indigo... I thought Avalon was
> going to be great, but now I am convinced that Indigo is going to be where
> it's at if they finally fix this and make encryption without certificates
> easy.

Unfortunately, security is never "easy." If it was, people wouldn't need us
anymore, they could just drag-and-drop their way to interoperable web
services. Pray that day never comes, or that you have another job offer by
that time ;o)

Just exaggerating. But the main point still is that using usernames and
passwords is increasingly risky because of several reasons, some of which
are outlined in Keith's article at [2].

[1] http://office.microsoft.com/en-us/officeupdate/CD010798711033.aspx

[2]
http://msdn.microsoft.com/webservices/default.aspx?pull=/library/en-us/dnwse/htm
l/securusernametoken.asp

William Stacey [MVP] - 15 Feb 2005 18:01 GMT
> Just exaggerating. But the main point still is that using usernames and
> passwords is increasingly risky because of several reasons, some of which
> are outlined in Keith's article at [2].
> http://office.microsoft.com/en-us/officeupdate/CD010798711033.aspx

http://msdn.microsoft.com/webservices/default.aspx?pull=/library/en-us/dnwse/htm
l/securusernametoken.asp


I had also blogged on the weakness of UsernameTokens with supporting code
example at:
"Crack your WSE SendHashed Passwords."
http://spaces.msn.com/members/staceyw/Blog/cns!1pnsZpX0fPvDxLKC6rAAhLsQ!178.entry

This could work with SendNone or SendHashed.  Naturally SendPlain is a joke
unless the plain text is actually encrypted first with a prior shared secret
or PKI.  It is much easier to crack ~standard passwords, but given some
time, you could crack most passwords.  Even passwords people "think" are
strong, like "Letmein;12" can be cracked pretty fast.

Signature

William Stacey, MVP
http://mvp.support.microsoft.com

James Hancock - 16 Feb 2005 15:29 GMT
> James,
>
[quoted text clipped - 18 lines]
> more
> control for very little effort.

Because all of my web services are derived from
Microsoft.Web.Services2.WebServicesClientProtocol or down the list

System.Web.Services.Protocols.SoapHttpClientProtocol
SA - 16 Feb 2005 17:38 GMT
> Because all of my web services are derived from
> Microsoft.Web.Services2.WebServicesClientProtocol or down the list
>
> System.Web.Services.Protocols.SoapHttpClientProtocol

Yes, that's a difference, but that doesn't mean it's not SOAP ;o)

HTH,

Sven.
Softwaremaker - 11 Feb 2005 06:55 GMT
James,

Grokking in the dark here: Have you set the usernametoken manager in the
config file ?
Signature

Thank you.

Regards,
William T (Softwaremaker)
http://www.softwaremaker.net/blog
=========================================

> Ok, so I have been looking and looking for a solution that is simple and
> eligent and easy to mainatain (see previous post) that replaces the WSE 1.0
[quoted text clipped - 18 lines]
> I would be happy :)... sounds like there are a lot of others in here with
> the same problem)
James Hancock - 11 Feb 2005 16:53 GMT
Yup, and all works perfectly if I send the password as plain text or hashed.

> James,
>
[quoted text clipped - 26 lines]
>> I would be happy :)... sounds like there are a lot of others in here with
>> the same problem)

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.