Pierre Greborio.NET

Talking about .NET world

September 2003 - Posts

SHA-1 algorithm for Compact Framework

Compact Framework lacks of Cryptography support. If you have to hash a string you can't use SHA1CryptoServiceProvider since it isn't  supported on CF. One of the available workaround is to use Win.CE (2.10 and later) SDK functions through P/Invoke.

I developed a simple helper function that get a string as parameter and returns it's hashed value. I want to share here the code so that if somebody else will encounter the same issue can save some times :-D

Here is the code:

public static string HashString(string textToHash)
{
 string hashValue = string.Empty;

 if(textToHash == null || textToHash == string.Empty)
  throw new ArgumentNullException("textToHash", "The text to hash cannot be null.");

 const int PROV_RSA_FULL = 1;
 const int CALG_SHA1   = 0x8004;
 const int HP_HASHSIZE = 0x0004;
 const int HP_HASHVAL  =  0x0002;

 IntPtr hHash = IntPtr.Zero;
 IntPtr hProv = IntPtr.Zero;

 // Obtain handle to the default key container
 if(!HashNative.CryptAcquireContext(ref hProv, null, "Microsoft Base Cryptographic Provider v1.0", PROV_RSA_FULL, 0))
  throw new Win32Exception(Marshal.GetLastWin32Error());
 else
 {
  try
  {
   // Obtain handle to hash object.
   if(!HashNative.CryptCreateHash(hProv, CALG_SHA1, IntPtr.Zero, 0, ref hHash))
    throw new Win32Exception(Marshal.GetLastWin32Error());
   else
   {
    byte[] buffer = System.Text.Encoding.ASCII.GetBytes(textToHash);

    // Hash data.
    if(!HashNative.CryptHashData(hHash, buffer, buffer.Length, 0))
     throw new Win32Exception(Marshal.GetLastWin32Error());

    // Get size of hash value.
    int bufLen = Marshal.SizeOf(typeof(uint));
    byte[] hashBuf = new byte[bufLen];
    HashNative.CryptGetHashParam(hHash, HP_HASHSIZE, hashBuf, ref bufLen, 0);

    // Get hash value.
    bufLen = hashBuf[0];
    hashBuf = new byte[bufLen];
    if(!HashNative.CryptGetHashParam(hHash, HP_HASHVAL, hashBuf, ref bufLen, 0))
     throw new Win32Exception(Marshal.GetLastWin32Error());

    // Convert to base 64 string
    hashValue = Convert.ToBase64String(hashBuf, 0, bufLen);
   }
  }
  finally
  {
   // Release hash object.
   if(hHash != IntPtr.Zero)
    HashNative.CryptDestroyHash(hHash);

   // Release context object
   if(hProv != IntPtr.Zero)
    HashNative.CryptReleaseContext(hProv, 0);
  }
 }

 return hashValue;
}

The native declarations are:

internal class HashNative
{
 [DllImport("CoreDLL.Dll", SetLastError=true)]
 internal extern static bool CryptAcquireContext(ref IntPtr hCryptProv, string containerName, string providerName,
  int providerType, uint providerFlags);

 [DllImport("CoreDLL.Dll", SetLastError=true)]
 internal extern static bool CryptReleaseContext(IntPtr hCryptProv, uint providerFlags);

 [DllImport("CoreDLL.Dll", SetLastError=true)]
 internal extern static bool CryptCreateHash(IntPtr hProv, int algId, IntPtr hKey, uint dwFlags, ref IntPtr phHash);

 [DllImport("CoreDLL.Dll", SetLastError=true)]
 internal extern static bool CryptDestroyHash(IntPtr phHash);

 [DllImport("CoreDLL.Dll", SetLastError=true)]
 internal extern static bool CryptHashData(IntPtr hHash, byte[] pbData, int dwDataLen, uint dwFlags);

 [DllImport("CoreDLL.Dll", SetLastError=true)]
 internal extern static bool CryptGetHashParam(IntPtr hHash, int dwParam, [in,Out] byte[] pbData, ref int pdwDataLen, uint dwFlags);
}

Note that the above code is for demo purpose only and I don't have any responsability for it's usage. You can use and modify it freely.

RegularExpressionValidator

The RegularExpressionValidator validate an input user control content based on a regular expression. Then, if you want have a string of length between 1 and 20 containing a single word (without blank spaces) you can add the following regular expression to the validator:

^\w{1,20}$

Unfortunately, this isn't sufficient. A note on MSDN library states:

Note   Validation succeeds if the input control is empty. If a value is required for the associated input control, use a RequiredFieldValidator control in addition to the RegularExpressionValidator control.

I sincerly don't agree with that design decision since if the regular expression states that the string must be at least 1 character long, why should I have to use two validators ? The entropy of our code grows uselessly.

The only workaround I found on client side is to edit the function RegularExpressionValidatorEvaluateIsValid on WebUIValidation.js file. Just commenting the following lines of code:

if (ValidatorTrim(value).length == 0)
  return true;

It seems to work now.
Posted: Sep 15 2003, 01:17 PM by PierreG | with 1 comment(s)
Filed under:
Attribute-based data validation

Attributes gives a great power for some kind of control over entities, operations and attributes in OOP. NewTelligence posted an interesting library that uses, in a clever manner, custom attributes to validate the data of business objects.

Though it is complete for most of scenarios, I think it lacks on other. Validation rules aren't "absolute" defined. They can depends from two factors: current user and context. For example, you could have a field (or property) that is mandatory if the user is a manager whereas optional for an employee. Or, you could have a property that is mandatory for a customer but it isn't for a prospect. Then, it should be nice to add also the concept of role and context, more or less as ASP.NET does.

Anyway, that is a very good starting point for building a complete and efficient data validation system.

InfoPath 2003 reference
Axiom: "I like InfoPath 2003" ;-) Yes, that's a great tool that solves a common business problem: data gathering. Well, we could implement a lot of nice web sites (ASP.NET obviously) or Windows clients, but the productivity of InfoPath cannot be equalled. Today there is only one problem: there isn't a lot of documentation about this product. I found an interesting web site talking about InfoPath. This is a good reference. 
"Real world" application

I am reviewing some TechEd 2003 (European edition) sessions and I noted the usage, and misusage, of the sentence "real world applications". There's somebody developing unreal applications ?

I personally think that we can have two categories of applications: business applications and study/test/personal applications. Both of them are "real".....hopefully.

More Posts