martes, septiembre 23, 2008

Guardar errores en un archivo de texto de forma encriptada

Siempre es buena practica llevar un registro de los errores que se presentan en cualquier aplicacion, creo que lo mas comun es colocar los errores en un archivo de texto, como una especie de log, o en su caso dentro de una base de datos para llevar un registro. Los habra mas sofisticados que pondra la informacion como un evento de windows.

Pero si no queremos que los usuarios de la aplicacion que estan de curiosos, vean y lean los errores que se producen en nuestra aplicacion, una forma practica es la de encriptar el archivo. El problema con esto es que si el archivo de texto se vuelve muy grande la encriptacion puede hacer lenta la aplicacion, ya que tienes que abrir el archivo desencriptar, colocar un mensaje, y volver a encriptar el archivo.

Siendo lo anterior un poco impractico decidi mejor colocar los mensajes encriptados dentro del archivo. Para lo cual modifique la clase que estoy utilizando para guardar los mensajes:

   1:      Public Shared Sub WriteError(ByVal errorMessage As String)
   2:          Try
   3:              Dim path As String = "error.txt"
   4:              If (Not File.Exists(System.Web.HttpContext.Current.Server.MapPath(path))) Then
   5:                  File.Create(System.Web.HttpContext.Current.Server.MapPath(path)).Close()
   6:              End If
   7:              Using w As StreamWriter = File.AppendText(System.Web.HttpContext.Current.Server.MapPath(path))
   8:                  w.WriteLine(Constants.vbCrLf & "Error : ")
   9:                  w.WriteLine("{0}", DateTime.Now.ToString(CultureInfo.InvariantCulture))
  10:                  Dim err As String = "En linea: " & System.Web.HttpContext.Current.Request.Url.ToString() & ". Mensaje:" & errorMessage
  11:                  w.WriteLine(Encrypt(err, True))
  12:                  w.WriteLine("__________________________")
  13:                  w.Flush()
  14:                  w.Close()
  15:              End Using
  16:          Catch ex As Exception
  17:              WriteError(ex.Message)
  18:          End Try
  19:      End Sub


Si observan en la linea 11 puse la palabra Encrypt, es ahi donde estoy haciendo llamar otra funcion, importando en el archivo la libreria de .net de criptografia:

Imports System.Security.Cryptography


    Public Function Encrypt(ByVal toEncrypt As String, ByVal useHashing As Boolean) As String
        Dim keyArray As Byte()
        Dim toEncryptArray As Byte() = UTF8Encoding.UTF8.GetBytes(toEncrypt)
        Dim key As String = "MyKEY"
        If useHashing Then
            Dim hashmd5 As New MD5CryptoServiceProvider()
            keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key))
            hashmd5.Clear()
        Else
            keyArray = UTF8Encoding.UTF8.GetBytes(key)
        End If
        Dim tdes As New TripleDESCryptoServiceProvider()
        tdes.Key = keyArray
        tdes.Mode = CipherMode.ECB
        tdes.Padding = PaddingMode.PKCS7
        Dim cTransform As ICryptoTransform = tdes.CreateEncryptor()
        Dim resultArray As Byte() = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length)
        tdes.Clear()
        Return Convert.ToBase64String(resultArray, 0, resultArray.Length)
    End Function


Ahora ya tendremos nuestros mensajes encriptados. Si queremos desencriptar los mensajes solo tendremos que usar la siguiente funcion en algun lugar y hacerla llamar:



    Public Shared Function Decrypt(ByVal cipherString As String, ByVal useHashing As Boolean) As String
       Dim keyArray As Byte()
        Dim toEncryptArray As Byte() = Convert.FromBase64String(cipherString)
        Dim key As String = "MyKEY"
        If useHashing Then
            Dim hashmd5 As New MD5CryptoServiceProvider()
            keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key))
            hashmd5.Clear()
        Else
            keyArray = UTF8Encoding.UTF8.GetBytes(key)
        End If
        Dim tdes As New TripleDESCryptoServiceProvider()
        tdes.Key = keyArray
        tdes.Mode = CipherMode.ECB
        tdes.Padding = PaddingMode.PKCS7
        Dim cTransform As ICryptoTransform = tdes.CreateDecryptor()
        Dim resultArray As Byte() = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length)
        tdes.Clear()
        Return UTF8Encoding.UTF8.GetString(resultArray)
    End Function

Tal vez usar una forma de aspx que reciba el codigo encriptado:


<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="WebForm1.aspx.vb" Inherits="Bintech.WebForm1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        Forma de desencriptacion:<br />
        <asp:TextBox ID="TextBoxEncriptado" runat="server" Height="173px" TextMode="MultiLine" Width="308px"></asp:TextBox>
        <br />
        <asp:Button ID="Button1"
            runat="server" Text="Button" />
        <br />
        <asp:Label ID="LabelResult" runat="server"></asp:Label></div>
    </form>
</body>
</html>

Y agregar un evento al boton:







    Protected Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
       LabelResult.Text = Decrypt(TextBoxEncriptado.Text, False)
    End Sub


Listo!

1 comentario:

usuario usb dijo...

Hablando de errores, recuerdo que para el office 98 tu ingresabas un serie de comandos con el tecleado y lograbas que se congelará.

Pero una clave tan larga que no recuerdo, posiblemente este en internet.