Tom Goff's .Net Musings

Tidbits of information regarding .Net, C#, and SQL Server.

Archive for August 2007

Sign and Verify Data

leave a comment »

Recently, I needed a way to sign some text using a private RSA key and then verify it with the corresponding public key. I searched around for some simple and straight forward examples, but could not find any. MSDN has an example[^] of both generating[^] and validating[^] signatures, but the examples hard code the hash value.

In order to save others some time figuring this out, I’ve put together a sample program[^] that can generate and validate an RSA signature for a user-provided string. In addition, the program shows how to generate a hash value for a given string.

NOTE: In the interest of security, the private key should not be stored in plain-text as shown by my sample program. It is recommended that the private key be encrypted before being saved anywhere.

Below is a screen shot of the sample application. Before signing or validating the text, you must first load a public or private key, or generate a new public/private key pair. Once the key is loaded you will see the key type (“Private” or “Public”) and the key size (the application defaults to 1024).

If you load a private key, then you can both generate and validate signatures. To generate a signature, enter some text in the first text box. As you type, the base-64 encoded SHA-1 hash value will automatically update below it. Next, when you click the “Generate Signature” button you will see the base-64 encoded RSA signature. Finally, you can validate the signature by clicking “Validate Signature” button, obviously.

If you have a public key loaded, then you can only validate signatures. If you have a public/private key pair then you can load the private key, generate the signature, load the public, then validate the signature.

You can try changing the text after generating the signature, but before validating the signature. This should invalidate the signature, resulting in a message box saying as much. You can also try changing the signature.

There are similar built-in .Net classes, to the ones used by the sample application, for working with DSA (instead of RSA) keys and signatures. Therefore, the translation should be trivial.

Hopefully, this will help someone else save some time when trying to sign some data.

Advertisements

Written by Tom

August 30, 2007 at 12:02 pm

Posted in .Net, C#, Security

XML Serialization Sorrows

with 11 comments

One of the features of our flagship product allows the user to save the results from a T-SQL script (run against one or more SQL Server databases) to a file. These results are stored in XML and can be re-opened and viewed by the user. One problem we have run into is that the XML standard does not allow certain characters[^]. For example, the null (0x00) character is not technically allowed even when encoded as “�” in the XML file.

Before I coded a work-around or fix, I wanted to understand where the problem data was coming from. In one instance, the null character was clearly coming from a string (or varchar) column. The SELECT statement was:

SELECT TOP 1 filename FROM sysaltfiles WITH (NOLOCK)

It turned out that the filename column included a trailing null character, but only on SQL Server 2000. I was able to verify this with Microsoft’s Query Analzyer.

There was another instance of an invalid character showing up, but this time the SELECT statement was:

SELECT password FROM syslogins WITH (NOLOCK)

It appears that syslogins is a view on top of sysxlogins, which defines the password column as a varbinary. When syslogins selects the password from sysxlogins it converts it as-is to a varchar. This produces the invalid characters, because the binary data cannot be converted in this manner.

Beyond these two tables a user can still write a valid SELECT statement which would produce an invalid character like so:

SELECT CHAR(0) AS InvalidChar

Now, I’ve been calling the characters “invalid” when really they are perfectly valid. SQL Server, .Net, ADO.Net, and all the controls used to display this data perfectly supports these characters. Even more, when saving these characters the XML serializer would properly encode them using their hexadecimal value (e.g. “�” for the null character). The problem was with the XML deserialization process.

When loading an XML file with one of these invalid characters, an InvalidOperationException[^] would be thrown with the following message:

There is an error in XML document (<Line>, <Column>). 

This exception had an inner exception of type XmlException[^] and the following message:

‘.’, hexadecimal value 0x00, is an invalid character. Line <Line>, position <Column>.

The code used to deserialize the file was similar to the following:

TestObject testObject = null; 
if (true == File.Exists(Form1.fileName)) { 
    XmlSerializer xs = null; 
    TextReader tr = null; 

    try { 
        xs = new XmlSerializer(typeof(TestObject)); 
        tr = new StreamReader(Form1.fileName); 
        testObject = xs.Deserialize(tr) as TestObject; 
    } 
    catch (Exception ex) { 
        //... Exception caught here ... 
    } 
    finally { 
        if (null != tr) 
            tr.Close(); 
    } 
}

The solution was very simple, but not obvious. Simply wrapping a XmlTextReader[^] around the StreamReader[^] allows the code to properly decode the invalid characters. This change is shown here:

TestObject testObject = null; 
if (true == File.Exists(Form1.fileName)) { 
    XmlSerializer xs = null; 
    TextReader tr = null; 

    try { 
        xs = new XmlSerializer(typeof(TestObject)); 
        tr = new StreamReader(Form1.fileName); 

        // Wrap stream with an XmlTextReader so bad chars are accepted 
        XmlTextReader xtr = new XmlTextReader(tr); 
        testObject = xs.Deserialize(xtr) as TestObject; 
    } 
    catch (Exception ex) { 
        // ... No exception thrown ... 
    } 
    finally { 
        if (null != tr) 
            tr.Close(); 
    } 
}

I’m unsure why the XML standard doesn’t allow all characters (even the null character, when properly encoded), but I’m sure they had/have their reasons. The only down side is that XML files that contain these invalid characters will still be considered invalid by other applications.

I’ve put together a sample project[^] that demonstrates the XML portion of this blog.

Written by Tom

August 23, 2007 at 1:59 pm

Posted in .Net, Ado.Net, C#, Gotcha, SQL Server, Xml