Send Encrypt Data PC to Raspberry Pi 2






4.56/5 (4 votes)
Send encrypt string and send/receive as bytes between Raspberry Pi 2 with Windows 10 IoT and PC
Introduction
This project will show you how to encrypt a string
and send as bytes between Raspberry Pi 2 with Windows 10 IoT and PC with Windows 10 using C# and UWP (Universal Windows Platform) over TCP/IP network, where Raspberry is a server, receiving and send message to client when receive, and PC is a client and PC sends a message to Raspberry.
Background
UWP - Universal Windows Platform
UWP is a new type of project from Microsoft which allows applications to run in any Windows platform (like Windows 8 or superior, Xbox, Windows phone, etc.) without any modification, and now you have a “Manifest”, if you don't give permission in manifest, your app won't work. For further information, access this link.
Windows 10 IoT Core
Windows 10 IoT Core is a version of Windows 10 that is optimized for small devices with or without display. When this article was written, Windows 10 IoT Core supported the following devices:
- Raspberry Pi 2
- Arrow DragonBoard 410c
- MinnowBoard Max.
You can use UWP to develop apps for Windows 10 IoT Core. For more information, access this link.
Requirements
- VS 2015
- SDK Windows 10 IoT
- Raspberry Pi 2 with Windows 10 IoT Core on ethernet (if you are using Wi-fi, maybe you will have some problem to debug and/or deploy).
Project
This project has two solutions, one for raspberry and another for Windows App. If you have one solution and two projects, maybe you will have some problem to debug because raspberry uses architecture ARM and PC x86.
Using the Code
Encrypt
The Cryptographic
class is responsible to encrypt/decrypt data, for this article, I used symmetric Algorithm. To encrypt or decrypt some data, some steps are necessary:
- Create a
SymmectricKeyAlgorithmProvider
, that has astatic
method to create where you pass name of the algorithm,SymmetricAlgorithmNames
class that has name of algorithm is supported - Generate Hash from key
- Convert text to binary
- Encrypt passing key, binary text and iv (Initialization Vector, this can be
null
)
For this article, I used encrypt key "123
".
For further information about how algorithms are supported, access this link.
Encrypt
public static byte[] Encrypt(string text, string passPhrase)
{
IBuffer iv = null;
//Create SymmetricKeyAlgorithmProvider
var symetric = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
//Create hash for passPhrase to create symmetric Key
IBuffer keyBuffer = Hash(passPhrase);
//Create symmetric
CryptographicKey key = symetric.CreateSymmetricKey(keyBuffer);
//Convert texto to binary, for encrypt
IBuffer data = CryptographicBuffer.ConvertStringToBinary(text, BinaryStringEncoding.Utf8);
//Encrypt data
//Encrypt method return IBuffer
return CryptographicEngine.Encrypt(key, data, iv).ToArray();
}
Decrypt
public static string Decrypt(IBuffer data, string passPhrase)
{
IBuffer iv = null;
//Create SymmetricKeyAlgorithmProvider
var symetric = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
//Create hash for passPhrase to create symmetric Key
IBuffer keyBuffer = Hash(passPhrase);
//Create symmetric key
CryptographicKey key = symetric.CreateSymmetricKey(keyBuffer);
//Decrypt data
IBuffer bufferDecrypted = CryptographicEngine.Decrypt(key, data, iv);
//Convert binary to string
return CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8, bufferDecrypted);
}
Hash
public static IBuffer Hash(string text)
{
//Create HashAlgorithmProvider
var hash = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Md5);
//Create Hash object
CryptographicHash cryptographicHash = hash.CreateHash();
//Convert string to binary
IBuffer data = CryptographicBuffer.ConvertStringToBinary(text, BinaryStringEncoding.Utf8);
//Append data to generate Hash
cryptographicHash.Append(data);
//Generate Hash
return cryptographicHash.GetValueAndReset();
}
Server TCP
ServerTcp
class is responsible to bind and listen to any port, for this example I was binding port 9000.
For work bind any port, you need to mark flag in: Package.appmanifest -> Capabilities -> InterneT(Client & Server).
Bind Port
public async void StartAsync()
{
try
{
//Create a new Cancel Token
_cancel = new CancellationTokenSource();
_listener = new StreamSocketListener();
//Assigned event when have a new connection
_listener.ConnectionReceived += Listener_ConnectionReceived;
//Bind port
await _listener.BindServiceNameAsync(_port.ToString());
}
catch (Exception e)
{
InvokeOnError(e.Message);
}
}
Wait for Some Connection
private async void Listener_ConnectionReceived
(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
_socket = args.Socket;
var reader = new DataReader(args.Socket.InputStream);
try
{
//If Close
while (!_cancel.IsCancellationRequested)
{
//Wait receive some data
byte[] data = await ReciveData(reader);
IBuffer buffer = data.AsBuffer();
//Decrypt message
string text = Cryptographic.Decrypt(buffer, "123");
//Invoke event when message is received
InvokeOnDataRecive(text);
}
}
catch (Exception e)
{
InvokeOnError(e.Message);
}
}
After receive connection, we need listening port to check if some data is received.
private async Task<byte[]> ReciveData(DataReader reader)
{
//Read length of Message
uint sizeFieldCount = await reader.LoadAsync(sizeof(uint));
//if disconnect
if (sizeFieldCount != sizeof(uint))
throw new Exception("Disconnect");
//Get length of Message from buffer
uint bufferSize = reader.ReadUInt32();
//Read Message
uint dataRecive = await reader.LoadAsync(bufferSize);
//if disconnect
if (dataRecive != bufferSize)
throw new Exception("Disconnect");
var data = new byte[bufferSize];
//Get message from buffer
reader.ReadBytes(data);
return data;
}
Send Message
public async Task SendAsync(string text)
{
try
{
// DataWriter, who is send a message
var writer = new DataWriter(_socket.OutputStream);
//Encrypt message
byte[] data = Cryptographic.Encrypt(text, "123");
//Write length of message in buffer
writer.WriteInt32(data.Length);
//Write message in buffer
writer.WriteBytes(data);
//Send buffer
await writer.StoreAsync();
//Clear buffer
await writer.FlushAsync();
}
catch (Exception e)
{
InvokeOnError(e.Message);
}
}
Start Application on Raspberry Pi
When we created project Background Application(IoT), the VS created a StartUpTask
class, and this will have method Run
, application begins to run from that.
public void Run(IBackgroundTaskInstance taskInstance)
{
BackgroundTaskDeferral background = taskInstance.GetDeferral();
var server = new ServerTcp(9000);
server.OnError += Server_OnError;
server.OnDataRecive += Server_OnDataRecive;
ThreadPool.RunAsync(x =>{
server.StartAsync();
});
}
private async void Server_OnDataRecive(ServerTcp sender, string args)
{
//answer text receive
await sender.SendAsync(string.Concat("Text Recive:", args));
}
Client
Socket
A SocketClient
class is responsible to create socket and communicated with some server.
Connect
public async Task ConnectAsync(string ip, int port)
{
Ip = ip;
Port = port;
try
{
//Resolved HostName to connect
var hostName = new HostName(Ip);
_socket = new StreamSocket();
//Indicates whether keep-alive packets are sent to the remote destination
_socket.Control.KeepAlive = true;
//Connect
await _socket.ConnectAsync(hostName, Port.ToString());
_cancel = new CancellationTokenSource();
_writer = new DataWriter(_socket.OutputStream);
//Read Data
ReadAsync();
}
catch (Exception ex)
{
InvokeOnError(ex.Message);
}
}
ReadAsync
private async Task ReadAsync()
{
_reader = new DataReader(_socket.InputStream);
try
{
//If Close
while (!_cancel.IsCancellationRequested)
{
//Wait receive some data
byte[] data = await ReciveData(_reader);
IBuffer buffer = data.AsBuffer();
//Decrypt message
string text = Cryptographic.Decrypt(buffer, "123");
//Invoke event when message Recive
InvokeOnDataRecive(text);
}
}
catch (Exception e)
{
InvokeOnError(e.Message);
}
}
Method ReceiveData
is the same on ServerTcp
class.
DisconnectAsync
public async Task DisconnectAsync()
{
try
{
_cancel.Cancel();
_reader.DetachStream();
_reader.DetachBuffer();
_writer.DetachStream();
_writer.DetachBuffer();
await _socket.CancelIOAsync();
_cancel = new CancellationTokenSource();
}
catch (Exception ex)
{
InvokeOnError(ex.Message);
}
}
Conclusion
Create a communication between server and client send encrypt message isn't hard, but you have a little work. One problem about UWP/IoT core is to find some information, because we have a small site to talk about this, compared to AspNet or WinForm. The best place to find this is Microsoft documentation, there are many examples.
History
- Created article