Jump to navigation

Poupou's Corner of the Web

Looking for perfect security? Try a wireless brick.
Otherwise you may find some unperfect stuff here...

Weblog

What's New in System.Security.Cryptography v2

I guess most people are too busy at PDC to be blogging. So let me fill the empty electrons with my own enoisetm ;-)

From time to time I'll blog, positively or negatively, about the new v2 framework using both available information and my own imagination - I'll try to limit the later part (but I make no promise). Let's start with a (really) quick analysis of the new classes included in System.Security.Cryptography namespace of the .NET framework v2 (PDC release) and compare them with what Mono:: already has it's Mono.Security assembly.

DISCLAIMER: Like most of you, my access to information is limited to the MSDN's Longhorn web site. I don't (yet) have to the actual framework v2 installed so this is only my limited understanding of what's new and how it relates to Mono.

New classes

AsnEncodedData
Seems to be a container for ASN.1 data. Unlike Mono.Security.ASN1 and ASN1Convert there seems to be no way to manipulate the ASN.1 data (other than a RawData property).
CspKeyContainerInfo
Expose a lot of properties about CryptoAPI keys. The properties are mainly applicable to asymmetric keypairs, like RSACryptoServiceProvider and DSACryptoServiceProvider, so the class isn't used for symmetric key algorithms, like DESCryptoServiceProvider, RC2CryptoServiceProvider and TripleDESCryptoServiceProvider.
HMAC
Previously the only HMAC avaiable was HMACSHA1, which was required for Xml Digital Signature, and inherited KeyedHashAlgorithm. Mono.Security.Cryptography already as a similar class for handling HMAC with any hash algorithm.
HMACMD5
HMAC using MD5. Easy as we have both managed HMAC and MD5.
HMACRIPEMD160
HMAC using RIPEMD160. We'll need a RIPEMD160 implementation.
HMACSHA256
HMAC using SHA256. Easy as we have both managed HMAC and SHA256.
HMACSHA384
HMAC using SHA384. Easy as we have both managed HMAC and SHA384.
HMACSHA512
HMAC using SHA512. Easy as we have both managed HMAC and SHA512.
Oid
ASN.1 encoded object identifiers. All cryptographic algorithms got one, so here's the way to keep your hands clean. Mono.Security.ASN1 already has methods for converting OID to/from strings.
OidCollection
A collection of OIDs.
OidEnumerator
The OID's enumerator. No big surprise here ;-).
ProtectedData
Wrapper into CryptoAPI CryptProtectData. An easy and secure way would be to use P/Invoke on Windows (XP+) and something similar on Linux. But I would much prefer a managed implementation - or maybe with just a little help from the runtime...
ProtectedMemory
Wrapper into CryptoAPI CryptProtectMemory. Same comment.
Rfc2898DeriveBytes
Password-based key derivation using PKCS#5 version 2 PBKDF2. The current PasswordDerviceBytes is also based on PKCS#5 (version 1) with some modification at extends the key size when required.
RIPEMD160
Abstract base class for all RIPEMD160 implementations. RIPEMD-160 is an european hash algorithm optimized for 32bits processors. More informations are available here.
RIPEMD160Managed
A managed implementation of RIPEMD160.

New interface

ICspAsymmetricAlgorithm
Defines two methods ExportCspBlob and ImportCspBlob and one property CspKeyContainerInfo. The two methods are probably very similar to Mono.Security.Cryptography.CryptoConvert class.

New enumerations

DataProtectionScope
Scope of data protection: CurrentUser and LocalMachine
KeyNumber
Not quite numbers but it should match the same CryptoAPI definitions for Exchange and Signature.
MemoryProtectionScope
Scope of memory protection: SameProcess, CrossProcess and SameLogon.

Of interest

DSACryptoServiceProvider, RSACryptoServiceProvider
Both classes now implements the new ICspAsymmetricAlgorithm interface. It should be easier to exchange keypairs between managed and unmanaged code.
DSA
The constructor of the abstract class DSA is no more internal. It should now be possible to create derived implementation of DSA (like a DSAManaged class).
CipherMode
No new mode of operation but no symmetric algorithms implemented the CFB or CTS cipher mode in v.1.0 and v.1. I'm curious to see if this has changed...
PaddingMode
Also of interest, two new padding mode ANSI X9.23 and ISO 10126. I wonder if one of them is the padding used by XmlEncryption which is (just a little) different than PKCS #7 and cause some interoperability problems with Microsoft WS-Security implementation.

There are probably many other changes insides the existing classes. Eventually I'll investigate them further... but for the time being I prefer quick surfing to deep diving :-)


10/28/2003 20:37:29 | Comments | Permalink

WS-Security - slow but steady progress

I know I promised to keep quiet during PDC but it's not really started so... anyway no one started bloging about it yet, so my promise isn't broken ;-).

After much more time than anticipated, actually much more classes implemented than I expected (which is a more positive view of my time), I can now use Mono's WSE implementation to encrypt a request, using a X.509 certificate, to a web service.

I did so by modifying my previous example (the one I copied from an MSDN article):

[STAThread] static void Main(string[] args) { Username proxy = new Username (); UsernameToken tok = new UsernameToken ("poupou", "password", PasswordOption.SendHashed); proxy.RequestSoapContext.Security.Tokens.Add (tok); X509Certificate x509 = X509Certificate.CreateCertFromFile (@"..\..\server.cer"); X509SecurityToken xst = new X509SecurityToken (x509); EncryptedData ed = new EncryptedData (xst); proxy.RequestSoapContext.Security.Elements.Add (ed); try { Console.WriteLine (proxy.PersonnalHello ()); } catch (Exception e) { Console.WriteLine (e.ToString ()); } }

This generates the following SOAP request. Apart from the (missing) routing headers this is very similar to the Microsoft WSE version would generate. Which is why IIS had no problem decrypting it.

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" ...> <soap:Header> <wsu:Timestamp xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility"> <wsu:Created>2003-10-25T19:58:29Z</wsu:Created> <wsu:Expires>2003-10-25T20:03:29Z</wsu:Expires> </wsu:Timestamp> <wsse:Security soap:mustUnderstand="1" xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/07/secext"> <wsse:UsernameToken wsu:Id="SecurityToken-45a0ef45-6d9d-408a-bd99-17f15e0bccc1" ...> <wsse:Username>poupou</wsse:Username> <wsse:Password Type="wsse:PasswordDigest">v76oaS0a8xct5vQ16vbafBIEPig=</wsse:Password> <wsse:Nonce>i43pLvPilkHAc5cJDG9twQ==</wsse:Nonce> <wsu:Created>2003-10-25T19:58:29Z</wsu:Created> </wsse:UsernameToken> <xenc:EncryptedKey Type="http://www.w3.org/2001/04/xmlenc#EncryptedKey" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" /> <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> <wsse:SecurityTokenReference> <wsse:KeyIdentifier ValueType="wsse:X509v3">AuGnMlSu/cCkMjb2/iNqA3Iosfc=</wsse:KeyIdentifier> </wsse:SecurityTokenReference> </KeyInfo> <xenc:CipherData> <xenc:CipherValue>yziZ+MYDRTuFEnNAEH6d7eH3ZK7fK0WlQf/fWWvBJsqA1+9nHCp3w9B/9oEIC8tgv1T/ ...</xenc:CipherValue> </xenc:CipherData> <xenc:ReferenceList> <xenc:DataReference URI="#EncryptedContent-96e3ddc5-be73-4aef-a244-d7b8aa26121e" /> </xenc:ReferenceList> </xenc:EncryptedKey> </wsse:Security> </soap:Header> <soap:Body wsu:Id="Id-38917d98-eeab-41e4-b640-6f3a033f8da8" xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility"> <xenc:EncryptedData Id="EncryptedContent-96e3ddc5-be73-4aef-a244-d7b8aa26121e" ...> <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" /> <xenc:CipherData> <xenc:CipherValue>kq9yNn7L4rUbo/rOvOi4ZVcH4RVxvOrVf4H4UTVYVhMS8aBPA15uaiHDbJ6YjLZ04M/DPG7VK3M= </xenc:CipherValue> </xenc:CipherData> </xenc:EncryptedData> </soap:Body> </soap:Envelope>

But if you remember the first post you may notice that this sample really don't do much. That's because there's (almost) nothing in the soap body, the interesting part was the UsernameToken which is unencrypted. Well the promised sample is for another time.

Talking of the beast I still haven't figured out how to generate the UsernameToken signing key, but I know from the newsgroup that I'm not the only one looking. Anyone at the PDC can extract this information from some (drunk and/or supportive) MS WSE guy ? I can name a few if this helps... >:-)


10/25/2003 23:34:50 | Comments | Permalink

A last blog before PDC

Primates' Miguel, Gonzalo and Lluis are present, or will soon be, at the PDC. I hope they have a good time and blog a lot about it ;-). As for the few unlucky others out there I was told that the same 2.0 beta framework would be included soon in MSDN subscriptions, however Longhorn is only available at PDC - but this is something I can live with.

Can someone bring me back a Mono t-shirt ? I wonder is the sold-out of Mono's t-shirt is somewhat related to the sold-out of the PDC ;-).

Update: John St. Clair tells me that we may see Longhorn soon in MSDN. Let's hope there will be some new API documentation supplied with it...


10/24/2003 21:30:55 | Comments | Permalink

Back to WSE

Now that code signing, both strongnames and authenticode, support are included into corlib, with a big thanks to Zoltan for the runtime part, let's get back to Web Services Enhancements.

Lately Todd has been doing a great job to support the still in-flux, as in breaking changes, WSE 2 Technical Preview. As for myself I've set my own goal - I wanna to make a secure web service sample ;-). No kidding - not just some samples about security but something that may prove useful in some real life problems. Of course this will be entirely done using Mono:: while implementing WS-Security.

As with many of my stories it all starts with someone using a client application (I never said this would be intriguing). The user needs to authenticate to a web service. Using X.509 certificates would be cool, and make my professional life much easier, but that's just not reality (no sci-fi here). Real dictates that most users still authenticate with password (and associated office tools). So let's do this right and start by hashing the password (PasswordOptions.SendHashed) so no one can read it in transit.

The next step would be assure the confidentiality of the user's requests. Nobody want to see it's credit card numbers transmitted in clear on the internet (and only few actually cares that it's not the way credit card numbers are stolen on the net). Here is a good, real life example, of how X.509 certificates are used today on the internet. Servers have their own certificates, binded to their DNS entries, so you can establish a trusted link from a client to the server (and yes directions matters). This can be done by using SSL/TLS or by using XML Encryption.

But we're still missing something between the client and the server. Anyone can use the server X.509 certificate, so anyone can establish a trusted communication between itself and the server. What we are lacking (most) is integrity - we do not want someone else to get, somewhere somehow, your post-it credentials. The timestamp inside the UsernameToken may help by limiting the vulnerability window - it's a nice addition but it's not enough. For this we need digital signature which is possible, albeit with very limited non-repudiation, using a password. However this isn't very well documented in the current WS-Security specifications but it is possible using the WSE's UsernameToken.SignatureKey.

So without required any major investment/burden on the user, like a PKI, we can send an request to a web service with a good level of trust. Now what's the server gonna do with it ? With a little luck (and interop) the service will process your request and sent you back a response. If you used SSL/TLS to send your request then the same encrypted channel will be used to send you back the response. In this case this works well because you have demonstrated your trust on the server or you wouldn't have sent your request to it, would you ?

But, the interesting case is, what happens if you used XML Encryption ? It was easy (well it may look so) to use the server's certificate to encrypt your request but the server can't do the same - as the users don't have their own X.509 certificate (that's my story and I'm sticking to it). For this we need a shared secret between the client and the server. The server can use this secret, as a symmetric key, to encrypt it's response. Getting the secret from the user to the server can be done by including it into, the encrypted part, the request.

What about the integrity of the response ? This one is easy because the server can sign the response using it's own certificate. The users just have to verify the response's signature. Again trust of the server is implied by the fact that you wouldn't have sent the request if you didn't trust the server.

This should make an interesting sample and keep me busy, both coding and blogging, for some time...

Questions: How do you trust the servers ? the certificates ? the DNS entries ? or your own computer ? if you can't I would suggest you my wireless brick but it's not for sale ;-)


10/18/2003 23:46:38 | Comments | Permalink

.NET Security Tools Roundup

Seems I've been talking about many tools recently. Just to add to the confusion here are all the security tools that are currently available with Mono:: - at least in CVS ;-)

makecert.exe
This tools lets you create many kind of X.509 certificates, like root (self-signed) certificates, SSL certificates (both client and server) and, more .NET aligned, Software Publisher Certificates for digitally signing PE executable using Authenticode®. This tools is for test purpose only as the generated certificates won't, by default, be trusted by anyone. You need to buy a code-signing certificate from a commercial certificate authority (CA) to be trusted.
cert2spc.exe
This tools let you construct a SPC (Software Publisher Certificate) file (looks grandiose but it's only a PKCS#7 file) out of many certificates (normally a chain) and CRLs. This SPC is the only format supported by signcode so this is a rather important step to sign assemblies.
signcode.exe
This tool lets you digitally sign any PE executable (EXE, DLL, OCX ... and CLR assemblies) using a private key (PVK file generated by makecert.exe) and a Software Publisher Certificate (SPC file generated in steps by makecert.exe and cert2spc.exe>.
chktrust.exe
This tool lets you verify that a PE executable has a valid Authenticode® digital signature embedded into itself.
sn.exe
This tools lets you create a strongname keypair, resign assemblies and verify assemblies signature. Unlike signcode/chktrust the signature isn't binded to it's owner (via a certificate) so it can only assure the integrity of an assembly (not it's origin). Note that the first signature, delayed or not, must be done by the compiler using attributes.
secutil.exe
This tools let you extract a X.509 certificate (Authenticode®) or a StrongName public key from an existing assembly in a format usable by C# or VB.NET (either in decimal or hexadecimal).

All the provided tools are 100% managed (but not all 100% complete) versions of the Microsoft .NET Framework SDK tools. With the exception of secutil.exe all tools requires the assembly Mono.Security.dll to execute. This is just a proof that the current .NET frameworks aren't, by themselves, complete enough to support its own tools. If you need more security stuff than the framework actually provides, have a look at Mono.Security.dll assembly.

Same trick if you ever wondered about the internal of any of those tools, check their source code under /mcs/tools/security for each tool and under /mcs/class/Mono.Security for the Mono.Security.dll assembly. Mono's source code is a great place to learn!

So far so good, now what does the PDC have in store for us? and no I won't be there :( so you all better blog about it! If you do I'll keep silent, if you don't...


10/15/2003 19:28:50 | Comments | Permalink

Strangest X509Certificate ever seen ?

The source code at the end of this post does a Authenticode® self-check. That is, it check if it has, itself, been signed by a X.509 certificate. This is done using the (rather crudely documented) X509Certificate.CreateFromSignedFile.

If the assembly is signed you would expect a valid X509Certificate as the output, would you? Well you got it. Or if the assembly has been modified, so the code signature doesn't verify, you would expect an exception, right? Got it again. But if the assembly wasn't signed what would you expect ?

  1. null
  2. DivideByZeroException
  3. X509Certificate

If you expected a null, then you'll be (at least) disappointed and probably surprised at lot the first time you run your program. If you expected a DivideByZeroException then you should stop reading my blog right now and go to sleep - do not try again unless you have slept for a minimum of 8 straight hours. If you (really) expected an X509Certificate then tell me, without looking to the source code, what it should contains ?

Actually it doesn't contains much and the best way to detect it is to call GetHashCode () and check if it returns 0. As I said i'm unsure if this a feature or a bug - but it certainly complicates unit testing (and not only for Mono ;-).

Here's the promised code for doing an Authenticode® self-check on an assembly. This works on both Mono (post 0.28, which means CVS right now) and the Microsoft framework.

using System; using System.Reflection; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; public class MainClass { public static void Main (string[] args) { Assembly self = Assembly.GetEntryAssembly (); try { X509Certificate x509 = X509Certificate.CreateFromSignedFile (self.Location); if (x509.GetHashCode () != 0) Console.WriteLine (x509.ToString (true)); else Console.WriteLine ("Assembly isn't signed by a software publisher certificate"); } catch (COMException ce) { // using a test certificate without trusting the test root ? Console.WriteLine (ce.Message); } } }

Hmmm... a little explaination may not hurt everyone, so:

> makecert.exe -n "CN=your name" -sv yourkeypair.pvk yourcert.cer
Succeeded
 
> cert2spc.exe yourcert.cer yourspc.spc
Succeeded
 
> signcode.exe -v yourkeypair.pvk -spc yourspc.spc -t http://timestamp.verisign.com/scripts/timstamp.dll selfcheck.exe
Succeeded
 
> chktrust.exe selfcheck.exe
Succeeded
 
> selfcheck.exe
CERTIFICATE:
Format: X509
Name: CN=your name
Issuing CA: CN=Root Agency
Key Algorithm: 1.2.840.113549.1.1.1
Serial Number: 88488DD7C38FED4E907DB55418353D04
Key Alogrithm Parameters: 0500
Public Key: 30818902818100BB16FBE837D1B326BA547936A4CE3068FC63AE5D9F885
12339A372CC564F77E5ECA1087F27B9523A23E9D7F0B8B11FA63BB03A8890CC2CB21E75F0215F267
F56FC4A96174BC17C7585835E312BBE320F22C26970EA1A282898C52BE090B511AFDF88C14437BB5
E0402257C3CFA34BCA324C8660A1A4F0BAB479403C8FFD5E99B0203010001

Notes:

  1. Under Windows and the MS runtime you have to add trust to the test root in order for this demonstration to work, otherwise the self-check will fail with the message: The certification path terminates with the test root which is not trusted with the current policy settings.
  2. You must add mono before each command when using the Mono:: runtime.

Actually the title is a little misleading - it is strange but surely not the strangest X.509 certificate you can find. Warning: This is a funny read whether or not you care about X.509 certificates (in the last case just read the citations).


10/12/2003 20:28:02 | Comments | Permalink

May the strongest survive...

... and I'm still alive ;)

Source code to generate and validate strongname signatures is now in CVS under/mcs/class/Mono.Security/Mono.Security/StrongName.cs while the code for the SN tool can be found under /mcs/tools/security/SN.cs.

It's probable not (yet) 100% bulletproof but I was able to sign Mono's corlib using this code. If you're interested in testing this out please report any bugs into bugzilla.

There are many articles on the web (including MSDN) which explains how to strongname assemblies - so I won't blog about this. However there's (at least today) a bug in mcs which makes it include the whole keypair (i.e. both the private and public key) inside the assembly. So most explanation you'll find right now can't be applied to Mono yet.

Here's a temporary solution which works with Mono (and not restricted to Windows) using latest CVS...

1. Extract the public key from the StrongName keypair (the hello.snk from previous example)

> sn -p hello.snk hello.pub

2. Modify helloworld.cs to
a. reference the file containing only the public key (hello.pub)
b. use delay signing (as mcs cannot, yet, sign the assembly)

-[assembly: AssemblyKeyFile ("hello.snk")] -[assembly: AssemblyDelaySign (true)] +[assembly: AssemblyKeyFile ("hello.pub")] +[assembly: AssemblyDelaySign (false)]

3. Recompile the helloword assembly.

> mcs helloworld.cs

4. Sign the assembly using sn

> sn -R helloworld.exe hello.snk

5. Validate the assembly

> sn -v helloworld.exe

Now a GAC would be cool to support both WSE1 and WSE2 under Mono. Any takers ?


10/11/2003 16:05:39 | Comments | Permalink

Back to treasure iSlaNd - follow the map until you hit a 0

Note: This is a direct follow-up to while (being(stubborn) + bruteforce < strongname) { !Sleep(); }

Well there are a lot of 1 on this map - which only makes it easier to follow. 0's are visible in three sections:

  • 4 bytes @ 0xd8 (the PE checksum)
  • 8 bytes @ 0x110 (the Security/Certificate directory - RVA and size)
  • 16 bytes at 0x1f0 (padding before first section)

The first two spots were expected because Authenticode® signatures are similar (see /mcs/class/Mono.Security/Mono.Security.Authenticode/AuthenticodeBase.cs). The third one is the padding before the first section.

Add to this the actual signature (128 bytes starting, in our case, at position 0x250 - defined in "Partition II Metadata", section 24.3.3), which cannot be modified for validation but, obviously, isn't part of the assembly hash.

But this isn't yet the complete solution. The previous four sections may each either be excluded from the hash (like the first two are in Authenticode®) or zeroized before hashing. Well when there's more than one X on a treasure map you better be prepared to dig more than one hole. At this stage computing hashes (for all possibilities) is easy - but not enough. We need to compare our hash results with the "real" hash used for the signature - and you may find it meaningful to know that an RSA signature is actually an encrypted padded-hash ;-). As we know where the signature is (at 0x250) by using some PE tools or the documentation this should be easy, no? Well it turns out that Microsoft RSA's implementation, based on CryptoAPI, doesn't let you get the decrypted hash (RSACryptoServiceProvider.DecryptValue throws a NotSupportedException). But we're lucky because Mono has a managed RSA implementation - so we have an easy way to our decrypted hash (which is the last 20 bytes of the decrypted signature - the rest being the PKCS#1 padding).

Here is the decrypted hash: 46-65-DA-3D-2B-64-B0-CB-E4-63-60-C2-2D-42-09-9D-E7-02-C4-4F for the helloworld.exe assembly

After some more trials and errors (like using the map file, not the actual EXE file) I finally got a hit! The first two (checksum and security directory entry) are zeroized (unlike Authenticode®, while the last two (padding and signature) are skipped. Here's the source code:

static void Main(string[] args) { const byte marker = 0x00; byte[] data = ReadFile ("helloworld.exe"); // PE checksum data [0x00d8] = marker; data [0x00d9] = marker; data [0x00da] = marker; data [0x00db] = marker; // security directory data [0x0118] = marker; data [0x0119] = marker; data [0x011a] = marker; data [0x011b] = marker; data [0x011c] = marker; data [0x011d] = marker; data [0x011e] = marker; data [0x011f] = marker; SHA1 hash = SHA1.Create (); hash.Initialize (); hash.TransformBlock (data, 0, 0x1f0, data, 0); // skip padding (16 bytes) hash.TransformBlock (data, 0x200, 0x50, data, 0x200); // skip signature (128 bytes) hash.TransformFinalBlock (data, 0x2d0, data.Length - 0x2d0); Console.WriteLine (BitConverter.ToString (hash.Hash)); }

Using this treasured, and now publicly shared, knowledge I should now be able to re-sign/validate a simple assembly :-).

Wait a minute! How about delay signing ? There must be some things to do before signing, for the first time, an assembly.

Actually by using the same "map" trick it's easy to see the differences between a signature delayed assembly and a really signed assembly. Results are:

  • 2 bytes @ 0xd8 (parts of the PE checksum, the other 2 bytes were already 0)
  • 1 bytes @ 0x218 (the CLI header flags, which is part of the previous hash calculation, equals to 0x9 COMIMAGE_FLAGS_ILONLY | COMIMAGE_FLAGS_STRONGNAMESIGNED)
  • 128 bytes (1024 bits) at 0x250 (the signature, un-hashed)

That last part was easy, but two challenges remains: First mcs must output a delay signed assembly (I'll leave that to Miguel or other mcs gurus) and, second, generalizing the process (mainly testing) for more elaborate assemblies (including resources, Authenticode® signatures ...).


10/8/2003 22:42:05 | Comments | Permalink

while (being(stubborn) + bruteforce < strongname) { !Sleep(); }

I was disappointed to see that the Hash class wasn't (enough) related to StrongName. It left me (again) clueless :-(. Being back to square one I needed another, more radical and systemic, approach to the problem. So there I was sleepless in the middle of the night (perhaps a coincidence?) thinking about going back to the most basic stuff, like:

My favorite "Hello world" program:

using System; using System.Reflection; [assembly: AssemblyKeyFile ("hello.snk")] [STAThread] public class MainClass { public static void Main (string[] args) { Console.WriteLine ("Hello world!"); } }

So far so good, next create a StrongName keypair (sn -k), compile and automatically strongname it with the included AssemblyKeyFile attribute - so for the moment it must be done with csc not mcs.

> sn -k helloworld.snk
> csc helloworld.cs

Now let's verify it with ... hmm... Microsoft's sn tool. What do I get? A success (somewhat expected) and an exit code equals to 0 (right now you'll need to trust me on this ;-).

> sn -v helloworld.exe

Armed with knowledge that my helloworld.exe was correctly strongnamed, it became obvious that I needed to bruteforce further knowledge (believe me being stubborn isn't always enough). So if I changed the very first byte, would it still be a valid strongnamed assembly? and if I changed the second byte ? ... until the last byte ? and all the while keeping the result on a map.

Actually I didn't do this in my head (nor in my bed). I waited to get back to my computer (and waiting doesn't help sleeping very much). Anyway this ended up looking like this:

using System; using System.Diagnostics; using System.IO; class StrongNameTheHardWay { static int CheckStrongName () { Process p = Process.Start ("sn", "-v hellosn.exe"); p.WaitForExit (); return p.ExitCode; } static byte[] ReadFile (string filename) { FileStream fs = File.OpenRead (filename); byte[] data = new byte [fs.Length]; fs.Read (data, 0, data.Length); fs.Close (); return data; } static void WriteFile (string filename, byte[] data) { FileStream fs = File.OpenWrite (filename); fs.Write (data, 0, data.Length); fs.Close (); } [STAThread] static void Main(string[] args) { byte[] data = ReadFile ("helloworld.exe"); fs.Read (data, 0, data.Length); fs.Close (); byte[] map = new byte [data.Length]; byte old; WriteFile ("hellosn.exe", data); if (CheckStrongName () == 0x00) { for (int i=0; i < data.Length; i++) { old = data [i]; data [i] ^= 0xFF; WriteFile ("hellosn.exe", data); if (CheckStrongName () != 0x00) map [i] = 1; data [i] = old; if (i % 1024 == 0) Console.WriteLine (i); } WriteFile ("hellosn.map", map); } else Console.WriteLine ("original not strongnamed"); } }

Compiling, running and waiting... (at that particular moment I had the distinct feeling I could easily sleep).

> csc brutesn.cs
> brutesn.exe

Note : It's possible that your anti-virus will not appreciate the full subtleties of systematically messing with an EXE. Also sn isn't always very happy about every possible mutation you can force on a PE file (in this case just click Ok to continue).

Note to self : Compiling with debugging information only makes it much longer than necessary.

Oops, did I fell asleep? Anyway it seems I now have my own personal treasure map to interpret... To be continued


10/7/2003 20:18:46 | Comments | Permalink

First WSE client for Mono

Today I got the Mono' implementation of WSE to send a SOAP request containing a WS-Security UsernameToken (based on the first sample of MSDN's WS-Security Authentication and Digital Signatures with Web Services Enhancements) and Timestamp. However this only works (right now) under Windows. Now I just got to make this works with the mono runtime, then make the web service runs under XSP.

What I really like about WSE it's that it doesn't requires much code to use. Here's the sample client code:

using System; using Microsoft.Web.Services.Security; class UsernameTokenTest { [STAThread] static void Main(string[] args) { Username proxy = new Username (); UsernameToken tok = new UsernameToken ("poupou", "password", PasswordOption.SendHashed); proxy.RequestSoapContext.Security.Tokens.Add (tok); try { Console.WriteLine (proxy.PersonnalHello ()); } catch (Exception e) { Console.WriteLine (e.ToString ()); } } }

And the service code:

[WebMethod] public string PersonnalHello () { string response = ""; SoapContext requestContext = HttpSoapContext.RequestContext; if (requestContext == null) throw new ApplicationException ("non SOAP request"); foreach (SecurityToken tok in requestContext.Security.Tokens) { if (tok is UsernameToken) response += "Hello " + ((UsernameToken)tok).Username; } if (response == "") response = "unauthenticated request"; return response; }

and, finally, the PasswordProvider:

public class PasswordProvider : IPasswordProvider { public string GetPassword (UsernameToken token) { return "password"; } }

Never been so excited to see Hello poupou written on the console ;-)


10/4/2003 16:16:13 | Comments | Permalink

Clean-up day...

Ben asked every Mono's bloggers to clean up their RSS/HTML mess. Now that I'm "web legal" I decided to inclue both HTML and CSS buttons on the page (as a remainder to stay legal). Thanks for looking for us Ben, but I'm unsure that you don't like being the markup cop ;-).

Knowing Ben, I can't wait to see monologue in action. This will rock!


10/3/2003 22:28:07 | Comments | Permalink

The views expressed on this website/weblog are mine alone and do not necessarily reflect the views of my employer.