sexta-feira, setembro 20, 2013

Criptografar senhas em C# .net

Estava eu criando uma biblioteca de utilidades que precisarei em um novo projeto em que estou participando e este é todo desenvolvido em .net C#, quando pensei que precisaria traduzir meu algoritmo de criptografia de senhas de Java para C#. E então comecei a pesquisar sobre o assunto criptografia em .net / C#.

Assustei-me um pouco quando vi a quantidade de gente postando a seguinte pergunta por aí "como eu criptografo e 'descriptografo' uma senha em C#?". É sabido (ou deveria ser) que senhas devem ser criptografadas em via de mão única (one way) sem poder ser revertidas novamente. Lembre-se sempre de que uma senha não precisará nunca voltar a ser legível, não é como uma mensagem que eu quero mandar cifrada para, se, interceptada não possa ser lida por pessoas não autorizadas.

Enfim, achei o pacote namespace System.Security.Cryptography e com isso fiz meu algoritmo para criptografar senhas que lhes deixo aqui como dica, inspiração, presente de grego, etc...

using System;
using System.Text;
using System.Security.Cryptography;
 
namespace com.blogspot.jeanjmichel.utilitieslibrary.password
{
    class Program
    {
        /// <summary>
        /// This method will encrypt a password passed by parameter using an
        /// algorithm SHA-1 of 256 bits.
        /// </summary>
        /// <param name="password">
        /// The password in plain text format to be encrypted.
        /// </param>
        /// <returns>
        /// An encrypted password (restrained in 64 characters).
        /// </returns>
        /// <author>
        /// Jean J. Michel (http://jeanjmichel.blogspot.com)
        /// </author>
        private static String EncryptPassword(String password)
        {
            SHA256Managed encryptionAlgorithm = new SHA256Managed();
            byte[] encryptedHash, passwordBytes;
            String encryptedPassword = "";
            
            //The firs step is get the password in bytes.
            UnicodeEncoding ue = new UnicodeEncoding();
            passwordBytes = ue.GetBytes(password);
            
            /*
             * After it, pass the bytes to the algorithm and receives the
             * encrypted hash.
             */
            encryptedHash = encryptionAlgorithm.ComputeHash(passwordBytes);
            
            //Now is just store the hash in a String
            foreach (byte b in encryptedHash)
            {
                encryptedPassword += String.Format("{0:x2}", b);
            }
            
            //And returns it ;)
            return encryptedPassword;
        }
        
        static void Main(string[] args)
        {
            int i = 0;
            
            //Creating a list of my favorites passwords
            String[] myPasswords = {"my5&cR&7P@55w0rD", "5&cR&7",
                                    "boo!", "^..^ oinc oinc!"};
            
            //And preparing a list to receive this passwords encrypted
            String[] myPasswordsEncrypted = new String[myPasswords.Length];
            
            Console.WriteLine("Encripting passwords");
            Console.WriteLine("");
            Console.Write("64 characters scale");
            Console.Write(".........................");
            Console.Write("012345678901234567890123456789");
            Console.WriteLine("0123456789012345678901234567890123");
            Console.WriteLine("");
            
            foreach (String s in myPasswords)
            {
                //Encrypting and store the password
                myPasswordsEncrypted[i++] = EncryptPassword(s);
                
                //Printing the original string and the encrypted string
                Console.WriteLine("Plain text: " +
                                  s.PadRight(20, ' ') +
                                  " Encrypted: " +
                                  myPasswordsEncrypted[--i]);
            }
            
            //This is the expected result for the generation of a password for
            //'5&cR&7' and we will compare it againt the password generated here
            String hashToCompare =
                "936ad4c3854a6b26f3f278702d36b8253e7bd438ac749518b53354079bd77a63";
            
            Console.WriteLine("");
            Console.WriteLine("Comparing two hashes");
            Console.WriteLine("");
            Console.Write("Is euquals ");
            Console.Write("936ad4c3854a6b26f3f278702d36b8253e7bd438ac749518b53354079bd77a63");
            Console.WriteLine(" and the generated hash of 5&cR&7?");
            Console.Write("Answer: ");
            Console.WriteLine(hashToCompare.Equals(EncryptPassword(myPasswords[1])));
            
            Console.Read();
        }
    }
}

Agora é só rodar e conferir o resultado ;)

segunda-feira, setembro 16, 2013

Nem só de códigos vive um programador

Dodge Charger R/T 1969. Hot Wheel série HW Showroom
Dodge Charger R/T 1969. Hot Wheel série HW Showroom.


Sempre gostei de carros, mas não sou aquele fanático que reconhece qualquer modelo e sabe o ano, modelo do motor, cilindradas, etc. de cada carro que passa pela rua, mas a minha mesa merecia esse Dodge Charger R/T 1969 da Hot Wheels.
Esse é o mesmo modelo do Dodge Charger chamado General Lee dirigido pelos primos Duke (Bo e Luke) no seriado americano The Dukes of Hazzard das décadas de 70 e 80 e no filme Os Gatões - Uma Nova Balada de 2005.

Dodge Charger R/T 1969 General Lee, utilizado na série de TV The Dukes of Hazzard
Dodge Charger R/T 1969 General Lee, utilizado na série de TV The Dukes of Hazzard.

quarta-feira, setembro 11, 2013

WCF utilizando nome da máquina nos serviços ao invés do domínio da aplicação

Uma das coisas que eu mais sinto falta no universo .Net é a falta de um bom servidor de aplicação.
Um cara como o GlassFish, JBoss, etc. a quem eu possa deixar a cargo toda a responsabilidade de criar e gerenciar pool de conexões, envio de e-mails, etc. e também hospedar as minhas aplicações do tipo webservice.
Estou usando o IIS (Internet Information Services) para tal tarefa e não estou gostando nada disso. Mas enfim, o post é sobre outro assunto ;)

Estava eu criando um serviço utilizando o WCF (Windows Communication Foundation) e o hospedando em um site chamado wcf rodando no IIS em um servidore de desenvolvimento. O deploy foi tranqüilo e quando acessei pelo browser o endereço http://192.xxx.xx.xxx:8081/wcf vi lá listado o meu serviço.

Tudo parecia bem, estranhamente bem, pois nada com a Microsoft é de primeira (ao menos comigo). E Murphy não me abandonou! Quando eu acessei o link do serviço vi que o mesmo estava referenciando o nome da máquina, Anita, na url para o arquivo XML do descritor do serviço (wsdl) e em todos os links dentro dele também está escrito o nome da máquina e não um IP ou o nome do domínio.

Embedded ImageUtil

Ok. Lá vamos nós procurar no MSDN a sintaxe da configuração do arquivo App.config. Para quem já utilizou os docs da linguagem Java da Sun/Oracle, a MSDN é de chorar.

Encontrei algumas soluções na internet, alterando arquivos de configuração do IIS, etc. até que achei a solução, colocar <behaviors><serviceBehaviors><behavior> a tag <useRequestHeadersForMetadataAddress>, que está descrito na MSDN como: Enables the retrieval of metadata address information from the request message headers. Ou seja, trocando em miúdos, pegar do header das requisições a informação do endereço.
E voilà!

Embedded ImageUtil

Todos os links dentro do descritor agora estão corretos também.
Para que fique registrada a dica, aqui está a configuração feita no App.config para o exemplo dessa postagem:

<?xml version="1." encoding="utf-8" ?>
<configuration>
   
  <system.web>
    <compilation debug="true" />
  </system.web>
   
  <system.serviceModel>
    <services>
      <service name="com.blogspot.jeanjmichel.services.GetGreetingService">
        <host>
          <baseAddresses>
            <add baseAddress = "http://localhost:8081/wcf" />
          </baseAddresses>
        </host>
         
        <endpoint address =""
                  binding="basicHttpBinding"
                  contract="com.blogspot.jeanjmichel.services.contract.IGetGreeting"
                  bindingNamespace="http://jeanjmichel.blogspot.com/services/v1.0.0" >
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
         
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
     
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <useRequestHeadersForMetadataAddress>
            <defaultPorts>
              <add scheme="http" port="8081" />
            </defaultPorts>
          </useRequestHeadersForMetadataAddress>
          <serviceMetadata httpGetEnabled="True"/>
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
     
  </system.serviceModel>
</configuration>