There are multiple encryption algorithms you can choose from in .NET Core. Some algorithms are implemented by the operating system and their names are suffixed with the CryptoServiceProvider
class, some are implemented entirely in .NET, some use symmetric keys, and some use asymmetric keys.
To make it easier to reuse your protection code in the future, we will create a static class named Protector
in its own class library.
In Visual Studio 2017, press Ctrl + Shift + N or navigate to File | New | Project....
In the New Project dialog, in the Installed | Templates list, expand Visual C# and select .NET Standard. In the list at the center, select Class Library (.NET Standard), type the name Ch11_CryptographyLib
, change the location to C:Code
, type the solution name as Chapter11
, and then click on OK. Rename Class1.cs
to Protector.cs
.
In Visual Studio 2017, add a new console application project named Ch11_EncryptionApp
.
Set your solution's startup project as the current selection.
In Solution Explorer, in the Ch11_EncryptionApp
project, right-click on Dependencies and choose Add Reference..., select the Ch11_CryptographyLib
project, and then click on OK.
In macOS, in the Code
folder, create a folder named Chapter11
, with two subfolders named Ch11_CryptographyLib
and Ch11_EncryptionApp
.
In Visual Studio Code, open the folder named Ch11_CryptographyLib
.
In the Integrated Terminal, enter the following command:
dotnet new classlib
Open the folder named Ch11_EncryptionApp
.
In the Integrated Terminal, enter the following command:
dotnet new console
Open the folder named Chapter11
.
In the Explorer window, expand Ch11_CryptographyLib
and rename the Class1.cs
file to Protector.cs
.
In the Ch11_EncryptionApp
project folder, open the file named Ch11_EncryptionApp.csproj
, and add a package reference to the Ch11_CryptographyLib
library, as shown highlighted in the following markup:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..Ch11_CryptographyLibCh11_CryptographyLib.csproj"
/>
</ItemGroup>
</Project>
In the Integrated Terminal, enter the following commands:
cd Ch11_EncryptionApp dotnet restore dotnet build
In both Visual Studio 2017 and Visual Studio Code, open the Protector.cs
file and change its contents to look like this:
using System; using System.Collections.Generic; using System.IO; using System.Security.Cryptography; using System.Text; using System.Xml.Linq; namespace Packt.CS7 { public static class Protector { // salt size must be at least 8 bytes, we will use 16 bytes private static readonly byte[] salt = Encoding.Unicode.GetBytes("7BANANAS"); // iterations must be at least 1000, we will use 2000 private static readonly int iterations = 2000; public static string Encrypt( string plainText, string password) { byte[] plainBytes = Encoding.Unicode.GetBytes(plainText); var aes = Aes.Create(); var pbkdf2 = new Rfc2898DeriveBytes( password, salt, iterations); aes.Key = pbkdf2.GetBytes(32); // set a 256-bit key aes.IV = pbkdf2.GetBytes(16); // set a 128-bit IV var ms = new MemoryStream(); using (var cs = new CryptoStream( ms, aes.CreateEncryptor(), CryptoStreamMode.Write)) { cs.Write(plainBytes, 0, plainBytes.Length); } return Convert.ToBase64String(ms.ToArray()); } public static string Decrypt( string cryptoText, string password) { byte[] cryptoBytes = Convert.FromBase64String(cryptoText); var aes = Aes.Create(); var pbkdf2 = new Rfc2898DeriveBytes( password, salt, iterations); aes.Key = pbkdf2.GetBytes(32); aes.IV = pbkdf2.GetBytes(16); var ms = new MemoryStream(); using (var cs = new CryptoStream( ms, aes.CreateDecryptor(), CryptoStreamMode.Write)) { cs.Write(cryptoBytes, 0, cryptoBytes.Length); } return Encoding.Unicode.GetString(ms.ToArray()); } } }
Note the following points:
Encrypt
and Decrypt
MemoryStream
type to store the results of encrypting and decrypting and then call ToArray
to turn the stream into a byte arrayIn the Ch11_EncryptionApp
project, open the Program.cs
file and then import the following namespace and type:
using Packt.CS7; using static System.Console;
In the Main
method, add the following statements to prompt the user for a message and a password and then encrypt and decrypt:
Write("Enter a message that you want to encrypt: "); string message = ReadLine(); Write("Enter a password: "); string password = ReadLine(); string cryptoText = Protector.Encrypt(message, password); WriteLine($"Encrypted text: {cryptoText}"); Write("Enter the password: "); string password2 = ReadLine(); try { string clearText = Protector.Decrypt(cryptoText, password2); WriteLine($"Decrypted text: {clearText}"); } catch { WriteLine( "Enable to decrypt because you entered the wrong password!"); }
Run the console application.
Try entering a message and password, and view the output:
Enter a message that you want to encrypt: Hello Bob Enter a password: secret Encrypted text: pV5qPDf1CCZmGzUMH2gapFSkn573lg7tMj5ajice3cQ= Enter the password: secret Decrypted text: Hello Bob
Rerun the application and try entering a message and password, but this time enter the password incorrectly after encrypting and view the output:
Enter a message that you want to encrypt: Hello Bob Enter a password: secret Encrypted text: pV5qPDf1CCZmGzUMH2gapFSkn573lg7tMj5ajice3cQ= Enter the password: 123456 Enable to decrypt because you entered the wrong password!
18.219.198.159