el Guille, la Web del Visual Basic, C#, .NET y más...

gsGenerarClaveSHA1

Utilidad para generar claves SHA1 para usar con autenticación

Publicado el 13/Nov/2006
Actualizado el 15/Jul/2007
Autor: Guillermo 'guille' Som

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. Y como de costumbre, con código para VB como para C#, así como el diseño en XAML.



 

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
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:

  1. Poder meter controles dentro de un Expander
  2. 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...

       
  3. 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 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 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
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.

 

Si quieres publicar un proyecto Web de .NET Framework 3.0

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.

 

Instalar / usar con ClickOnce

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.

 


Código Xaml   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>

 

Código para Visual Basic.NET (VB.NET)   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

 

Código para C Sharp (C#)   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

 


 

Código de ejemplo (comprimido):

Fichero con el código de ejemplo: gsGenerarClaveSHA1_src_13nov06.rar - 44.50 KB

 Contiene los tres proyectos sin binarios, sólo el código.

 (MD5 checksum: 28CAFEA6558AB762441A01ACEED8A8B3)

 



La fecha/hora en el servidor es: 22/12/2024 17:20:28

La fecha actual GMT (UTC) es: 

©Guillermo 'guille' Som, 1996-2024