Data can be encrypted using the public key, but only decrypted using the private key, now just because you can doesn't mean you should. Asymmetric encryption is slow, so it's usually only used for signing.
Whereas data signed with the private key can be verified with the public key and this is a digital signature.
Clear as mud, so there are numerous asymmetric encryption algorithms that you can use:
Asymmetric Algorithms
now the catch is that from my experimenting I've noticed that the algorithms in winrt that allow you to sign data do not allow you to encrypt it, and vice-versa, strange, if you're reading this and know something i don't please fill me in.
now from my investigation I found the following,
Algorithm
|
Min Byte Key size
|
Sign
|
Encrypt
|
"RSA_OAEP_SHA1"
|
1024
|
0
|
1
|
"RSA_OAEP_SHA256"
|
1024
|
0
|
1
|
"RSA_OAEP_SHA384"
|
2048
|
0
|
1
|
"RSA_OAEP_SHA512"
|
2048
|
0
|
1
|
"RSA_PKCS1"
|
512
|
1
|
0
|
"DSA_SHA1"
|
512
|
1
|
0
|
"DSA_SHA256"
|
2048
|
1
|
0
|
"ECDSA_P256_SHA256"
|
256
|
1
|
0
|
"ECDSA_P384_SHA384"
|
384
|
1
|
0
|
"ECDSA_P521_SHA512"
|
521
|
1
|
0
|
"RSASIGN_PKCS1_SHA1"
|
512
|
1
|
0
|
"RSASIGN_PKCS1_SHA256"
|
512
|
1
|
0
|
"RSASIGN_PKCS1_SHA384"
|
1024
|
1
|
0
|
"RSASIGN_PKCS1_SHA512"
|
1024
|
1
|
0
|
"RSASIGN_PSS_SHA1"
|
512
|
1
|
0
|
"RSASIGN_PSS_SHA256"
|
512
|
1
|
0
|
"RSASIGN_PSS_SHA384"
|
512
|
1
|
0
|
"RSASIGN_PSS_SHA512"
|
1024
|
1
|
0
|
OK let's take a look at a working example, first a screen shot of our demo
There's a lot going on, so i'll try and explain it, basically you can see that there's two vertical sections, the top one is for the creator of the private key. you never share your private in asymmetric encryption, you create both the public and private key, but you only ever share the private key.
the bottom half is for consumers of the public key.
now there's three horizontal sections, the first has the two message boxes, they are you data input.
the second horizontal section is used for signing and validating messages, basically in the top section you create a private public key combination and sign your message, then you send the message, the public key and the signature to the bottom section, the bottom section acts as the recipient and validates the message by using the three in combination.
finally the third horizontal section is for demonstrating the encryption capability. what you do in the top section is create a private and public key combination, then you send the public key to the bottom section; in turn the bottom section can encrypt data from the bottom message box using the public key and then send it back to the top which can then decrypt it using the private key.
Ok let's look at all the XAML
<Page
x:Class="pc.DigitalSignatureExample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:pc.DigitalSignatureExample"
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"/>
</Style>
<Style TargetType="Button">
<Setter Property="FontSize" Value="24"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
</Style>
<Style TargetType="ComboBox">
<Setter Property="FontSize" Value="24"/>
<Setter Property="Height" Value="84"/>
</Style>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="*"/>
<RowDefinition Height="10"/>
<RowDefinition Height="*"/>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="1" Grid.Row="0"
Grid.ColumnSpan="4"
Text="Digital Signature Example" VerticalAlignment="Center"
Style="{ThemeResource HeaderTextBlockStyle}"
/>
<!--
Private Key creator -->
<TextBox x:Name="Private_Message_TXT" Header="Message:"
Grid.Column="1" Grid.Row="1"
TextWrapping="Wrap"
Text="Place
Holder Text"/>
<!--
For Signing -->
<StackPanel Grid.Column="3" Grid.Row="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<ComboBox x:Name="SignAlgorithm_CB" Header="Sign
Algorithm:" />
<Button x:Name="Sign_BTN" Content="Sign"
Grid.Column="1" />
</Grid>
<TextBox x:Name="Private_Signature_TXT" Header="Signature"
/>
<TextBox x:Name="Private_SignaturePrivateKey_TXT" Header="Private
key:" />
<TextBox x:Name="Private_SignaturePublicKey_TXT" Header="Public
key:" />
<Button x:Name="Private_SignatureSend_BTN" Content="Send"
/>
</StackPanel>
<!--
For Encrypting -->
<StackPanel Grid.Column="5" Grid.Row="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<ComboBox x:Name="EncryptionAlgorithm_CB" Header="Encrypt
Algorithm:" />
<Button x:Name="KeysForEncryption_BTN" Content="Get Keys" Grid.Column="1"
/>
</Grid>
<TextBox x:Name="Private_EncryptionPrivateKey_TXT" Header="Private
key:" />
<TextBox x:Name="Private_EncryptionPublicKey_TXT" Header="Public
key:" />
<StackPanel Orientation="Horizontal">
<Button x:Name="Private_EncryptionSend_BTN" Content="Send Public
Key" />
<Button x:Name="Private_Decrypt_BTN" Content="Decrypt"/>
</StackPanel>
</StackPanel>
<!--
Public key recipient -->
<!--
Varifying data -->
<TextBox x:Name="Public_Message_TXT" Header="Message:" Grid.Column="1"
Grid.Row="3" TextWrapping="Wrap"
/>
<StackPanel Grid.Column="3" Grid.Row="3">
<TextBox x:Name="Public_PublicKey_TXT" Header="Public
Key:" />
<TextBox x:Name="Public_Signature_TXT" Header="Signature:"
/>
<Button x:Name="Public_Validate_BTN" Content="Validate"
/>
</StackPanel>
<!--
Encrypting Data -->
<StackPanel Grid.Column="5" Grid.Row="3">
<TextBox x:Name="Public_EncryptionPublicKey_TXT" Header="Public
Key:" />
<StackPanel Orientation="Horizontal">
<Button x:Name="Public_Encrypt_BTN" Content="Encrypt"
/>
<Button x:Name="Public_Send_BTN"
Content="Send"/>
</StackPanel>
</StackPanel>
</Grid>
</Page>
Anyway let's look at the whole code behind, then I'll dissect it
using System;
using Windows.Security.Cryptography;
using Windows.Security.Cryptography.Core;
using Windows.Storage.Streams;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace pc.DigitalSignatureExample
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
//set
algorithms that can sign data
SignAlgorithm_CB.ItemsSource = new string[] {
AsymmetricAlgorithmNames.DsaSha1, AsymmetricAlgorithmNames.DsaSha256,
AsymmetricAlgorithmNames.EcdsaP256Sha256, AsymmetricAlgorithmNames.EcdsaP384Sha384,
AsymmetricAlgorithmNames.EcdsaP521Sha512, AsymmetricAlgorithmNames.RsaSignPkcs1Sha1,
AsymmetricAlgorithmNames.RsaSignPkcs1Sha256, AsymmetricAlgorithmNames.RsaSignPkcs1Sha384,
AsymmetricAlgorithmNames.RsaSignPkcs1Sha512, AsymmetricAlgorithmNames.RsaSignPssSha1,
AsymmetricAlgorithmNames.RsaSignPssSha256, AsymmetricAlgorithmNames.RsaSignPssSha384,
AsymmetricAlgorithmNames.RsaSignPssSha512 };
//set
algorithms that can encrypt data
EncryptionAlgorithm_CB.ItemsSource
= new string[]{
AsymmetricAlgorithmNames.RsaOaepSha1, AsymmetricAlgorithmNames.RsaOaepSha256,
AsymmetricAlgorithmNames.RsaOaepSha384, AsymmetricAlgorithmNames.RsaOaepSha512,
AsymmetricAlgorithmNames.RsaPkcs1,
};
//private
key owner evnets
Sign_BTN.Click += Sign_BTN_Click;
Private_SignatureSend_BTN.Click +=
Private_SignatureSend_BTN_Click;
KeysForEncryption_BTN.Click +=
GeneratePublicPrivateKeysForEncryption_Click;
Private_EncryptionSend_BTN.Click +=
Private_EncryptionSend_BTN_Click;
Private_Decrypt_BTN.Click +=
Private_Decrypt_BTN_Click;
//public
key user events
Public_Validate_BTN.Click +=
Public_Validate_BTN_Click;
Public_Encrypt_BTN.Click +=
EncryptData_Click;
Public_Send_BTN.Click +=
Public_Send_BTN_Click;
}
//
create public & private Key for encryption
void GeneratePublicPrivateKeysForEncryption_Click(object sender, RoutedEventArgs e)
{
//get
the algorithm to use
string algorithmName = EncryptionAlgorithm_CB.SelectedValue.ToString();
AsymmetricKeyAlgorithmProvider asymmetricKeyProvider =
AsymmetricKeyAlgorithmProvider.OpenAlgorithm(algorithmName);
//differnet
algorithms have different min key sizes, I tried to figure it out
CryptographicKey keyPair =
asymmetricKeyProvider.CreateKeyPair(GetKeySize(algorithmName));
//get
the public key
IBuffer publicKey =
keyPair.ExportPublicKey(GetCryptographicPublicKeyBlobType(algorithmName));
Private_EncryptionPublicKey_TXT.Text
= CryptographicBuffer.EncodeToBase64String(publicKey);
//get
the private key
IBuffer privateKey = keyPair.Export();
Private_EncryptionPrivateKey_TXT.Text = CryptographicBuffer.EncodeToBase64String(privateKey);
}
//use
the public key by the recipient to encrypt data.
void EncryptData_Click(object sender, RoutedEventArgs e)
{
//get
algorithm to use
string algorithmName = EncryptionAlgorithm_CB.SelectedValue.ToString();
AsymmetricKeyAlgorithmProvider asymmetricKeyProvider =
AsymmetricKeyAlgorithmProvider.OpenAlgorithm(algorithmName);
//Convert
the message to a buffer
IBuffer message = CryptographicBuffer.ConvertStringToBinary(Public_Message_TXT.Text, BinaryStringEncoding.Utf8);
//get
the public key to use
IBuffer publicKey = CryptographicBuffer.DecodeFromBase64String(Public_EncryptionPublicKey_TXT.Text);
//get
the public key to use, again did my best, might not be 100%
CryptographicKey keyPublic =
asymmetricKeyProvider.ImportPublicKey(publicKey,
GetCryptographicPublicKeyBlobType(algorithmName));
//encrypt
the data using the public key, and set the message box to the result
var encryptedData = CryptographicEngine.Encrypt(keyPublic, message, null);
Public_Message_TXT.Text = CryptographicBuffer.EncodeToBase64String(encryptedData);
}
//Decrypt
void Private_Decrypt_BTN_Click(object sender, RoutedEventArgs e)
{
//Get
the algorithm to use
string aglorithmName =
EncryptionAlgorithm_CB.SelectedValue.ToString();
AsymmetricKeyAlgorithmProvider asymmetricKeyProvider =
AsymmetricKeyAlgorithmProvider.OpenAlgorithm(aglorithmName);
//get
the recieved message from the recipient
IBuffer message = CryptographicBuffer.DecodeFromBase64String(Private_Message_TXT.Text);
//get
the private key
IBuffer privateKey = CryptographicBuffer.DecodeFromBase64String(Private_EncryptionPrivateKey_TXT.Text);
CryptographicKey key = asymmetricKeyProvider.ImportKeyPair(privateKey);
//Decrypt
the message
IBuffer decryptedMessage = CryptographicEngine.Decrypt(key, message, null);
//set
the message box to display the message
Private_Message_TXT.Text = CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8,
decryptedMessage);
}
//Send
the encrypted message from the recipient to the Private key holder
void Public_Send_BTN_Click(object sender, RoutedEventArgs e)
{
Private_Message_TXT.Text =
Public_Message_TXT.Text;
}
//Send
public key from the private key holder to the recipient
void Private_EncryptionSend_BTN_Click(object sender, RoutedEventArgs e)
{
Public_EncryptionPublicKey_TXT.Text
= Private_EncryptionPublicKey_TXT.Text;
}
//Sign
Data with private key
void Sign_BTN_Click(object sender, RoutedEventArgs e)
{
//get
the algorithm to use
string algorithmName =
SignAlgorithm_CB.SelectedValue.ToString();
AsymmetricKeyAlgorithmProvider asymmetricKeyProvider =
AsymmetricKeyAlgorithmProvider.OpenAlgorithm(algorithmName);
//create
the key pair, both private and public
CryptographicKey keyPair =
asymmetricKeyProvider.CreateKeyPair(GetKeySize(algorithmName));
//convert
the message to be signed and sent to a buffer
IBuffer binaryMessage = CryptographicBuffer.ConvertStringToBinary(Private_Message_TXT.Text, BinaryStringEncoding.Utf8);
//sign
the message using the keypair, but onlyr requires the private key
IBuffer signature = CryptographicEngine.Sign(keyPair, binaryMessage);
this.Private_Signature_TXT.Text = CryptographicBuffer.EncodeToBase64String(signature);
//extract
the public key from the key pair
IBuffer publicKey =
keyPair.ExportPublicKey(GetCryptographicPublicKeyBlobType(algorithmName));
Private_SignaturePublicKey_TXT.Text = CryptographicBuffer.EncodeToBase64String(publicKey);
//extract
the private key from the key pair
IBuffer privateKey = keyPair.Export();
Private_SignaturePrivateKey_TXT.Text = CryptographicBuffer.EncodeToBase64String(privateKey);
}
//validate
the message receieved from the private key holder using the public key,
//
signature and the message itself
async void Public_Validate_BTN_Click(object sender, RoutedEventArgs e)
{
// get
the algorithm to use
var algorithmName =
SignAlgorithm_CB.SelectedValue.ToString();
AsymmetricKeyAlgorithmProvider asymmetricKeyProvider =
AsymmetricKeyAlgorithmProvider.OpenAlgorithm(algorithmName);
//extract
the signature
IBuffer signature = CryptographicBuffer.DecodeFromBase64String(Public_Signature_TXT.Text);
//extract
the public key
IBuffer publicKey = CryptographicBuffer.DecodeFromBase64String(Public_PublicKey_TXT.Text);
//import
the public key
CryptographicKey keyPublic =
asymmetricKeyProvider.ImportPublicKey(publicKey,
GetCryptographicPublicKeyBlobType(algorithmName));
//convert
the message to a buffer
IBuffer message = CryptographicBuffer.ConvertStringToBinary(Public_Message_TXT.Text, BinaryStringEncoding.Utf8);
//validate
the message and notify the user
if (CryptographicEngine.VerifySignature(keyPublic, message, signature))
await new MessageDialog("Message is
valid").ShowAsync();
else
await new MessageDialog("Message is
invalid").ShowAsync();
}
//send
the message, signature and public key to the user.
void Private_SignatureSend_BTN_Click(object sender, RoutedEventArgs e)
{
Public_Message_TXT.Text =
Private_Message_TXT.Text;
Public_Signature_TXT.Text = Private_Signature_TXT.Text;
Public_PublicKey_TXT.Text =
Private_SignaturePublicKey_TXT.Text;
}
//get
the min key size required for the algorithm
uint GetKeySize(string AglorithmName)
{
switch (AglorithmName)
{
case "ECDSA_P256_SHA256":
return 256;
case "ECDSA_P384_SHA384":
return 384;
case "DSA_SHA1":
case "RSA_PKCS1":
case "RSASIGN_PKCS1_SHA1":
case "RSASIGN_PKCS1_SHA256":
case "RSASIGN_PSS_SHA1":
case "RSASIGN_PSS_SHA256":
case "RSASIGN_PSS_SHA384":
return 512;
case "ECDSA_P521_SHA512":
return 521;
case "RSA_OAEP_SHA1":
case "RSA_OAEP_SHA256":
case "RSASIGN_PKCS1_SHA384":
case "RSASIGN_PKCS1_SHA512":
case "RSASIGN_PSS_SHA512":
return 1024;
case "DSA_SHA256":
case "RSA_OAEP_SHA384":
case "RSA_OAEP_SHA512":
return 2048;
default:
return 512;
}
}
// get
the type of public key used by the algorithm, not 100% on this,
CryptographicPublicKeyBlobType GetCryptographicPublicKeyBlobType(string
AsymmetricAlgorithmName)
{
switch (AsymmetricAlgorithmName)
{
case "DSA_SHA1":
case "RSA_OAEP_SHA256":
case "RSA_OAEP_SHA512":
case "RSA_PKCS1":
case "RSASIGN_PKCS1_SHA1":
case "RSASIGN_PKCS1_SHA256":
case "RSASIGN_PKCS1_SHA384":
case "RSASIGN_PKCS1_SHA512":
case "RSASIGN_PSS_SHA1":
case "RSASIGN_PSS_SHA256":
case "RSASIGN_PSS_SHA384":
case "RSASIGN_PSS_SHA512":
return CryptographicPublicKeyBlobType.Capi1PublicKey;
case "DSA_SHA256":
case "ECDSA_P256_SHA256":
case "ECDSA_P384_SHA384":
case "ECDSA_P521_SHA512":
case "RSA_OAEP_SHA1":
case "RSA_OAEP_SHA384":
return CryptographicPublicKeyBlobType.BCryptPublicKey;
default:
throw new ArgumentOutOfRangeException("AsymmetricAlgorithmName", "No such
algorithm");
}
}
}
}
public MainPage()
{
this.InitializeComponent();
//set
algorithms that can sign data
SignAlgorithm_CB.ItemsSource = new string[] {
AsymmetricAlgorithmNames.DsaSha1, AsymmetricAlgorithmNames.DsaSha256,
AsymmetricAlgorithmNames.EcdsaP256Sha256, AsymmetricAlgorithmNames.EcdsaP384Sha384,
AsymmetricAlgorithmNames.EcdsaP521Sha512, AsymmetricAlgorithmNames.RsaSignPkcs1Sha1,
AsymmetricAlgorithmNames.RsaSignPkcs1Sha256, AsymmetricAlgorithmNames.RsaSignPkcs1Sha384,
AsymmetricAlgorithmNames.RsaSignPkcs1Sha512, AsymmetricAlgorithmNames.RsaSignPssSha1,
AsymmetricAlgorithmNames.RsaSignPssSha256, AsymmetricAlgorithmNames.RsaSignPssSha384,
AsymmetricAlgorithmNames.RsaSignPssSha512 };
//set
algorithms that can encrypt data
EncryptionAlgorithm_CB.ItemsSource = new string[]{
AsymmetricAlgorithmNames.RsaOaepSha1, AsymmetricAlgorithmNames.RsaOaepSha256,
AsymmetricAlgorithmNames.RsaOaepSha384, AsymmetricAlgorithmNames.RsaOaepSha512,
AsymmetricAlgorithmNames.RsaPkcs1,
};
//private
key owner evnets
Sign_BTN.Click += Sign_BTN_Click;
Private_SignatureSend_BTN.Click +=
Private_SignatureSend_BTN_Click;
KeysForEncryption_BTN.Click +=
GeneratePublicPrivateKeysForEncryption_Click;
Private_EncryptionSend_BTN.Click +=
Private_EncryptionSend_BTN_Click;
Private_Decrypt_BTN.Click +=
Private_Decrypt_BTN_Click;
//public
key user events
Public_Validate_BTN.Click +=
Public_Validate_BTN_Click;
Public_Encrypt_BTN.Click +=
EncryptData_Click;
Public_Send_BTN.Click +=
Public_Send_BTN_Click;
}
next lets look at the sign event handler.
//Sign
Data with private key
void Sign_BTN_Click(object sender, RoutedEventArgs e)
{
//get
the algorithm to use
string algorithmName =
SignAlgorithm_CB.SelectedValue.ToString();
AsymmetricKeyAlgorithmProvider asymmetricKeyProvider =
AsymmetricKeyAlgorithmProvider.OpenAlgorithm(algorithmName);
//create
the key pair, both private and public
CryptographicKey keyPair =
asymmetricKeyProvider.CreateKeyPair(GetKeySize(algorithmName));
//convert
the message to be signed and sent to a buffer
IBuffer binaryMessage = CryptographicBuffer.ConvertStringToBinary(Private_Message_TXT.Text,
BinaryStringEncoding.Utf8);
//sign
the message using the keypair, but only requires the private key
IBuffer signature = CryptographicEngine.Sign(keyPair, binaryMessage);
this.Private_Signature_TXT.Text = CryptographicBuffer.EncodeToBase64String(signature);
//extract
the public key from the key pair
IBuffer publicKey =
keyPair.ExportPublicKey(GetCryptographicPublicKeyBlobType(algorithmName));
Private_SignaturePublicKey_TXT.Text = CryptographicBuffer.EncodeToBase64String(publicKey);
//extract
the private key from the key pair
IBuffer privateKey = keyPair.Export();
Private_SignaturePrivateKey_TXT.Text = CryptographicBuffer.EncodeToBase64String(privateKey);
}
Once our data is signed, we send it to the recipient where it is validated
//validate
the message receieved from the private key holder using the public key,
//
signature and the message itself
async void Public_Validate_BTN_Click(object sender, RoutedEventArgs e)
{
// get
the algorithm to use
var algorithmName =
SignAlgorithm_CB.SelectedValue.ToString();
AsymmetricKeyAlgorithmProvider asymmetricKeyProvider =
AsymmetricKeyAlgorithmProvider.OpenAlgorithm(algorithmName);
//extract
the signature
IBuffer signature = CryptographicBuffer.DecodeFromBase64String(Public_Signature_TXT.Text);
//extract
the public key
IBuffer publicKey = CryptographicBuffer.DecodeFromBase64String(Public_PublicKey_TXT.Text);
//import
the public key
CryptographicKey keyPublic =
asymmetricKeyProvider.ImportPublicKey(publicKey,
GetCryptographicPublicKeyBlobType(algorithmName));
//convert
the message to a buffer
IBuffer message = CryptographicBuffer.ConvertStringToBinary(Public_Message_TXT.Text, BinaryStringEncoding.Utf8);
//validate
the message and notify the user
if (CryptographicEngine.VerifySignature(keyPublic, message, signature))
await new MessageDialog("Message is
valid").ShowAsync();
else
await new MessageDialog("Message is
invalid").ShowAsync();
}
next let's take a look at the method for creating a public private key combination for decryption and sharing it with a recipient who will in turn be able to encrypt data using the public key.
//
create public & private Key for encryption
void GeneratePublicPrivateKeysForEncryption_Click(object sender, RoutedEventArgs e)
{
//get
the algorithm to use
string algorithmName =
EncryptionAlgorithm_CB.SelectedValue.ToString();
AsymmetricKeyAlgorithmProvider asymmetricKeyProvider =
AsymmetricKeyAlgorithmProvider.OpenAlgorithm(algorithmName);
//differnet
algorithms have different min key sizes, I tried to figure it out
CryptographicKey keyPair = asymmetricKeyProvider.CreateKeyPair(GetKeySize(algorithmName));
//get
the public key
IBuffer publicKey =
keyPair.ExportPublicKey(GetCryptographicPublicKeyBlobType(algorithmName));
Private_EncryptionPublicKey_TXT.Text = CryptographicBuffer.EncodeToBase64String(publicKey);
//get
the private key
IBuffer privateKey = keyPair.Export();
Private_EncryptionPrivateKey_TXT.Text = CryptographicBuffer.EncodeToBase64String(privateKey);
}
once we have our private public keys we can share the public one with a recipient and then that recipient can encrypt data and pass it back to us so that we can decrypt it with our private key, so lets look at the encrypt function the recipient would use.
//use
the public key by the recipient to encrypt data.
void EncryptData_Click(object sender, RoutedEventArgs e)
{
//get
algorithm to use
string algorithmName =
EncryptionAlgorithm_CB.SelectedValue.ToString();
AsymmetricKeyAlgorithmProvider asymmetricKeyProvider =
AsymmetricKeyAlgorithmProvider.OpenAlgorithm(algorithmName);
//Convert
the message to a buffer
IBuffer message = CryptographicBuffer.ConvertStringToBinary(Public_Message_TXT.Text, BinaryStringEncoding.Utf8);
//get
the public key to use
IBuffer publicKey = CryptographicBuffer.DecodeFromBase64String(Public_EncryptionPublicKey_TXT.Text);
//get
the public key to use, again did my best, might not be 100%
CryptographicKey keyPublic =
asymmetricKeyProvider.ImportPublicKey(publicKey,
GetCryptographicPublicKeyBlobType(algorithmName));
//encrypt
the data using the public key, and set the message box to the result
var encryptedData = CryptographicEngine.Encrypt(keyPublic, message, null);
Public_Message_TXT.Text = CryptographicBuffer.EncodeToBase64String(encryptedData);
}
and here we just decrypt the message using the corresponding private key
//Decrypt
void Private_Decrypt_BTN_Click(object sender, RoutedEventArgs e)
{
//Get
the algorithm to use
string aglorithmName =
EncryptionAlgorithm_CB.SelectedValue.ToString();
AsymmetricKeyAlgorithmProvider asymmetricKeyProvider =
AsymmetricKeyAlgorithmProvider.OpenAlgorithm(aglorithmName);
//get
the recieved message from the recipient
IBuffer message = CryptographicBuffer.DecodeFromBase64String(Private_Message_TXT.Text);
//get
the private key
IBuffer privateKey = CryptographicBuffer.DecodeFromBase64String(Private_EncryptionPrivateKey_TXT.Text);
CryptographicKey key = asymmetricKeyProvider.ImportKeyPair(privateKey);
//Decrypt
the message
IBuffer decryptedMessage = CryptographicEngine.Decrypt(key, message, null);
//set
the message box to display the message
Private_Message_TXT.Text = CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8,
decryptedMessage);
}
now I also create two helper methods for my demo app
get key size
//get
the min key size required for the algorithm
uint GetKeySize(string AglorithmName)
{
switch (AglorithmName)
{
case "ECDSA_P256_SHA256":
return 256;
case "ECDSA_P384_SHA384":
return 384;
case "DSA_SHA1":
case "RSA_PKCS1":
case "RSASIGN_PKCS1_SHA1":
case "RSASIGN_PKCS1_SHA256":
case "RSASIGN_PSS_SHA1":
case "RSASIGN_PSS_SHA256":
case "RSASIGN_PSS_SHA384":
return 512;
case "ECDSA_P521_SHA512":
return 521;
case "RSA_OAEP_SHA1":
case "RSA_OAEP_SHA256":
case "RSASIGN_PKCS1_SHA384":
case "RSASIGN_PKCS1_SHA512":
case "RSASIGN_PSS_SHA512":
return 1024;
case "DSA_SHA256":
case "RSA_OAEP_SHA384":
case "RSA_OAEP_SHA512":
return 2048;
default:
return 512;
}
}
and on method to get the public key blob type
//
get the type of public key used by the algorithm, not 100% on this,
CryptographicPublicKeyBlobType GetCryptographicPublicKeyBlobType(string
AsymmetricAlgorithmName)
{
switch (AsymmetricAlgorithmName)
{
case "DSA_SHA1":
case "RSA_OAEP_SHA256":
case "RSA_OAEP_SHA512":
case "RSA_PKCS1":
case "RSASIGN_PKCS1_SHA1":
case "RSASIGN_PKCS1_SHA256":
case "RSASIGN_PKCS1_SHA384":
case "RSASIGN_PKCS1_SHA512":
case "RSASIGN_PSS_SHA1":
case "RSASIGN_PSS_SHA256":
case "RSASIGN_PSS_SHA384":
case "RSASIGN_PSS_SHA512":
return CryptographicPublicKeyBlobType.Capi1PublicKey;
case "DSA_SHA256":
case "ECDSA_P256_SHA256":
case "ECDSA_P384_SHA384":
case "ECDSA_P521_SHA512":
case "RSA_OAEP_SHA1":
case "RSA_OAEP_SHA384":
return CryptographicPublicKeyBlobType.BCryptPublicKey;
default:
throw new ArgumentOutOfRangeException("AsymmetricAlgorithmName", "No such
algorithm");
}
}