Introducción:
Esta es una utilidad para generar una clave SHA1 a partir de una clave, con idea de no guardar
la clave en texto plano, también permite crear una clave SHA1 combinando (uniendo) un nombre de
usuario y una clave, esto último lo uso para confirmar que la clave y el usuario es correcta.
Nota:
Las instrucciones que están con un link, te llevará a la ayuda en línea en español, si está
disponible, sino, te llevará a la ayuda en inglés.
Versiones de .NET Framework
Esta utilidad también la tengo hecha con el Visual Studio 2005 (normal) y cuando lo publique
pondré el link, pero por ahora solo está disponible con WPF y .NET Framework 3.0.
Un poco más abajo tienes los links para instalarlo con ClickOnce,
no lo he probado, pero debería funcionar, aunque deberás tener instalado el .NET Framework 3.0 y
por consiguiente el 2.0 que es un requisito, ya que como sabes la versión 3.0 solo es un
"añadido" al 2.0.
Efectivamente funciona, pero solo si tienes instalado el .NET Framework 3.0, si no lo tienes
y quieres instalar cualquiera de las aplicaciones (los dos ejecutables), recibirás un aviso como
el de la siguiente figura:
Aviso de que necesitas el .NET framework 3.0 para usar estas aplicaciones
El link ese que sale en esa captura te traerá nuevamente a esta página, así que... ya sabes,
te bajas el runtime de .NET Framework 3.0, lo instalas y a funcionar con lo más nuevo...
que tarde o temprano tendrás que instalarlo, así que... ¿para que esperar?
Lenguajes y código XAML
Este código (como viene siendo costumbre con todo lo que publico sobre .NET) está tanto para
Visual Basic 2005 como para
Visual C# 2005.
En el código que te muestro, está por separado el código de cada uno de los lenguajes, aunque
el código XAML mostrado es el mismo, la única diferencia en ese código
XAML (que es el necesario para crear el formulario) son dos:
1- La definición de la ventana, que en Visual Basic solo tiene el nombre de la clase, mientras
que en C#, además del nombre de la clase debes poner el espacio de nombres en el que está esa
clase. Para que no te líes, te lo pongo por separado.
2- El color que he puesto de fondo, que el de VB es en azul y el de C# es... adivina...
efectivamente, en verde, mientras que el de la aplicación WEB es en un color grisáceo.
Compilación y creación de los proyectos
El proyecto está creado en una máquina virtual con el Windows XP Service Pack 2 en español,
en la que he instalado el Visual Studio 2005 Professional, la versión final, en inglés, del
runtime de .NET Framework 3.0, el SDK de .NET Framework 3.0 y las extensiones (el CTP de
Noviembre 2006) para crear proyectos de .NET Framework 3.0 con Visual Studio 2005.
Todas estas cosas te las puedes bajar, porque son
gratuitas.
Cosas de interés en el código
Este código no tiene nada del otro mundo. Pero lo que más trabajo me ha costado (sobre todo
ahora que estoy empezando con esto de WinFX) son estas cosas:
- Poder meter controles dentro de un
Expander
- Poder acceder a un control desde un evento de un
timer, para esto he usado un delegado por medio de
Dispatcher.Invoke.
Pero el rollo no era usar el delegado, sino saber cómo decirle al "runtime" que esa es mi
intención, la de llamar a ese delegado para que actualice el control.
- Lo de usar un timer es porque mi intención era que al pulsar en el
Expander (y mostrar los controles que están agrupados dentro de ese "expansor") se
pusiera el foco en una de las cajas de texto, y es que usando el código "como se supone
que hay que usarlo", pues no se posicionaba en ese control, así que me lo monté usando
un timer, de forma que pasado un periodo de tiempo (muy corto) se pusiera el
cursor en el control en cuestión, pero ya sabes que en .NET Framework 2.0 eso de acceder
a controles desde otro hilo es un rollo...
- Generar la clave SHA1 usando la clase
SHA1, ya que usando lo que hasta ahora he usado: el método
HashPasswordForStoringInConfigFile de la clase
FormsAuthentication del espacio de nombres System.Web.Security, me fallaba
precisamente ¡en la aplicación Web!
Así que... para que fuese siempre el mismo código, me he fabricado una función que devuelve
el código SHA1 de la cadena indicada.
Unas capturas de la aplicación en ejecución
Y para que sepas de que va esta aplicación, aquí tienes unas capturas en ejecución desde un
Windows XP SP2 con el .NET Framework 3.0 versión final en inglés.
Figura 1. Usando la clave y el usuario en la aplicación de Visual Basic
Figura 2. Solo creando la clave en la aplicación para C#
Figura 3. La aplicación Web funcionando en un XP con Internet Explorer 6
Nota:
Para que te funcione la aplicación Web desde el explorador, debes tener instalado el .NET
Framework 3.0 o estar usando Windows Vista, aunque en el Internet Explorer 7 y el FireFox 1.5
desde Windows Vista, se ve mal... a ver si lo arreglo.
Decirte que en el servidor donde esté alojado tu sitio Web (o la página que tiene la
aplicación para que se ejecute desde el navegador), debes permitir que la extensión
.xbap se pueda ejecutar, normalmente si la ponen como que es de tipo texto es suficiente, ya
que si ese servidor es un Windows 2003, y la extensión no está registrada, dará un error 404
indicando que esa página no existe, y por tanto no funcionará la aplicación.
También decirte que a la aplicación Web debes otorgarle permisos de Internet (los normales), eso
lo haces desde la propia ficha de Seguridad del Visual Studio 2005, sí, la misma que se usa para
las aplicaciones ClickOnce, ya que al fin y al cabo, esa aplicación se ejecuta por medio de
ClickOnce.
De forma directa solo lo he probado en modo local, abriendo precisamente el fichero que tiene la
extensión .xbap.
Por último decirte que ese fichero .xbap no está incluido en el RAR con el código, ya que se
genera al pulsar en publicar.
Espero que te sea de utilidad.
Nos vemos.
Guillermo
Código completo
Al final tienes un fichero RAR (sí, ahora uso el RAR en vez del
ZIP), con todo el código fuente de los tres proyectos, pero sin ningún binario, solo código.
Si quieres "probar" a instalarlo usando ClickOnce, pulsa estos links:
Pero recuerda que debes tener el .NET Framework 3.0 instalado.
Nota:
Las instalaciones con ClickOnce solo están disponible en
elguille.info.
Para que no haya problemas, he puesto los links fijos al sitio que si se ejecuta.
El código Xaml
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Generar clave SHA1 (VB)"
Height="232" Width="526" MinHeight="232" MinWidth="470"
WindowStartupLocation="CenterScreen">
<Grid>
<Grid.Background>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Color="sc#1, 0.75, 0.75, 0.90" Offset="0" />
<GradientStop Color="sc#1, 0.32, 0.40, 0.65" Offset="1" />
</LinearGradientBrush>
</Grid.Background>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="90" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="4" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="8"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="8" />
<RowDefinition Height="28" />
<!-- Clave -->
<RowDefinition Height="4" />
<RowDefinition Height="88" />
<!-- Expander -->
<RowDefinition Height="4" />
<RowDefinition Height="28" />
<!-- Clave SHA1 -->
<RowDefinition Height="29" />
<!-- LabelInfo -->
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Margin="8,2,2,2" Name="LabelClave" Grid.Row="1" Content="Clave:"
FontWeight="Bold" Foreground="#FF4B0082" />
<TextBox Margin="2,4,2,4" Name="txtClave" Grid.Column="1" Grid.Row="1"/>
<Expander Grid.Row="3" Margin="8,4,2,2"
Name="Expander1" Grid.ColumnSpan="2" IsExpanded="True" FontWeight="Bold"
Foreground="Indigo"
ToolTip=" Usa el nombre del usuario para crear una clave combinando el nombre y la clave "
Focusable="False">
<Expander.Header>Usar la clave en combinación con el nombre de usuario</Expander.Header>
<Grid Name="GridExpander">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="86" />
<ColumnDefinition Width="32" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Margin="8,2,4,2" Name="LabelUsuario" FontWeight="Bold"
Foreground="#FF4B0082">Usuario:</Label>
<TextBox Margin="2,4,2,4" Name="txtUsuario" FontWeight="Regular"
Grid.Column="1" Grid.ColumnSpan="2"></TextBox>
<Label Margin="8,2,4,2" Name="LabelCaracteres" FontWeight="Bold"
Foreground="#FF4B0082" Grid.Row="1" Height="22.2766666666667"
VerticalAlignment="Top">Caracteres:</Label>
<TextBox Margin="2,4,2,4" Name="txtCaracteres" FontWeight="Regular"
HorizontalAlignment="Left" Width="28.6077922077921"
Grid.Row="1" Grid.Column="1">10</TextBox>
<Label Grid.Column="2" Margin="2,2,2,2" Name="LabelInfoCaracteres"
Grid.Row="1" FontWeight="Normal"
Foreground="#FF4B0082">(de 6 a 40 caracteres)</Label>
</Grid>
</Expander>
<Label Grid.Row="5" Margin="8,2,2,2" Name="LabelSHA1" Content="Clave SHA1:"
FontWeight="Bold" Foreground="#FF4B0082" />
<TextBox Grid.Row="5" Margin="2,4,2,4" Name="txtClaveSHA" Grid.Column="1" />
<Button Margin="2,2,2,2" Name="btnGenerar" Grid.Column="3" Grid.Row="5"
Content="Generar clave" />
<Label Grid.Row="6" Margin="4,2,4,4" Name="LabelInfo" Grid.ColumnSpan="4"
FontWeight="Bold" Content="©Guillermo 'guille' Som, 2004-2006"
Foreground="#FF4B0082" />
</Grid>
</Window>
Para C# cambia estos valores:
Son las primeras líneas del código anterior.
<Window x:Class="gsGenerarClaveSHA1_cs.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Generar clave SHA1 (C#)"
Height="232" Width="526" MinHeight="232" MinWidth="470"
WindowStartupLocation="CenterScreen">
<Grid>
<Grid.Background>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Color="sc#1, 0.75, 0.90, 0.75" Offset="0" />
<GradientStop Color="sc#1, 0.32, 0.65, 0.40" Offset="1" />
</LinearGradientBrush>
</Grid.Background>
El código para Visual Basic .NET
'------------------------------------------------------------------------------
' Generar la clave SHA1 a partir de un nombre de usuario (11/Nov/06)
' También permite crear una clave SHA1 combinando el nombre y la clave
' Así es como creo la clave de confirmación de los registros de mi sitio.
'
' Basado en:
' Generar código SHA1 como el usado para el registro (05/Jul/04)
' Adaptado a VS2005 y WinFX (11/Nov/06)
'
' Usando la clase SHA1 (13/Nov/06)
'
' ©Guillermo 'guille' Som, 2004-2006
'------------------------------------------------------------------------------
Imports Microsoft.VisualBasic
Imports System
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Threading
Imports System.Timers
Imports System.Security.Cryptography
Imports System.Text
Partial Public Class Window1
Inherits System.Windows.Window
'
Private sbGuille As New StringBuilder("©Guillermo 'guille' Som, 2004-")
Private iniciando As Boolean = True
Private WithEvents timerExpander As New System.Timers.Timer
Private Const minCar As Integer = 6
Private Const maxCar As Integer = 40
'
Public Sub New()
InitializeComponent()
'
End Sub
Private Sub Window1_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs) _
Handles Me.Loaded
' Asignar el icono por código
' No hace falta, al usar el .exe se muestra el icono del ejecutable
'
' Ocultar el nombre del usuario
Me.Expander1.IsExpanded = False
'
If DateTime.Now.Year > 2006 Then
sbGuille.Append(DateTime.Now.Year)
Else
sbGuille.Append("2006")
End If
' Mostrar la versión, para saber la última actualización
sbGuille.AppendFormat(" (v{0})", My.Application.Info.Version.ToString)
'
Me.LabelInfo.Content = sbGuille.ToString
Me.LabelInfo.Foreground = Brushes.Indigo
'
Me.LabelInfoCaracteres.Content = "(de " & minCar & " a " & maxCar & " caracteres)"
Me.txtClave.Text = "aB23@wZ3/"
Me.txtClave.SelectionStart = Me.txtClave.Text.Length
Me.txtClave.Focus()
'
timerExpander.Interval = 100
timerExpander.Enabled = False
'
iniciando = False
End Sub
Private Sub btnGenerar_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) _
Handles btnGenerar.Click
' Generar la clave SHA
'
Me.LabelInfo.Content = sbGuille.ToString
Me.LabelInfo.Foreground = Brushes.Indigo
'
' Si el Expander1 está expandido y hay una clave
' usar esa clave en combinación con el nombre de usuario
' para generar la clave SHA.
' (esto es lo que hago en el registro de mi sitio para generar
' la clave SHA de comprobación)
If Me.Expander1.IsExpanded Then
Dim txt As TextBox = Nothing
' Si está expandido, usar la clave y el usuario
If String.IsNullOrEmpty(Me.txtClave.Text) = False Then
If String.IsNullOrEmpty(Me.txtUsuario.Text) = False Then
Dim cant As Integer = CInt(Me.txtCaracteres.Text)
If cant < minCar OrElse cant > maxCar Then
Me.LabelInfo.Content = "Debes indicar una cantidad entre " & _
minCar & " y " & maxCar & " caracteres."
Me.LabelInfo.Foreground = Brushes.Firebrick
Me.txtCaracteres.Focus()
Exit Sub
End If
Me.txtClaveSHA.Text = claveSHA1(Me.txtUsuario.Text, Me.txtClave.Text, cant)
Me.txtClaveSHA.SelectAll()
Me.txtClaveSHA.Focus()
Else
txt = Me.txtUsuario
End If
Else
txt = Me.txtClave
End If
If txt IsNot Nothing Then
' Avisar de que debe escribir los dos datos
Me.LabelInfo.Content = _
"Debes introducir la clave y el nombre o bien oculta el campo del nombre"
Me.LabelInfo.Foreground = Brushes.Firebrick
txt.Focus()
End If
Else
If String.IsNullOrEmpty(Me.txtClave.Text) = False Then
Me.txtClaveSHA.Text = claveSHA1(Me.txtClave.Text)
Me.txtClaveSHA.SelectAll()
Me.txtClaveSHA.Focus()
Else
Me.LabelInfo.Content = "Debes escribir la clave a encriptar"
Me.LabelInfo.Foreground = Brushes.Firebrick
Me.txtClave.Focus()
End If
End If
End Sub
''' <summary>
''' Genera la clave SHA1 a partir de una cadena
''' </summary>
''' <param name="sPassw">El password a encriptar</param>
''' <returns>
''' La clave SHA1 del password indicado
''' </returns>
''' <remarks></remarks>
Private Function claveSHA1(ByVal sPassw As String) As String
Return generarClaveSHA1(sPassw)
End Function
''' <summary>
''' Genera la clave SHA1 a partir de dos cadenas
''' </summary>
''' <param name="sUser">El nombre del usuario</param>
''' <param name="sPassw">El password asociado con el usuario</param>
''' <param name="caracteres">La cantidad de caracteres a devolver</param>
''' <returns>
''' Devuelve los primeros <paramref name="caracteres">caracteres</paramref> de la clave SHA1
''' resultante de usar el usuario y la clave
''' </returns>
''' <remarks>
''' Esto es lo que uso para la comprobación del usuario y password
''' de forma que pueda confirmar que los datos son correctos.
''' </remarks>
Private Function claveSHA1(ByVal sUser As String, _
ByVal sPassw As String, _
ByVal caracteres As Integer) As String
Return generarClaveSHA1(sUser & sPassw).Substring(0, caracteres)
End Function
Private Function generarClaveSHA1(ByVal nombre As String) As String
' Crear una clave SHA1 como la generada por
' FormsAuthentication.HashPasswordForStoringInConfigFile
' Adaptada del ejemplo de la ayuda en la descripción de SHA1 (Clase)
Dim enc As New UTF8Encoding
Dim data() As Byte = enc.GetBytes(nombre)
Dim result() As Byte
Dim sha As New SHA1CryptoServiceProvider()
' This is one implementation of the abstract class SHA1.
result = sha.ComputeHash(data)
'
' Convertir los valores en hexadecimal
' cuando tiene una cifra hay que rellenarlo con cero
' para que siempre ocupen dos dígitos.
Dim sb As New StringBuilder
For i As Integer = 0 To result.Length - 1
If result(i) < 16 Then
sb.Append("0")
End If
sb.Append(result(i).ToString("x"))
Next
'
Return sb.ToString.ToUpper
End Function
Private Sub Expander1_Collapsed(ByVal sender As Object, ByVal e As RoutedEventArgs) _
Handles Expander1.Collapsed
' Posicionar el cursor en la clave
If iniciando Then Exit Sub
If String.IsNullOrEmpty(Me.txtClave.Text) = False Then
Me.txtClave.SelectionStart = Me.txtClave.Text.Length
End If
Me.txtClave.Focus()
End Sub
Private Sub Expander1_Expanded(ByVal sender As Object, ByVal e As RoutedEventArgs) _
Handles Expander1.Expanded
' Posicionar el cursor en el textbox
If iniciando Then Exit Sub
' Acceder mediante el temporizador
timerExpander.Enabled = True
End Sub
' Para acceder al control desde otro hilo
Public Delegate Sub InvocarCallback()
Private Sub ponerFocoUsuario()
If String.IsNullOrEmpty(Me.txtUsuario.Text) = False Then
Me.txtUsuario.SelectionStart = Me.txtUsuario.Text.Length
End If
Me.txtUsuario.Focus()
End Sub
Private Sub timerExpander_Elapsed(ByVal sender As Object, ByVal e As ElapsedEventArgs) _
Handles timerExpander.Elapsed
timerExpander.Enabled = False
Me.txtUsuario.Dispatcher.Invoke(DispatcherPriority.Normal, _
New InvocarCallback(AddressOf ponerFocoUsuario))
End Sub
End Class
El código para C#
//-----------------------------------------------------------------------------
// Generar la clave SHA1 a partir de un nombre de usuario (11/Nov/06)
// También permite crear una clave SHA1 combinando el nombre y la clave
// Así es como creo la clave de confirmación de los registros de mi sitio.
//
// Basado en:
// Generar código SHA1 como el usado para el registro (05/Jul/04)
// Adaptado a VS2005 y WinFX (11/Nov/06)
//
// Usando la clase SHA1 (13/Nov/06)
//
// Revisión para C# (convertido con VB2CS) (13/Nov/06)
//
// ©Guillermo 'guille' Som, 2004-2006
//-----------------------------------------------------------------------------
using System;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Timers;
using System.Windows.Threading;
using System.Security.Cryptography;
using System.Reflection;
using System.Diagnostics;
namespace gsGenerarClaveSHA1_cs
{
public partial class Window1 : System.Windows.Window
{
//
private StringBuilder sbGuille = new StringBuilder("©Guillermo 'guille' Som, 2004-");
private bool iniciando = true;
private System.Timers.Timer timerExpander = new System.Timers.Timer();
private const int minCar = 6;
private const int maxCar = 40;
//
public Window1() {
InitializeComponent();
//
// Los eventos a interceptar
btnGenerar.Click +=new RoutedEventHandler(btnGenerar_Click);
this.Loaded +=new RoutedEventHandler(Window1_Loaded);
Expander1.Collapsed +=new RoutedEventHandler(Expander1_Collapsed);
Expander1.Expanded +=new RoutedEventHandler(Expander1_Expanded);
timerExpander.Elapsed +=new System.Timers.ElapsedEventHandler(timerExpander_Elapsed);
}
private void Window1_Loaded(object sender, RoutedEventArgs e)
{
// Asignar el icono por código
// No hace falta, al usar el .exe se muestra el icono del ejecutable
//
// Ocultar el nombre del usuario
this.Expander1.IsExpanded = false;
//
if (DateTime.Now.Year > 2006)
{
sbGuille.Append(DateTime.Now.Year);
}
else
{
sbGuille.Append("2006");
}
// Mostrar la versión, para saber la última actualización
sbGuille.AppendFormat(" (v{0})", versionApp());
//
this.LabelInfo.Content = sbGuille.ToString();
this.LabelInfo.Foreground = Brushes.Indigo;
//
this.LabelInfoCaracteres.Content = "(de " + minCar + " a " + maxCar + " caracteres)";
this.txtClave.Text = @"aB23MwZ3/";
this.txtClave.SelectionStart = this.txtClave.Text.Length;
this.txtClave.Focus();
//
timerExpander.Interval = 100;
timerExpander.Enabled = false;
//
iniciando = false;
}
// Función que devuelve la versión del ensamblado
private string versionApp()
{
Assembly ensamblado = Assembly.GetExecutingAssembly();
FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(ensamblado.Location);
//return ensamblado.GetName().Name + " v" + fvi.FileVersion;
return fvi.FileVersion;
}
private void btnGenerar_Click(object sender, RoutedEventArgs e)
{
// Generar la clave SHA
//
this.LabelInfo.Content = sbGuille.ToString();
this.LabelInfo.Foreground = Brushes.Indigo;
//
// Si el Expander1 está expandido y hay una clave
// usar esa clave en combinación con el nombre de usuario
// para generar la clave SHA.
// (esto es lo que hago en el registro de mi sitio para generar
// la clave SHA de comprobación)
if( this.Expander1.IsExpanded )
{
TextBox txt = null;
// Si está expandido, usar la clave y el usuario
if( String.IsNullOrEmpty(this.txtClave.Text) == false )
{
int cant = int.Parse(this.txtCaracteres.Text);
if( cant < minCar || cant > maxCar )
{
this.LabelInfo.Content = "Debes indicar una cantidad entre " +
minCar + " y " + maxCar + " caracteres.";
this.LabelInfo.Foreground = Brushes.Firebrick;
this.txtCaracteres.Focus();
return;
}
if( String.IsNullOrEmpty(this.txtUsuario.Text) == false )
{
this.txtClaveSHA.Text = claveSHA1(this.txtUsuario.Text, this.txtClave.Text, cant);
this.txtClaveSHA.SelectAll();
this.txtClaveSHA.Focus();
}
else
{
txt = this.txtUsuario;
}
}
else
{
txt = this.txtClave;
}
if( txt != null )
{
// Avisar de que debe escribir los dos datos
this.LabelInfo.Content =
"Debes introducir la clave y el nombre o bien oculta el campo del nombre";
this.LabelInfo.Foreground = Brushes.Firebrick;
txt.Focus();
}
}
else
{
if( String.IsNullOrEmpty(this.txtClave.Text) == false )
{
this.txtClaveSHA.Text = claveSHA1(this.txtClave.Text);
this.txtClaveSHA.SelectAll();
this.txtClaveSHA.Focus();
}
else
{
this.LabelInfo.Content = "Debes escribir la clave a encriptar";
this.LabelInfo.Foreground = Brushes.Firebrick;
this.txtClave.Focus();
}
}
}
/// <summary>
/// Genera la clave SHA1 a partir de una cadena
/// </summary>
/// <param name="sPassw">El password a encriptar</param>
/// <returns>
/// La clave SHA1 del password indicado
/// </returns>
/// <remarks></remarks>
private string claveSHA1(string sPassw)
{
return generarClaveSHA1(sPassw);
}
/// <summary>
/// Genera la clave SHA1 a partir de dos cadenas
/// </summary>
/// <param name="sUser">El nombre del usuario</param>
/// <param name="sPassw">El password asociado con el usuario</param>
/// <param name="caracteres">El número de caracteres a devolver</param>
/// <returns>
/// Devuelve los primeros <paramref name="caracteres">caracteres</paramref> de la clave SHA1
/// resultante de usar el usuario y la clave
/// </returns>
/// <remarks>
/// Esto es lo que uso para la comprobación del usuario y password
/// de forma que pueda confirmar que los datos son correctos.
/// </remarks>
private string claveSHA1(string sUser, string sPassw, int caracteres)
{
return generarClaveSHA1(sUser + sPassw).Substring(0, caracteres);
}
private string generarClaveSHA1(string nombre)
{
// Crear una clave SHA1 como la generada por
// FormsAuthentication.HashPasswordForStoringInConfigFile
// Adaptada del ejemplo de la ayuda en la descripción de SHA1 (Clase)
UTF8Encoding enc = new UTF8Encoding();
byte[] data = enc.GetBytes(nombre);
byte[] result;
SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();
// This is one implementation of the abstract class SHA1.
result = sha.ComputeHash(data);
//
// Convertir los valores en hexadecimal
// cuando tiene una cifra hay que rellenarlo con cero
// para que siempre ocupen dos dígitos.
StringBuilder sb = new StringBuilder();
for(int i= 0; i< result.Length; i++)
{
if( result[i] < 16 )
{
sb.Append("0");
}
sb.Append(result[i].ToString("x"));
}
//
return sb.ToString().ToUpper();
}
private void Expander1_Collapsed(object sender, RoutedEventArgs e)
{
// Posicionar el cursor en la clave
if( iniciando ) return;
if( String.IsNullOrEmpty(this.txtClave.Text) == false )
{
this.txtClave.SelectionStart = this.txtClave.Text.Length;
}
this.txtClave.Focus();
}
private void Expander1_Expanded(object sender, RoutedEventArgs e)
{
// Posicionar el cursor en el textbox
if( iniciando ) return;
//
// Acceder mediante el temporizador
timerExpander.Enabled = true;
}
// Para acceder al control desde otro hilo
public delegate void InvocarCallback();
private void ponerFocoUsuario()
{
if( String.IsNullOrEmpty(this.txtUsuario.Text) == false )
{
this.txtUsuario.SelectionStart = this.txtUsuario.Text.Length;
}
this.txtUsuario.Focus();
}
private void timerExpander_Elapsed(object sender, ElapsedEventArgs e)
{
timerExpander.Enabled = false;
this.txtUsuario.Dispatcher.Invoke(
DispatcherPriority.Normal,
new InvocarCallback( ponerFocoUsuario));
}
}
}
Espacios de nombres usados en el código de este artículo:
System.Text
System.Windows
System.Windows.Controls
System.Windows.Media
System.Timers
System.Security.Cryptography