Tuesday, 10 February 2015

Hashing

A hash transforms a binary values of varied lengths to to smaller binary values of similar lengths in essence creating a sort of fingerprint for data that can later be used to compare the data to check for integrity; for example a contract is written, a hash is created and stored. moving forward every time the contract is hashed (with the assumption the same hash algorithm is used) it'll be the same as the original unless something within the contract is changed then the hashes will not match up.

one thing to note is that hashing is not the same a encrypting, hashing is a one-way street, once hashed data cannot be un-hashed; so it's really only used for data integrity checks.

anyway lets' start with a simple example to demonstrate what we mean, as always let's start with an interface.

<Page
    x:Class="pc.HashExmple.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:pc.HashExmple"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Page.Resources>
        <Style TargetType="TextBox">
            <Setter Property="Margin" Value="100 0 50 20"/>
            <Setter Property="TextWrapping" Value="Wrap"/>
            <Setter Property="FontSize" Value="24"/>
        </Style>
    </Page.Resources>
   
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="140"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
       
        <TextBlock Text="Hash Example" Style="{StaticResource HeaderTextBlockStyle}"
                   VerticalAlignment="Center" Margin="100 0 0 0"/>
       
        <TextBox x:Name="Plain_TXT" Header="Intput:" Grid.Row="1"/>
       
        <StackPanel Margin="100 0" Grid.Row="2" Orientation="Horizontal" >
            <Button x:Name="Hash_BTN" Content="Hash" VerticalAlignment="Bottom"/>
            <ComboBox x:Name="Hash_CB" VerticalAlignment="Bottom"/>
        </StackPanel>
       
        <TextBox x:Name="Hash_TXT" Header="Hash:" IsReadOnly="True" Grid.Row="3"/>
    </Grid>
</Page>

and it should render as

ignore the drop down with the md5 selected value, yours should be blank, i'm just working with an already built out example. Now to the code behind.

firstly lets' work with the constructor,

public MainPage()
{
    this.InitializeComponent();
           
    Hash_CB.ItemsSource = new string[] {"Md5", "Sha1", "Sha256", "Sha384", "Sha512" };
    Hash_CB.SelectedIndex = 0;

    this.Hash_BTN.Click += Hash_BTN_Click;

}

here we populated our combo-box and added an event handler to our calculate button, so let's look at that event handler

void Hash_BTN_Click(object sender, RoutedEventArgs e)
{
    IBuffer binaryMessage =
        CryptographicBuffer.ConvertStringToBinary(this.Plain_TXT.Text, BinaryStringEncoding.Utf8);

    //get the algorithm we want to use
    HashAlgorithmProvider hashProvider = HashAlgorithmProvider.OpenAlgorithm(GetAlgorithmName());

    IBuffer hashedMessage = hashProvider.HashData(binaryMessage);

    Hash_TXT.Text = CryptographicBuffer.EncodeToBase64String(hashedMessage);

}

in our handler we pick which hash algorithm we use, so let's write that function now

string GetAlgorithmName()
{
    switch(Hash_CB.SelectedValue.ToString())
    {
        case "Md5":
            return HashAlgorithmNames.Md5;
        case "Sha1":
            return HashAlgorithmNames.Sha1;
        case "Sha256":
            return HashAlgorithmNames.Sha256;
        case "Sha384":
            return HashAlgorithmNames.Sha384;
        case "Sha512":
            return HashAlgorithmNames.Sha512;
    }

    return null;

}

ok  with that complete, play around with it, try the following text, then modify the first S to a lowercase s

Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?

and see that it hashes to a completely different value also notice that the hashes come out to the same length more or less as

Sed ut perspiciatis 

Hope you get the idea,

long:

similar:

Short:

and here's the full codebehind

using Windows.Security.Cryptography;
using Windows.Security.Cryptography.Core;
using Windows.Storage.Streams;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace pc.HashExmple
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();

            Hash_CB.ItemsSource = new string[] { "Md5", "Sha1", "Sha256", "Sha384", "Sha512" };
            Hash_CB.SelectedIndex = 0;

            this.Hash_BTN.Click += Hash_BTN_Click;
        }

        void Hash_BTN_Click(object sender, RoutedEventArgs e)
        {
            IBuffer binaryMessage =
                CryptographicBuffer.ConvertStringToBinary(this.Plain_TXT.Text, BinaryStringEncoding.Utf8);

            //get the algorithm we want to use
            HashAlgorithmProvider hashProvider = HashAlgorithmProvider.OpenAlgorithm(GetAlgorithmName());

            IBuffer hashedMessage = hashProvider.HashData(binaryMessage);

            Hash_TXT.Text = CryptographicBuffer.EncodeToBase64String(hashedMessage);
        }


        string GetAlgorithmName()
        {
            switch (Hash_CB.SelectedValue.ToString())
            {
                case "Md5":
                    return HashAlgorithmNames.Md5;
                case "Sha1":
                    return HashAlgorithmNames.Sha1;
                case "Sha256":
                    return HashAlgorithmNames.Sha256;
                case "Sha384":
                    return HashAlgorithmNames.Sha384;
                case "Sha512":
                    return HashAlgorithmNames.Sha512;
            }

            return null;
        }
    }
}