Example Code

Integrating Windows hashing functions into CVI

Products and Environment

This section reflects the products and operating system used to create the example.

To download NI software, including the products shown below, visit ni.com/downloads.

    Programming Language

  • C

Code and Documents

Attachment

Description

 This example integrates Windows SDK hashing functions into a CVI project.

Hashing functions are used to store passwords safely. Windows SDK includes functions for easily creating a hashed version of a string. Storing a password on the system can be dangerous if another user can read this information back and by-pass the password security level. The usual solution for this problem is to apply some algorithm to the password text to generate a string from which the original password cannot be deciphered. This process is often called "hashing", where a "hash algorithm" is a one-way function that generates a unique signature from an original string passed to it. Being one-way implies that there is no possibility to obtain the original text starting from the hashed output. A good hashing function also has no possibility of collisions (i.e. two different texts that produce the same hashed output).

 

Having a good hashing function reduces the problem of storing passwords anywhere in the system to a procedure like this:

- Let the user input his password the first time

- Hash it and store the hashed text ("signature") on disk (e.g. in the system's registry)

- When the user needs to enter the system again, let him retype his password, hash it and check this hashed text with the signature already stored in the system: if they're the same, the password is correct so let the user come in.

 

This code hashes a user-supplied string, saves it, and checks the hashed string against the saved string.

 

 

21-Mar-2013 Updated following vix note about erroneous memory allocation.

 

How to Use

  1. Extract the files.
  2. Open Hashing.prj in LabWindows/CVI
  3. Run the project
  4. Enter text, hash, and save.
  5. Enter new text, hash, and check. If the new text is the same as the saved text, they will have the same hash. Otherwise, they'll be different.

 

Additional Information

Code Snippet

 

          char          msg[512];

          const BYTE                                                  *rgpbToBeHashed[1] = { NULL };          // Array of strings to hash

          DWORD                                                            rgcbToBeHashed[1];          // Array of string lenghts

          DWORD                                                            error = 0;

          BYTE                                                            *pbHashedBlob;                    // The hashed string

          DWORD                                                            cbHashedBlob;                    // The hashed string length

          CRYPT_HASH_MESSAGE_PARA                    HashPara;          // Data structure used to hash a message

          CRYPT_ALGORITHM_IDENTIFIER          AlgId;                    // Data structure to hold the hash algorithm identifier

 

 

          if (event != EVENT_COMMIT) return 0;

 

 

          GetCtrlVal (panel, Main_txt, msg); rgcbToBeHashed[0] = strlen (msg);

          rgpbToBeHashed[0] = malloc (rgcbToBeHashed[0] + 1);

          strcpy ((char *)rgpbToBeHashed[0], msg);

 

 

          //--------------------------------------------------------------------

          //  Initialize the CRYPT_ALGORITHM_IDENTIFIER data structure.

          AlgId.Parameters.pbData = NULL;

          AlgId.pszObjId = szOID_RSA_MD5;

          AlgId.Parameters.cbData = 0;

 

 

          //--------------------------------------------------------------------

          //  Initialize the CRYPT_HASH_MESSAGE_PARA data structure.

          HashPara.cbSize = sizeof(CRYPT_HASH_MESSAGE_PARA);

          HashPara.dwMsgEncodingType = MY_ENCODING_TYPE;

          HashPara.hCryptProv = 0;

          HashPara.HashAlgorithm = AlgId;

          HashPara.pvHashAuxInfo = NULL;

 

 

          //-------------------------------------------------------------------

          //  Allocated memory for the hashed, encoded blob.

          //--------------------------------------------------------------------

          if (CryptHashMessage (&HashPara, FALSE, 1, rgpbToBeHashed, rgcbToBeHashed,

                                        pbHashedBlob, &cbHashedBlob, NULL, NULL)) {

                    DebugPrintf("The message has been hashed and encoded.\n");

                    Fmt (msg, "%s<%*x[zb1r16] \n", cbHashedBlob, pbHashedBlob);

                    ResetTextBox (panel, Main_hash, msg);

                    SetCtrlVal (panel, Main_size, cbHashedBlob);

          }

          else {

                    error = GetLastError ();

                    goto Error;

          }

 



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?

Example code from the Example Code Exchange in the NI Community is licensed with the MIT license.

Comments
BetaCommunityCo
Member
Member
on

Hashing algo

What hashing algorithm does this use, and how does it compare to say sha-512?

BetaCommunityCo
Member
Member
on

Hashing algo

As far as I can see in SDK documentation, it uses MD5 algorithm. Note that this sample uses some simplified commands included in the system: inside the library several low-level CryptoAPI functions are present with which you can use other algorithms. Look in SDK documentation for more reference.

Kurt Jakobsen
Member
Member
on

I have an .Net (aspx) application that I want to share password with a CVI application (store hashed pwd in registry then typing the pwd in either .Net or CVI should give the same hashed pwd that can be compared with the one in registry).
But I have not been able to find hash functions that give the same hashed string in CVI and .Net.

I tried the CVI project supplied here. Apparently it uses MD5, but it does not give the same hashed string as .net give with the function pasted below.
CVI:
Input: test
Output: 3047692a864886f7d175a03a303821030c682a864886f7d25503013692a864886f7d171a0644746 5737441098f6bcd4621d373cade4e832627b4f6
.Net:
Input: test
Output: 9F7D8627E02F97CC5A52DCB2BA96038FE12F2A34B0FAC50E041359AE13D5EDE8A8A50562DA58BA7 916DA378E7343EF91E85EFBD6A0A70AB237ADA4C2274DF13D
Both the .Net and CVI functions have some parameters to play around with, but I do not know how to set them to provide the same output.
Is there anybody who have managed to compute the same hashed string from .net and CVI (does not need to be MD5,  anything that will provide a secure password checking will do)

using System.Security.Cryptography;
static public string GetCryptString(string str)
{
  Encoder enc = System.Text.Encoding.Unicode.GetEncoder();
  byte[] unicodeText = new byte[str.Length * 2];
  enc.GetBytes(str.ToCharArray(), 0, str.Length, unicodeText, 0, true);
  MD5 md5 = new MD5CryptoServiceProvider();
  byte[] result = md5.ComputeHash(unicodeText);
  StringBuilder sb = new StringBuilder();
  for (int i=0;i<result.Length;i++)
  {
    sb.Append(result.ToString("X2"));
  }
  string sRet = sb.ToString();
}

vix
Active Participant
Active Participant
on

Line 21 of the code snippet is

     AlgId.pszObjId = malloc (strlen (szOID_RSA_MD5 + 1));

Is this right?

Shouldn't this be

     AlgId.pszObjId = malloc (strlen (szOID_RSA_MD5) + 1); ?

As a matter of fact, at line 23 the string szOID_RSA_MD5 is put into AlgId.pszObjId and so I think this should have enough space for the string itself and the terminating '\0' char.

Vix
-------------------------------------------
In claris non fit interpretatio

-------------------------------------------
Using LV from 7
Using LW/CVI from 6.0
RobertoBozzolo
Proven Zealot
Proven Zealot
on

Well, that line is actually useless, as the returned pointer is rewritten two lines after

Running the example in more recent releases of the IDE, infact, returns a warning about a lost memory block on that line. I don't remember where I have taken that line, but it should be really cancelled.

Thanks for pointing me to this: I have updated both the snippet and the attached project.



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?