Tải bản đầy đủ (.pdf) (5 trang)

Tài liệu Transferring Login Credentials Securely pptx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (29.81 KB, 5 trang )

[ Team LiB ]


Recipe 5.8 Transferring Login Credentials Securely
Problem
You need to protect login credentials during transmission over the network and when
they are stored within a database.
Solution
Use password hashing and salting with the .NET FormsAuthentication class to control
user authentication and access to the application.
The schema of table TBL0508 used in this solution is shown in Table 5-5
.
Table 5-5. TBL0508 schema
Column name Data type Length Allow nulls?
UserName nvarchar 50 No
PasswordHash nvarchar 50 No
PasswordSalt nvarchar 50 No
The sample code contains two event handlers:
Create Button.Click
Creates a GUID-based salt and generates a hash of the password concatenated
with the salt for a user-specified password. The username, password hash, and salt
are inserted into a database.
Login Button.Click
Retrieves the salt and the hash of the password and salt from the database for the
specified username. The user-entered password is concatenated with the retrieved
salt and the hash is generated. If the hash matches the hash retrieved from the
database, the user is authenticated.
The C# code is shown in Example 5-8
.
Example 5-8. File: ADOCookbookCS0508.aspx.cs
// Namespaces, variables, and constants


using System;
using System.Configuration;
using System.Web.Security;
using System.Data;
using System.Data.SqlClient;

private const String TABLENAME = "TBL0508";

// . . .

private void createButton_Click(object sender, System.EventArgs e)
{
// Create and display the password salt.
String passwordSalt = Guid.NewGuid().ToString( );
passwordSaltLabel.Text = passwordSalt;

// Create and display the password hash.
String passwordHash =
FormsAuthentication.HashPasswordForStoringInConfigFile(
passwordTextBox.Text + passwordSalt, "md5");
passwordHashLabel.Text = passwordHashDBLabel.Text = passwordHash;

// Insert UserName with the password hash and salt into the database.
String sqlText = "INSERT " + TABLENAME +
"(UserName, PasswordHash, PasswordSalt) " +
"VALUES ('" + userNameTextBox.Text + "', '" + passwordHash +
"', '" + passwordSalt + "')";
SqlConnection conn = new SqlConnection(
ConfigurationSettings.AppSettings["DataConnectString"]);
SqlCommand cmd = new SqlCommand(sqlText, conn);

conn.Open( );

try
{
if(cmd.ExecuteNonQuery( ) == 1)
statusLabel.Text = "User created.";
else
statusLabel.Text = "Could not create user.";
}
catch(SqlException)
{
statusLabel.Text = "Could not create user.";
}
finally
{
conn.Close( );
}
}

private void loginButton_Click(object sender, System.EventArgs e)
{
bool isAuthenticated = false;

// Get the password hash and salt for the user.
String sqlText = "SELECT PasswordHash, PasswordSalt FROM " +
TABLENAME + " WHERE UserName = '" + userNameTextBox.Text + "'";
SqlConnection conn = new SqlConnection(
ConfigurationSettings.AppSettings["DataConnectString"]);
SqlCommand cmd = new SqlCommand(sqlText, conn);


conn.Open( );
SqlDataReader dr = cmd.ExecuteReader( );

// Get the DataReader first row containing user's password and salt.
if(dr.Read( ))
{
// Get and display password hash and salt from the DataReader.
String passwordHashDB = passwordHashDBLabel.Text =
dr.GetString(0);
String passwordSalt = passwordSaltLabel.Text = dr.GetString(1);

// Calculate password hash based on the password entered and
// the password salt retrieved from the database.
String passwordHash = passwordHashLabel.Text =
FormsAuthentication.HashPasswordForStoringInConfigFile(
passwordTextBox.Text + passwordSalt, "md5");

// Check whether the calculated hash matches the hash retrieved
// from the database.
isAuthenticated = (passwordHash == passwordHashDB);
}
conn.Close( );

if(isAuthenticated)
statusLabel.Text = "Authentication succeeded.";
else
statusLabel.Text = "Authentication failed.";
}
Discussion
Persisting a user's password can be made more secure by first hashing the password. This

means that an algorithm is applied to the password to generate a one-way
transformation—or hash—of the password making it statistically infeasible to recreate
the password from the hash.
A hash algorithm creates a small binary value of fixed length from a larger binary value
of an arbitrary length. The hash value is a statistically unique compact representation of
the original data. A hash value can be created for and transmitted together with data. The
hash can be recreated at a later time and compared to the original hash to ensure that the
data has not been altered. To prevent the message from being intercepted and replaced
along with a new hash, the hash is encrypted using the private key of an asymmetric key
algorithm. This allows the hash to be authenticated as having come from the sender. For
more information about symmetric and asymmetric key algorithms, see the discussion in
Recipe 5.7
. The .NET Framework classes that implement hash algorithms are:

HMACSHA1

MACTripleDES

MD5CryptoServiceProvider

SHA1Managed

SHA256Managed

SHA384Managed

SHA512Managed
In the sample, the user enters his password, the password is hashed, and then the
combination of user ID and password hash are compared to values stored persistently
such as in a database table. If the pairs match, the user is authenticated, without

comparing the actual password. Because the hash algorithm is a one-way algorithm, the
user's password cannot be recreated even if unauthorized access is gained to the persistent
store where the user's password hash is stored.
The .NET Framework, as part of the FormsAuthentication class, provides the method
HashPasswordForStoringInConfigFile( ) that can hash a password using either SHA1 or
MD5 algorithms. The method is easy to call. It takes two arguments, the password and
the hash algorithm, and returns a string containing the password hash.
Security is never perfect and this technique is no exception. It can be compromised by a
dictionary attack where hash values for most commonly used passwords are generated.
When these values are compared with the hash of the password and a match is found, the
password is then known. To thwart the dictionary attack, a random string referred to as
salt is concatenated with the original password before generating the hash value. The salt
is stored together with the hash of the password and salt. This makes a dictionary attack
much more difficult to perform.
This web page should be used in conjunction with forms-based authentication.
Additionally, this page should be accessed securely (i.e., https to protect the plaintext
password from client to server).
The most secure technique is useless if the password policy does not prevent users from
choosing easy to guess passwords, or if security is compromised by users who write
passwords down on notes attached to their computer monitors, for example.
[ Team LiB ]


×