Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / UWP

Send Encrypt Data PC to Raspberry Pi 2

4.56/5 (4 votes)
3 Apr 2016CPOL3 min read 17.4K   213  
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:

  1. Create a SymmectricKeyAlgorithmProvider, that has a static method to create where you pass name of the algorithm, SymmetricAlgorithmNames class that has name of algorithm is supported
  2. Generate Hash from key
  3. Convert text to binary
  4. 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

C#
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

C#
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

C#
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

C#
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

C#
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.

C#
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

C#
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.

C#
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();
    });
}
When data received:
C#
private async void Server_OnDataRecive(ServerTcp sender, string args)
{
    //answer text receive
    await sender.SendAsync(string.Concat("Text Recive:", args));
} 

Client

A client is a Windows App using C# UWP.

Socket

A SocketClient class is responsible to create socket and communicated with some server.

Connect

C#
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

C#
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

C#
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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)