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>
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;
}
}
}
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";
}
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.