Sunday 1 March 2015

MAC Message Authentication code

Similar to a hash but with a slight twist, to review a hash is basically a one way transformation of data, it's often used for passwords in database, you hash your password then to test attempts you run the same hash on the input and compare it's result to the stored hash, if it's valid then the password is correct, if it's invalid than the input doesn't match the stored password. because the hash is one way all you can do is replace it because there is no way to get the password from the hash.

Now that's great for small amounts of data, but what about larger messages, not necessarily secrete messages, but important ones. a bit confused? let me try and clarify, lets say I send my wife a grocery list, not exactly secrete data, but I wouldn't want a 3rd party appending the list with their things, so what I can use is a MAC, that is I create a signature of the data using a private key that only me and my wife know, I send my data with the signature which in essence is a hash of my data, then since only me and my wife know the key she can use the message, signature and key to validate the message. take a look at the screen below.


Now as you can see above is a list of 4 things for her to pick up, I create a password "Unicorn" select my hashing algorithm, then hit the MAC hash button to generate a signature.

I then send the list with the signature to my wife, she then types in our secrete password "Unicorn" and validates the data, and she can be assured that the list came from me.


However if anything is wrong, that is the message, the key or the signature the data is invalid. for example lets say someone intercepted my message and added turtle meat to it, the key message combination would create a different signature and thus fail validation.

As you can see above if the list don't match then the message, key, signature combination fails. The signature is a hash of the key and message, thus it's a unique one way representation of the two.

anyway let's take a look at the code, first the UI.

<Page
    x:Class="pc.MAC.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:pc.MAC"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    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="FontSize" Value="24"/>
            <Setter Property="Margin" Value="0 0 50 0"/>
        </Style>
        <Style TargetType="Button">
            <Setter Property="FontSize" Value="24"/>
            <Setter Property="VerticalAlignment" Value="Bottom" />
        </Style>
    </Page.Resources>

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="120" />
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="100"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Column="1" Grid.Row="0" Text="MAC Example"
                   Style="{ThemeResource HeaderTextBlockStyle}"
                   VerticalAlignment="Center"/>

        <!-- For Sender-->
        <TextBox x:Name="SenderMessage_TXT"
            Grid.Column="1" Grid.Row="1"
            Header="Message:" TextWrapping="NoWrap"/>

        <StackPanel Grid.Column="2" Grid.Row="1">
            <TextBox Header="Key:" x:Name="SenderKey_TXT"
                     Grid.Column="1" Grid.Row="2" />

            <StackPanel Grid.Column="2" Grid.Row="2" 
                        Margin="0 20 0 10" Orientation="Horizontal" >
                <ComboBox x:Name="MacTypes_CB" MinWidth="200" Header="Mac:"
                          Height="85" FontSize="24"
                          ItemsSource="{Binding MacHashs, Mode=OneTime}"/>

                <Button Click="MachHash_Clicked" Content="MAC hash" />
                <Button Click="Send_Clicked" Content="Send"/>
                <Button Click="CopyKey_Clicked" Content="Send Key" />
            </StackPanel>
            <TextBox x:Name="SenderSigniture_TXT" Header="Signiture"
                 Grid.Column="1" Grid.Row="3" Grid.ColumnSpan="2"/>
        </StackPanel>

        <!-- For reciever -->
        <TextBox Header="Recieved Message:" x:Name="RecieverMessage_TXT"
                 Grid.Column="1" Grid.Row="2" />
        <StackPanel Grid.Column="2" Grid.Row="2">
            <TextBox Header="Receiver Key:" x:Name="ReceiverKey_TXT"
                     Grid.Column="1" Grid.Row="2" />

            <TextBox x:Name="ReceiverSigniture_TXT" Header="Receiver Signiture:"
                 Grid.Column="1" Grid.Row="3" Grid.ColumnSpan="2"/>

            <StackPanel Orientation="Horizontal">
                <Button x:Name="Test_BTN" Click="Test_Click"
                        Content="Test" Margin="0 10"/>
                <TextBlock x:Name="result_TB" FontSize="24" VerticalAlignment="Center"/>
            </StackPanel>
        </StackPanel>
    </Grid>
</Page>


as always straight forward, just take notice that in the page declaration i set the datacontext to the codebehind so that i can bind the mac combo box to an property in the codebehind.

DataContext="{Binding RelativeSource={RelativeSource Self}}"

next let's take a look at the whole 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.MAC
{
    public sealed partial class MainPage : Page
    {
        //Data source for MAC ComboBox
        public string[] MacHashs { get { return new string[] {
            MacAlgorithmNames.AesCmac, MacAlgorithmNames.HmacMd5,
            MacAlgorithmNames.HmacSha1, MacAlgorithmNames.HmacSha256,
            MacAlgorithmNames.HmacSha384, MacAlgorithmNames.HmacSha512 };
        } }

        public MainPage()
        {
            this.InitializeComponent();
            var b = new Button();
        }


        void MachHash_Clicked(object sender, RoutedEventArgs e)
        {
            var encoding = BinaryStringEncoding.Utf8;
            var senderKey = SenderKey_TXT.Text;
            var senderMessage = SenderMessage_TXT.Text;
            var algType = MacTypes_CB.SelectedValue.ToString();

            //get the mac algorithm to use
            MacAlgorithmProvider macProvider = MacAlgorithmProvider.OpenAlgorithm(algType);

            //create a hash-based message authentication code (hmac)
            IBuffer key = CryptographicBuffer.ConvertStringToBinary(senderKey, encoding);
            CryptographicKey hmacKey = macProvider.CreateKey(key);

            //convert message to a byte array
            IBuffer binaryMessage = CryptographicBuffer.ConvertStringToBinary(senderMessage, encoding);

            //sign the byte array message with the hmac
            IBuffer macSignature = CryptographicEngine.Sign(hmacKey, binaryMessage);

            //display the signiture.
            SenderSigniture_TXT.Text = CryptographicBuffer.EncodeToHexString(macSignature);
        }

        void Test_Click(object sender, RoutedEventArgs e)
        {
            var encoding = BinaryStringEncoding.Utf8;
            var receivedMessage = RecieverMessage_TXT.Text;
            var receiverKey = ReceiverKey_TXT.Text;
            var receiverSigniture = CryptographicBuffer.DecodeFromHexString(ReceiverSigniture_TXT.Text);
            var algType = MacTypes_CB.SelectedValue.ToString();

            //get the mac algorithm to use
            MacAlgorithmProvider macProvider = MacAlgorithmProvider.OpenAlgorithm(algType);

            // convert the message to a byte array
            IBuffer binaryMessage = CryptographicBuffer.ConvertStringToBinary(receivedMessage, encoding);

            //create the hash-based message authentication code (hmac), using the provided password
            IBuffer key = CryptographicBuffer.ConvertStringToBinary(receiverKey, encoding);
            CryptographicKey hmacKey = macProvider.CreateKey(key);

            //test to make sure that the key and message generate the same signiture
            if (CryptographicEngine.VerifySignature(hmacKey, binaryMessage, receiverSigniture))
                result_TB.Text = "valid";
            else
                result_TB.Text = "invalid";
        }

        //send the message with the signature
        void Send_Clicked(object sender, RoutedEventArgs e) {
            ReceiverSigniture_TXT.Text = SenderSigniture_TXT.Text;
            RecieverMessage_TXT.Text = SenderMessage_TXT.Text;
        }

        //copy the key to the reciever to avoid typos
        void CopyKey_Clicked(object sender, RoutedEventArgs e) {
            ReceiverKey_TXT.Text = SenderKey_TXT.Text;
        }
    }
}


ok let's go over the two interesting functions, firstly the machash

void MachHash_Clicked(object sender, RoutedEventArgs e)
{
    var encoding = BinaryStringEncoding.Utf8;
    var senderKey = SenderKey_TXT.Text;
    var senderMessage = SenderMessage_TXT.Text;
    var algType = MacTypes_CB.SelectedValue.ToString();

    //get the mac algorithm to use
    MacAlgorithmProvider macProvider = MacAlgorithmProvider.OpenAlgorithm(algType);

    //create a hash-based message authentication code (hmac)
    IBuffer key = CryptographicBuffer.ConvertStringToBinary(senderKey, encoding);
    CryptographicKey hmacKey = macProvider.CreateKey(key);

    //convert message to a byte array
    IBuffer binaryMessage = CryptographicBuffer.ConvertStringToBinary(senderMessage, encoding);

    //sign the byte array message with the hmac
    IBuffer macSignature = CryptographicEngine.Sign(hmacKey, binaryMessage);

    //display the signiture.
    SenderSigniture_TXT.Text = CryptographicBuffer.EncodeToHexString(macSignature);

}

this basically creates a signature using our message and key. next lets look at our test function

void Test_Click(object sender, RoutedEventArgs e)
{
    var encoding = BinaryStringEncoding.Utf8;
    var receivedMessage = RecieverMessage_TXT.Text;
    var receiverKey = ReceiverKey_TXT.Text;
    var receiverSigniture = CryptographicBuffer.DecodeFromHexString(ReceiverSigniture_TXT.Text);
    var algType = MacTypes_CB.SelectedValue.ToString();

    //get the mac algorithm to use
    MacAlgorithmProvider macProvider = MacAlgorithmProvider.OpenAlgorithm(algType);

    // convert the message to a byte array
    IBuffer binaryMessage = CryptographicBuffer.ConvertStringToBinary(receivedMessage, encoding);

    //create the hash-based message authentication code (hmac), using the provided password
    IBuffer key = CryptographicBuffer.ConvertStringToBinary(receiverKey, encoding);
    CryptographicKey hmacKey = macProvider.CreateKey(key);

    //test to make sure that the key and message generate the same signiture
    if (CryptographicEngine.VerifySignature(hmacKey, binaryMessage, receiverSigniture))
        result_TB.Text = "valid";
    else
        result_TB.Text = "invalid";

}

all it does is makes sure that infact the message, key and signature combination are valid.

now the flaw here is that if anyone where to get your key, then they could change your message recalculate the signature and send their list with the new key and thus when the receiver uses their key it shows that the data is valid so in essence this technique is only as secure as the key.