Implementation of AES encryption in Go

encryption.go

package helper

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"crypto/sha256"
	"encoding/base64"
	"fmt"
	"io"
)

// hashTo32Bytes will compute a cryptographically useful hash of the input string.
func hashTo32Bytes(input string) []byte {

	data := sha256.Sum256([]byte(input))
	return data[0:]

}

// DecryptString takes two strings, cryptoText and keyString.
// cryptoText is the text to be decrypted and the keyString is the key to use for the decryption.
// The function will output the resulting plain text string with an error variable.
func DecryptString(cryptoText string, keyString string) (plainTextString string, err error) {

	encrypted, err := base64.URLEncoding.DecodeString(cryptoText)
	if err != nil {
		return "", err
	}
	if len(encrypted) < aes.BlockSize {
		return "", fmt.Errorf("cipherText too short. It decodes to %v bytes but the minimum length is 16", len(encrypted))
	}

	decrypted, err := DecryptAES(hashTo32Bytes(keyString), encrypted)
	if err != nil {
		return "", err
	}

	return string(decrypted), nil
}

// DecryptAES ...
func DecryptAES(key, data []byte) ([]byte, error) {
	// split the input up in to the IV seed and then the actual encrypted data.
	iv := data[:aes.BlockSize]
	data = data[aes.BlockSize:]

	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	stream := cipher.NewCFBDecrypter(block, iv)

	stream.XORKeyStream(data, data)
	return data, nil
}

// EncryptString takes two string, plainText and keyString.
// plainText is the text that needs to be encrypted by keyString.
// The function will output the resulting crypto text and an error variable.
func EncryptString(plainText string, keyString string) (cipherTextString string, err error) {

	key := hashTo32Bytes(keyString)
	encrypted, err := encryptAES(key, []byte(plainText))
	if err != nil {
		return "", err
	}

	return base64.URLEncoding.EncodeToString(encrypted), nil
}

func encryptAES(key, data []byte) ([]byte, error) {

	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	// create two 'windows' in to the output slice.
	output := make([]byte, aes.BlockSize+len(data))
	iv := output[:aes.BlockSize]
	encrypted := output[aes.BlockSize:]

	// populate the IV slice with random data.
	if _, err = io.ReadFull(rand.Reader, iv); err != nil {
		return nil, err
	}

	stream := cipher.NewCFBEncrypter(block, iv)

	// note that encrypted is still a window in to the output slice
	stream.XORKeyStream(encrypted, data)
	return output, nil
}

EmguCV 3.x – Read and display local video file (C# .NET Visual Studio)

We are going to create a GUI application on Windows desktop using WPF on Visual Studio that reads and displays video file.

Firstly, let’s create a Window and put the following codes into its .xaml file:

< Window x:Class="NaimIbrahim.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:NaimIbrahim"
        mc:Ignorable="d"
        Title="MainWindow" 
        WindowState="Maximized"
        >
    < Grid>
        < Grid.RowDefinitions>
            < RowDefinition Height="*"/>
            < RowDefinition Height="Auto"/>
            < RowDefinition Height="Auto"/>
        < /Grid.RowDefinitions>
        < Grid.ColumnDefinitions>
            < ColumnDefinition Width="*"/>
            < ColumnDefinition Width="0"/>
        < /Grid.ColumnDefinitions>
        < Image x:Name="imageBox" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="0"/>
        < StackPanel Grid.Row="1" Grid.Column="0" Orientation="Horizontal" Margin="0,20,0,20" HorizontalAlignment="Center">
            < Button x:Name="btnOpen" Content="Open" Width="75" Margin="0,0,20,0" Click="btnOpen_Click"/>
            < Button x:Name="btnPause" Content="Pause" Width="75" Click="btnPause_Click"/>
        < /StackPanel>
    < /Grid>
< /Window>

The window will be on maximized screen, and it will have two buttons: Open and Pause.

Next, we will need to install EmguCV library or dependencies into our project solution. Right click on project solution, click ‘Manage NuGet packages for solution’. Search ‘EmguCV’ and install the NuGet package into your project. You can verify that EmguCV DLLs are installed to your project by browsing on the References menu. You can also manually download and install the EmguCV DLLs by following the instruction on EmguCV official website.

In the .cs file of the window, add the following objects into our class:

private Emgu.CV.Capture capture;
System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();

The capture object is to capture video from file, and dispatcherTimer object is to continuously read the video at every defined interval.

public MainWindow()
{
	InitializeComponent();
	Loaded += MainWindow_Loaded;

	dispatcherTimer.Tick += dispatcherTimer_Tick;
	dispatcherTimer.Interval = TimeSpan.FromMilliseconds(1000.0 / 60.0);
}

Line #4 is to read some codes once the window is loaded. Line #6 is to re-read our dispatcher function at every tick. Line #7 is to set the interval at 60 FPS (frames per second, a standard value)

void MainWindow_Loaded(object sender, EventArgs e)
{
	btnOpen.IsEnabled = true;
	btnPause.IsEnabled = false;
}

Once window is loaded, we disable the Pause button because no video is being played yet.

private void dispatcherTimer_Tick(object sender, EventArgs e)
{
	if (capture != null)
	{
		Mat mat = capture.QueryFrame();
		if (mat != null)
		{
			Image img = mat.ToImage();
			imageBox.Source = BitmapSourceConvert.ToBitmapSource(img);
		}
	}
}

The above function gets executed at every tick, that is 60 FPS. If a video file is captured, then read its frame and convert the frame to ImageSource by using a class I put at the bottom of this post.

private void btnOpen_Click(object sender, RoutedEventArgs e)
{
	OpenFileDialog openFileDialog = new OpenFileDialog();
	if (openFileDialog.ShowDialog() == true)
	{
		capture = new Emgu.CV.Capture(openFileDialog.FileName.ToString());
		dispatcherTimer.Start();
		btnPause.IsEnabled = true;
	}
}

A user clicks on the Open button and will be asked to choose a video file. Once a video is selected, we start the dispatcher timer and set the Pause button to be enabled.

private void btnPause_Click(object sender, RoutedEventArgs e)
{
	if (dispatcherTimer.IsEnabled)
	{
		dispatcherTimer.Stop();
		btnPause.Content = "Resume";
	} else
	{
		dispatcherTimer.Start();
		btnPause.Content = "Pause";
	}
	
}

And finally, the function invoked when the Pause button is clicked.

private System.Drawing.Bitmap BitmapFromSource(BitmapSource bitmapsource)
{
	System.Drawing.Bitmap bitmap;
	using (MemoryStream outStream = new MemoryStream())
	{
		BitmapEncoder enc = new BmpBitmapEncoder();
		enc.Frames.Add(BitmapFrame.Create(bitmapsource));
		enc.Save(outStream);
		bitmap = new System.Drawing.Bitmap(outStream);
	}
	return bitmap;
}