Jul 22, 2009

Create Salt/IV file for password

This code demonstrates that the salt and initialization vector (IV) are persisted unencrypted to a .dat file. In this way you can see how you would securely send a document to someone: The encrypted document could be sent over an unsecure wire, and the .dat file and password could be transferred securely using assymetric (or, public key) encryption.

using System.Text.RegularExpressions;
using System.Security.Cryptography;

private SampleCrypto crpSample;

This routine handles the "Create Salt / IV Key" button click event.

private void btnCreateKey_Click(object sender, System.EventArgs e)
{
try {
if (PasswordIsValid())
{
crpSample.Password = txtPassword.Text;
}
else
{
return;
}

if (crpSample.CreateSaltIVFile(strCurrentKeyFile))
{
MessageBox.Show("Salt and IV successfully generated and saved to a .dat " + Environment.NewLine +
"file in the Visual Studio .NET Solution root folder.",
this.Text,MessageBoxButtons.OK,MessageBoxIcon.Information);
}
}
catch( Exception exp)
{
MessageBox.Show(exp.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}


This routine validates the password.

private bool PasswordIsValid()
{
if (!Regex.IsMatch(txtPassword.Text, @"^\s*(\w){8}\s*$"))
{
MessageBox.Show("You must enter an 8-digit password consisting of numbers " +
"and/or letters.", this.Text,MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return false;

}
return true;
}


This routine creates a .dat file containing the salt and IV.

public bool CreateSaltIVFile(string strSaveToPath)
{
// Initialize the byte arrays to the proper length for the
// instantiated crypto class.

ReDimByteArrays();

// Create a Filestream object to write the salt and IV to a file.

FileStream fsKey = new FileStream(strSaveToPath, FileMode.OpenOrCreate,
FileAccess.Write);

// Generate a random "salt" value.
RandomNumberGenerator rng = RandomNumberGenerator.Create();

rng.GetBytes(abytSalt);

PasswordDeriveBytes pdb = new PasswordDeriveBytes(strPassword, abytSalt);

// Get the same amount of bytes the current abytKey length set in
// ReDimByteArrays().

abytKey = pdb.GetBytes(abytKey.Length);

// Generate a new random IV.

crpSym.GenerateIV();
abytIV = crpSym.IV;

try
{
fsKey.Write(abytSalt, 0, abytSalt.Length);
fsKey.Write(abytIV, 0, abytIV.Length);
strSaltIVFile = strSaveToPath;
return true;
}
catch( Exception exp)
{
throw new Exception(exp.Message);
}
finally
{
fsKey.Close();
}
}


This routine redimensions the byte arrays to the proper length for the instantiated crypto class.

private void ReDimByteArrays()
{
// For testing purposes only, write out the legal key sizes.

Debug.WriteLine(crpSym.GetType().ToString() + " legal key sizes in bits:");

foreach(KeySizes myKeySizes in crpSym.LegalKeySizes)
{
Debug.WriteLine("Max=" + myKeySizes.MaxSize + " bits " +
"(" + (myKeySizes.MaxSize / 8) + " bytes)");

Debug.WriteLine("Min=" + myKeySizes.MinSize + " bits " +
"(" + (myKeySizes.MinSize / 8) + " bytes)");

Debug.WriteLine("Skip=" + myKeySizes.SkipSize + " bits " +
"(" + (myKeySizes.SkipSize / 8) + " bytes)");
}
if (crpSym.GetType() == typeof(System.Security.Cryptography.RijndaelManaged))
{
// The Key byte array size was retrieved via the LegalKeySizes property
// of the crypto object.
abytKey = new byte[31];
// A good rule-of-thumb is to make the salt 1/2 the length of the key.
abytSalt = new byte[15];
abytIV = new byte[15];
}
else
{
abytKey = new byte[23];
abytSalt = new byte[11];
abytIV = new byte[7];
}
}

No comments:

Post a Comment