Squashed 'FSI.Lib/' content from commit 6aa4846
git-subtree-dir: FSI.Lib git-subtree-split: 6aa48465a834a7bfdd9cbeae8d2e4f769d0c0ff8
This commit is contained in:
704
FSI.Lib/EasyEncryption/Encryption.cs
Normal file
704
FSI.Lib/EasyEncryption/Encryption.cs
Normal file
@@ -0,0 +1,704 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace FSI.Lib.EasyEncryption
|
||||
{
|
||||
/// <summary>
|
||||
/// Encryption algorithm types.
|
||||
/// </summary>
|
||||
public enum EncryptionAlgorithm
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the Advanced Encryption Standard (AES) symmetric encryption algorithm.
|
||||
/// </summary>
|
||||
Aes,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the Data Encryption Standard (DES) symmetric encryption algorithm.
|
||||
/// </summary>
|
||||
Des,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the RC2 symmetric encryption algorithm.
|
||||
/// </summary>
|
||||
Rc2,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the Rijndael symmetric encryption algorithm.
|
||||
/// </summary>
|
||||
Rijndael,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the TripleDES symmetric encryption algorithm.
|
||||
/// </summary>
|
||||
TripleDes
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class to provide encryption and decryption services.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The Encryption class performs encryption and decryption using the specified algorithm.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The encrypted values may appear considerably larger than the decrypted values
|
||||
/// because encrypted values contains some additional meta data. If either data size or
|
||||
/// performance is a concern, use the <see cref="CreateStreamReader(Stream)"/> or
|
||||
/// <see cref="CreateStreamWriter(Stream)"/> methods to work with the streaming classes
|
||||
/// instead.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public class Encryption
|
||||
{
|
||||
private static readonly int SaltLength = 8;
|
||||
|
||||
private static readonly Dictionary<EncryptionAlgorithm, Type> AlgorithmLookup = new Dictionary<EncryptionAlgorithm, Type>
|
||||
{
|
||||
[EncryptionAlgorithm.Aes] = typeof(Aes),
|
||||
[EncryptionAlgorithm.Des] = typeof(DES),
|
||||
[EncryptionAlgorithm.Rc2] = typeof(RC2),
|
||||
[EncryptionAlgorithm.Rijndael] = typeof(Rijndael),
|
||||
[EncryptionAlgorithm.TripleDes] = typeof(TripleDES),
|
||||
};
|
||||
|
||||
private string Password { get; }
|
||||
private Type AlgorithmType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Converts a byte array to a string.
|
||||
/// </summary>
|
||||
/// <param name="bytes">The byte array to be converted.</param>
|
||||
/// <returns>Returns the converted string.</returns>
|
||||
public static string EncodeBytesToString(byte[] bytes) => Convert.ToBase64String(bytes);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string to a byte array.
|
||||
/// </summary>
|
||||
/// <param name="s">The string to be converted.</param>
|
||||
/// <returns>Returns the converted byte array.</returns>
|
||||
public static byte[] DecodeBytesFromString(string s) => Convert.FromBase64String(s);
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new <c>Encryption</c> instance.
|
||||
/// </summary>
|
||||
/// <param name="password">Specifies the encryption password. Leading and trailing spaces are removed.</param>
|
||||
/// <param name="algorithm">Specifies which encryption algorithm is used.</param>
|
||||
public Encryption(string password, EncryptionAlgorithm algorithm)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(password))
|
||||
throw new ArgumentException("Password is required.", nameof(password));
|
||||
Password = password.Trim();
|
||||
AlgorithmType = AlgorithmLookup[algorithm];
|
||||
}
|
||||
|
||||
#region Encryption stream creation methods
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="EncryptionWriter"/> instance using the specified stream.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The <see cref="EncryptionWriter"/> class is the preferred method to encrypt data
|
||||
/// as it will store some necessary meta data only once for all data in the stream.
|
||||
/// It is also more performant. The other encryption methods defer to the EncryptionWriter
|
||||
/// class for actual encryption.
|
||||
/// </remarks>
|
||||
/// <param name="stream">The stream the encrypted data will be written to.</param>
|
||||
/// <returns>An instance of the <see cref="EncryptionWriter"/> class.</returns>
|
||||
public EncryptionWriter CreateStreamWriter(Stream stream)
|
||||
{
|
||||
// Create a random salt and write to stream
|
||||
byte[] salt = CreateSalt();
|
||||
stream.Write(salt, 0, salt.Length);
|
||||
// Create symmetric algorithm
|
||||
SymmetricAlgorithm algorithm = CreateAlgorithm();
|
||||
algorithm.Padding = PaddingMode.PKCS7;
|
||||
// Create key and IV
|
||||
byte[] key, iv;
|
||||
GenerateKeyAndIv(algorithm, salt, out key, out iv);
|
||||
// Create EncryptionWriter
|
||||
ICryptoTransform encryptor = algorithm.CreateEncryptor(key, iv);
|
||||
CryptoStream cs = new CryptoStream(stream, encryptor, CryptoStreamMode.Write);
|
||||
return new EncryptionWriter(algorithm, encryptor, stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="EncryptionWriter"/> instance using the specified file name.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The <see cref="EncryptionWriter"/> class is the preferred method to encrypt data
|
||||
/// as it will store some necessary meta data only once for all data in the stream.
|
||||
/// It is also more performant. The other encryption methods defer to the EncryptionWriter
|
||||
/// class for actual encryption.
|
||||
/// </remarks>
|
||||
/// <param name="path">The file name the encrypted data will be written to.</param>
|
||||
/// <returns>An instance of the <see cref="EncryptionWriter"/> class.</returns>
|
||||
public EncryptionWriter CreateStreamWriter(string path)
|
||||
{
|
||||
return CreateStreamWriter(File.Open(path, FileMode.OpenOrCreate, FileAccess.Write));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="EncryptionReader"/> instance using the specified stream.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The <see cref="EncryptionReader"/> class is the preferred method to decrypt data.
|
||||
/// It is also more performant. The other decryption methods defer to the EncryptionReader
|
||||
/// class for actual decryption.
|
||||
/// </remarks>
|
||||
/// <param name="stream">The stream the encrypted data will be read from.</param>
|
||||
/// <returns>An instance of the <see cref="EncryptionReader"/> class.</returns>
|
||||
public EncryptionReader CreateStreamReader(Stream stream)
|
||||
{
|
||||
// Read salt from input stream
|
||||
byte[] salt = new byte[SaltLength];
|
||||
if (stream.Read(salt, 0, salt.Length) < SaltLength)
|
||||
throw new ArgumentOutOfRangeException("Reached end of input stream before reading encryption metadata.");
|
||||
// Create symmetric algorithm
|
||||
SymmetricAlgorithm algorithm = CreateAlgorithm();
|
||||
algorithm.Padding = PaddingMode.PKCS7;
|
||||
// Create key and IV
|
||||
byte[] key, iv;
|
||||
GenerateKeyAndIv(algorithm, salt, out key, out iv);
|
||||
// Create EncryptionReader
|
||||
ICryptoTransform decryptor = algorithm.CreateDecryptor(key, iv);
|
||||
CryptoStream cs = new CryptoStream(stream, decryptor, CryptoStreamMode.Read);
|
||||
return new EncryptionReader(algorithm, decryptor, stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="EncryptionReader"/> instance using the specified file name.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The <see cref="EncryptionReader"/> class is the preferred method to decrypt data.
|
||||
/// It is also more performant. The other decryption methods defer to the EncryptionReader
|
||||
/// class for actual decryption.
|
||||
/// </remarks>
|
||||
/// <param name="path">The file name the encrypted data will be read from.</param>
|
||||
/// <returns>An instance of the <see cref="EncryptionReader"/> class.</returns>
|
||||
public EncryptionReader CreateStreamReader(string path)
|
||||
{
|
||||
return CreateStreamReader(File.Open(path, FileMode.Open, FileAccess.Read));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Encryption
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a <c>string</c> value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The encrypted value will be larger than the unencrypted value because the
|
||||
/// encrypted value will contain some additional meta data. To minimize the
|
||||
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
|
||||
/// to create a <see cref="EncryptionWriter"/> instead.
|
||||
/// </remarks>
|
||||
/// <param name="value">The value to decrypt.</param>
|
||||
/// <returns>Returns the encrypted value</returns>
|
||||
public string Encrypt(string value) => Encrypt(w => w.Write(value ?? string.Empty));
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a <c>bool</c> value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The encrypted value will be larger than the unencrypted value because the
|
||||
/// encrypted value will contain some additional meta data. To minimize the
|
||||
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
|
||||
/// to create a <see cref="EncryptionWriter"/> instead.
|
||||
/// </remarks>
|
||||
/// <param name="value">The value to decrypt.</param>
|
||||
/// <returns>Returns the encrypted value</returns>
|
||||
public string Encrypt(bool value) => Encrypt(w => w.Write(value));
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a <c>char</c> value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The encrypted value will be larger than the unencrypted value because the
|
||||
/// encrypted value will contain some additional meta data. To minimize the
|
||||
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
|
||||
/// to create a <see cref="EncryptionWriter"/> instead.
|
||||
/// </remarks>
|
||||
/// <param name="value">The value to decrypt.</param>
|
||||
/// <returns>Returns the encrypted value</returns>
|
||||
public string Encrypt(char value) => Encrypt(w => w.Write(value));
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a <c>sbyte</c> value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The encrypted value will be larger than the unencrypted value because the
|
||||
/// encrypted value will contain some additional meta data. To minimize the
|
||||
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
|
||||
/// to create a <see cref="EncryptionWriter"/> instead.
|
||||
/// </remarks>
|
||||
/// <param name="value">The value to decrypt.</param>
|
||||
/// <returns>Returns the encrypted value</returns>
|
||||
public string Encrypt(sbyte value) => Encrypt(w => w.Write(value));
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a <c>byte</c> value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The encrypted value will be larger than the unencrypted value because the
|
||||
/// encrypted value will contain some additional meta data. To minimize the
|
||||
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
|
||||
/// to create a <see cref="EncryptionWriter"/> instead.
|
||||
/// </remarks>
|
||||
/// <param name="value">The value to decrypt.</param>
|
||||
/// <returns>Returns the encrypted value</returns>
|
||||
public string Encrypt(byte value) => Encrypt(w => w.Write(value));
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a <c>short</c> value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The encrypted value will be larger than the unencrypted value because the
|
||||
/// encrypted value will contain some additional meta data. To minimize the
|
||||
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
|
||||
/// to create a <see cref="EncryptionWriter"/> instead.
|
||||
/// </remarks>
|
||||
/// <param name="value">The value to decrypt.</param>
|
||||
/// <returns>Returns the encrypted value</returns>
|
||||
public string Encrypt(short value) => Encrypt(w => w.Write(value));
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a <c>ushort</c> value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The encrypted value will be larger than the unencrypted value because the
|
||||
/// encrypted value will contain some additional meta data. To minimize the
|
||||
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
|
||||
/// to create a <see cref="EncryptionWriter"/> instead.
|
||||
/// </remarks>
|
||||
/// <param name="value">The value to decrypt.</param>
|
||||
/// <returns>Returns the encrypted value</returns>
|
||||
public string Encrypt(ushort value) => Encrypt(w => w.Write(value));
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a <c>int</c> value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The encrypted value will be larger than the unencrypted value because the
|
||||
/// encrypted value will contain some additional meta data. To minimize the
|
||||
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
|
||||
/// to create a <see cref="EncryptionWriter"/> instead.
|
||||
/// </remarks>
|
||||
/// <param name="value">The value to decrypt.</param>
|
||||
/// <returns>Returns the encrypted value</returns>
|
||||
public string Encrypt(int value) => Encrypt(w => w.Write(value));
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a <c>uint</c> value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The encrypted value will be larger than the unencrypted value because the
|
||||
/// encrypted value will contain some additional meta data. To minimize the
|
||||
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
|
||||
/// to create a <see cref="EncryptionWriter"/> instead.
|
||||
/// </remarks>
|
||||
/// <param name="value">The value to decrypt.</param>
|
||||
/// <returns>Returns the encrypted value</returns>
|
||||
public string Encrypt(uint value) => Encrypt(w => w.Write(value));
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a <c>long</c> value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The encrypted value will be larger than the unencrypted value because the
|
||||
/// encrypted value will contain some additional meta data. To minimize the
|
||||
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
|
||||
/// to create a <see cref="EncryptionWriter"/> instead.
|
||||
/// </remarks>
|
||||
/// <param name="value">The value to decrypt.</param>
|
||||
/// <returns>Returns the encrypted value</returns>
|
||||
public string Encrypt(long value) => Encrypt(w => w.Write(value));
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a <c>ulong</c> value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The encrypted value will be larger than the unencrypted value because the
|
||||
/// encrypted value will contain some additional meta data. To minimize the
|
||||
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
|
||||
/// to create a <see cref="EncryptionWriter"/> instead.
|
||||
/// </remarks>
|
||||
/// <param name="value">The value to decrypt.</param>
|
||||
/// <returns>Returns the encrypted value</returns>
|
||||
public string Encrypt(ulong value) => Encrypt(w => w.Write(value));
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a <c>float</c> value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The encrypted value will be larger than the unencrypted value because the
|
||||
/// encrypted value will contain some additional meta data. To minimize the
|
||||
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
|
||||
/// to create a <see cref="EncryptionWriter"/> instead.
|
||||
/// </remarks>
|
||||
/// <param name="value">The value to decrypt.</param>
|
||||
/// <returns>Returns the encrypted value</returns>
|
||||
public string Encrypt(float value) => Encrypt(w => w.Write(value));
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a <c>double</c> value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The encrypted value will be larger than the unencrypted value because the
|
||||
/// encrypted value will contain some additional meta data. To minimize the
|
||||
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
|
||||
/// to create a <see cref="EncryptionWriter"/> instead.
|
||||
/// </remarks>
|
||||
/// <param name="value">The value to decrypt.</param>
|
||||
/// <returns>Returns the encrypted value</returns>
|
||||
public string Encrypt(double value) => Encrypt(w => w.Write(value));
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a <c>decimal</c> value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The encrypted value will be larger than the unencrypted value because the
|
||||
/// encrypted value will contain some additional meta data. To minimize the
|
||||
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
|
||||
/// to create a <see cref="EncryptionWriter"/> instead.
|
||||
/// </remarks>
|
||||
/// <param name="value">The value to decrypt.</param>
|
||||
/// <returns>Returns the encrypted value</returns>
|
||||
public string Encrypt(decimal value) => Encrypt(w => w.Write(value));
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a <c>DateTime</c> value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The encrypted value will be larger than the unencrypted value because the
|
||||
/// encrypted value will contain some additional meta data. To minimize the
|
||||
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
|
||||
/// to create a <see cref="EncryptionWriter"/> instead.
|
||||
/// </remarks>
|
||||
/// <param name="value">The value to decrypt.</param>
|
||||
/// <returns>Returns the encrypted value</returns>
|
||||
public string Encrypt(DateTime value) => Encrypt(w => w.Write(value));
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a <c>byte[]</c> value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The encrypted value will be larger than the unencrypted value because the
|
||||
/// encrypted value will contain some additional meta data. To minimize the
|
||||
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
|
||||
/// to create a <see cref="EncryptionWriter"/> instead.
|
||||
/// </remarks>
|
||||
/// <param name="value">The value to decrypt.</param>
|
||||
/// <returns>Returns the encrypted value</returns>
|
||||
public string Encrypt(byte[] value) => Encrypt(w => w.Write(value));
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a <c>string[]</c> value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The encrypted value will be larger than the unencrypted value because the
|
||||
/// encrypted value will contain some additional meta data. To minimize the
|
||||
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
|
||||
/// to create a <see cref="EncryptionWriter"/> instead.
|
||||
/// </remarks>
|
||||
/// <param name="value">The value to decrypt.</param>
|
||||
/// <returns>Returns the encrypted value</returns>
|
||||
public string Encrypt(string[] value) => Encrypt(w => w.Write(value));
|
||||
|
||||
private string Encrypt(Action<EncryptionWriter> action)
|
||||
{
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
using (EncryptionWriter writer = CreateStreamWriter(stream))
|
||||
{
|
||||
action(writer);
|
||||
return EncodeBytesToString(stream.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Decryption
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a <c>string</c> value encrypted with <see cref="Encrypt(string)"/>.
|
||||
/// </summary>
|
||||
/// <param name="encryptedValue">The value to decrypt.</param>
|
||||
/// <returns>Returns the decrypted value</returns>
|
||||
public string DecryptString(string encryptedValue) => (string)Decrypt(encryptedValue, r => r.ReadString());
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a <c>bool</c> value encrypted with <see cref="Encrypt(bool)"/>.
|
||||
/// </summary>
|
||||
/// <param name="encryptedValue">The value to decrypt.</param>
|
||||
/// <returns>Returns the decrypted value</returns>
|
||||
public bool DecryptBoolean(string encryptedValue) => (bool)Decrypt(encryptedValue, r => r.ReadBoolean());
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a <c>char</c> value encrypted with <see cref="Encrypt(char)"/>.
|
||||
/// </summary>
|
||||
/// <param name="encryptedValue">The value to decrypt.</param>
|
||||
/// <returns>Returns the decrypted value</returns>
|
||||
public char DecryptChar(string encryptedValue) => (char)Decrypt(encryptedValue, r => r.ReadChar());
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a <c>sbyte</c> value encrypted with <see cref="Encrypt(sbyte)"/>.
|
||||
/// </summary>
|
||||
/// <param name="encryptedValue">The value to decrypt.</param>
|
||||
/// <returns>Returns the decrypted value</returns>
|
||||
public sbyte DecryptSByte(string encryptedValue) => (sbyte)Decrypt(encryptedValue, r => r.ReadSByte());
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a <c>byte</c> value encrypted with <see cref="Encrypt(byte)"/>.
|
||||
/// </summary>
|
||||
/// <param name="encryptedValue">The value to decrypt.</param>
|
||||
/// <returns>Returns the decrypted value</returns>
|
||||
public byte DecryptByte(string encryptedValue) => (byte)Decrypt(encryptedValue, r => r.ReadByte());
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a <c>short</c> value encrypted with <see cref="Encrypt(short)"/>.
|
||||
/// </summary>
|
||||
/// <param name="encryptedValue">The value to decrypt.</param>
|
||||
/// <returns>Returns the decrypted value</returns>
|
||||
public short DecryptInt16(string encryptedValue) => (short)Decrypt(encryptedValue, r => r.ReadInt16());
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a <c>ushort</c> value encrypted with <see cref="Encrypt(ushort)"/>.
|
||||
/// </summary>
|
||||
/// <param name="encryptedValue">The value to decrypt.</param>
|
||||
/// <returns>Returns the decrypted value</returns>
|
||||
public ushort DecryptUInt16(string encryptedValue) => (ushort)Decrypt(encryptedValue, r => r.ReadUInt16());
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a <c>int</c> value encrypted with <see cref="Encrypt(int)"/>.
|
||||
/// </summary>
|
||||
/// <param name="encryptedValue">The value to decrypt.</param>
|
||||
/// <returns>Returns the decrypted value</returns>
|
||||
public int DecryptInt32(string encryptedValue) => (int)Decrypt(encryptedValue, r => r.ReadInt32());
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a <c>uint</c> value encrypted with <see cref="Encrypt(uint)"/>.
|
||||
/// </summary>
|
||||
/// <param name="encryptedValue">The value to decrypt.</param>
|
||||
/// <returns>Returns the decrypted value</returns>
|
||||
public uint DecryptUInt32(string encryptedValue) => (uint)Decrypt(encryptedValue, r => r.ReadUInt32());
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a <c>long</c> value encrypted with <see cref="Encrypt(long)"/>.
|
||||
/// </summary>
|
||||
/// <param name="encryptedValue">The value to decrypt.</param>
|
||||
/// <returns>Returns the decrypted value</returns>
|
||||
public long DecryptInt64(string encryptedValue) => (long)Decrypt(encryptedValue, r => r.ReadInt64());
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a <c>ulong</c> value encrypted with <see cref="Encrypt(ulong)"/>.
|
||||
/// </summary>
|
||||
/// <param name="encryptedValue">The value to decrypt.</param>
|
||||
/// <returns>Returns the decrypted value</returns>
|
||||
public ulong DecryptUInt64(string encryptedValue) => (ulong)Decrypt(encryptedValue, r => r.ReadUInt64());
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a <c>float</c> value encrypted with <see cref="Encrypt(float)"/>.
|
||||
/// </summary>
|
||||
/// <param name="encryptedValue">The value to decrypt.</param>
|
||||
/// <returns>Returns the decrypted value</returns>
|
||||
public float DecryptSingle(string encryptedValue) => (float)Decrypt(encryptedValue, r => r.ReadSingle());
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a <c>double</c> value encrypted with <see cref="Encrypt(double)"/>.
|
||||
/// </summary>
|
||||
/// <param name="encryptedValue">The value to decrypt.</param>
|
||||
/// <returns>Returns the decrypted value</returns>
|
||||
public double DecryptDouble(string encryptedValue) => (double)Decrypt(encryptedValue, r => r.ReadDouble());
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a <c>decimal</c> value encrypted with <see cref="Encrypt(decimal)"/>.
|
||||
/// </summary>
|
||||
/// <param name="encryptedValue">The value to decrypt.</param>
|
||||
/// <returns>Returns the decrypted value</returns>
|
||||
public decimal DecryptDecimal(string encryptedValue) => (decimal)Decrypt(encryptedValue, r => r.ReadDecimal());
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a <c>DateTime</c> value encrypted with <see cref="Encrypt(DateTime)"/>.
|
||||
/// </summary>
|
||||
/// <param name="encryptedValue">The value to decrypt.</param>
|
||||
/// <returns>Returns the decrypted value</returns>
|
||||
public DateTime DecryptDateTime(string encryptedValue) => (DateTime)Decrypt(encryptedValue, r => r.ReadDateTime());
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a <c>byte[]</c> value encrypted with <see cref="Encrypt(byte[])"/>.
|
||||
/// </summary>
|
||||
/// <param name="encryptedValue">The value to decrypt.</param>
|
||||
/// <returns>Returns the decrypted value</returns>
|
||||
public byte[] DecryptByteArray(string encryptedValue) => (byte[])Decrypt(encryptedValue, r => r.ReadByteArray());
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a <c>string[]</c> value encrypted with <see cref="Encrypt(string[])"/>.
|
||||
/// </summary>
|
||||
/// <param name="encryptedValue">The value to decrypt.</param>
|
||||
/// <returns>Returns the decrypted value</returns>
|
||||
public string[] DecryptStringArray(string encryptedValue) => (string[])Decrypt(encryptedValue, r => r.ReadStringArray());
|
||||
|
||||
private object Decrypt(string encryptedValue, Func<EncryptionReader, object> action)
|
||||
{
|
||||
using (MemoryStream stream = new MemoryStream(DecodeBytesFromString(encryptedValue)))
|
||||
using (EncryptionReader reader = CreateStreamReader(stream))
|
||||
{
|
||||
return action(reader);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Encryption/decryption of objects
|
||||
|
||||
/// <summary>
|
||||
/// Class to hold encrypt/decrypt functions for each supported data type.
|
||||
/// </summary>
|
||||
private class TypeInfo
|
||||
{
|
||||
public Func<Encryption, object, string> Encrypt { get; set; }
|
||||
public Func<Encryption, string, object> Decrypt { get; set; }
|
||||
|
||||
public TypeInfo(Func<Encryption, object, string> encrypt, Func<Encryption, string, object> decrypt)
|
||||
{
|
||||
Encrypt = encrypt;
|
||||
Decrypt = decrypt;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Dictionary<Type, TypeInfo> TypeInfoLookup = new Dictionary<Type, TypeInfo>()
|
||||
{
|
||||
[typeof(string)] = new TypeInfo((e, v) => e.Encrypt((string)v), (e, s) => e.DecryptString(s)),
|
||||
[typeof(bool)] = new TypeInfo((e, v) => e.Encrypt((bool)v), (e, s) => e.DecryptBoolean(s)),
|
||||
[typeof(char)] = new TypeInfo((e, v) => e.Encrypt((char)v), (e, s) => e.DecryptChar(s)),
|
||||
[typeof(sbyte)] = new TypeInfo((e, v) => e.Encrypt((sbyte)v), (e, s) => e.DecryptSByte(s)),
|
||||
[typeof(byte)] = new TypeInfo((e, v) => e.Encrypt((byte)v), (e, s) => e.DecryptByte(s)),
|
||||
[typeof(short)] = new TypeInfo((e, v) => e.Encrypt((short)v), (e, s) => e.DecryptInt16(s)),
|
||||
[typeof(ushort)] = new TypeInfo((e, v) => e.Encrypt((ushort)v), (e, s) => e.DecryptUInt16(s)),
|
||||
[typeof(int)] = new TypeInfo((e, v) => e.Encrypt((int)v), (e, s) => e.DecryptInt32(s)),
|
||||
[typeof(uint)] = new TypeInfo((e, v) => e.Encrypt((uint)v), (e, s) => e.DecryptUInt32(s)),
|
||||
[typeof(long)] = new TypeInfo((e, v) => e.Encrypt((long)v), (e, s) => e.DecryptInt64(s)),
|
||||
[typeof(ulong)] = new TypeInfo((e, v) => e.Encrypt((ulong)v), (e, s) => e.DecryptUInt64(s)),
|
||||
[typeof(float)] = new TypeInfo((e, v) => e.Encrypt((float)v), (e, s) => e.DecryptSingle(s)),
|
||||
[typeof(double)] = new TypeInfo((e, v) => e.Encrypt((double)v), (e, s) => e.DecryptDouble(s)),
|
||||
[typeof(decimal)] = new TypeInfo((e, v) => e.Encrypt((decimal)v), (e, s) => e.DecryptDecimal(s)),
|
||||
[typeof(DateTime)] = new TypeInfo((e, v) => e.Encrypt((DateTime)v), (e, s) => e.DecryptDateTime(s)),
|
||||
[typeof(byte[])] = new TypeInfo((e, v) => e.Encrypt((byte[])v), (e, s) => e.DecryptByteArray(s)),
|
||||
[typeof(string[])] = new TypeInfo((e, v) => e.Encrypt((string[])v), (e, s) => e.DecryptStringArray(s)),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the specified data type is supported by the encryption and decryption methods.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The encryption code supports all basic .NET data types in addition to <c>byte[]</c>
|
||||
/// and <c>string[]</c>. More complex data types are not supported.
|
||||
/// </remarks>
|
||||
/// <param name="type">The data type to be tested.</param>
|
||||
/// <returns>True if the specified type is supported. False otherwise.</returns>
|
||||
public static bool IsTypeSupported(Type type) => TypeInfoLookup.ContainsKey(type);
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts an object value. The object must hold one of the supported data types.
|
||||
/// </summary>
|
||||
/// <param name="value">Object to be encrypted.</param>
|
||||
/// <exception cref="ArgumentException"><paramref name="value"/> holds an unsupported data type.</exception>
|
||||
/// <returns>An encrypted string that can be decrypted using Decrypt.</returns>
|
||||
public string Encrypt(object value)
|
||||
{
|
||||
if (value == null)
|
||||
return null;
|
||||
if (TypeInfoLookup.TryGetValue(value.GetType(), out TypeInfo info))
|
||||
return info.Encrypt(this, value);
|
||||
throw new ArgumentException(string.Format("Cannot encrypt value : Data type '{0}' is not supported", value.GetType()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts an object value of the specified type.
|
||||
/// </summary>
|
||||
/// <param name="encryptedValue">The encrypted string to be decrypted.</param>
|
||||
/// <param name="targetType">The type of data that was originally encrypted into <paramref name="encryptedValue"/>.</param>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
/// <returns>Returns the decrypted value.</returns>
|
||||
public object Decrypt(string encryptedValue, Type targetType)
|
||||
{
|
||||
if (TypeInfoLookup.TryGetValue(targetType, out TypeInfo info))
|
||||
return info.Decrypt(this, encryptedValue);
|
||||
throw new ArgumentException(string.Format("Cannot decrypt value : Data type '{0}' is not supported", targetType));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Support methods
|
||||
|
||||
/// <summary>
|
||||
/// Creates a SymmetricAlgorithm instance for the current encryption algorithm.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Returns the created SymmetricAlgorithm instance.
|
||||
/// </returns>
|
||||
protected SymmetricAlgorithm CreateAlgorithm()
|
||||
{
|
||||
MethodInfo method = AlgorithmType.GetMethod("Create", Array.Empty<Type>());
|
||||
if (method != null)
|
||||
{
|
||||
if (method.Invoke(null, null) is SymmetricAlgorithm algorithm)
|
||||
return algorithm;
|
||||
}
|
||||
throw new Exception($"Unable to create instance of {AlgorithmType.FullName}.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a salt that contains a cryptographically strong sequence of random values.
|
||||
/// </summary>
|
||||
/// <returns>The generated salt value.</returns>
|
||||
private byte[] CreateSalt()
|
||||
{
|
||||
byte[] salt = new byte[SaltLength];
|
||||
using (RNGCryptoServiceProvider generator = new RNGCryptoServiceProvider())
|
||||
{
|
||||
generator.GetBytes(salt);
|
||||
}
|
||||
return salt;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a pseudorandom key and initialization vector from the current password and the
|
||||
/// given salt.
|
||||
/// </summary>
|
||||
/// <param name="algorithm"><see cref="SymmetricAlgorithm"></see> being used to encrypt.</param>
|
||||
/// <param name="salt">The salt used to derive the key and initialization vector.</param>
|
||||
/// <param name="key">Returns the generated key.</param>
|
||||
/// <param name="iv">Returns the generated initialization vector.</param>
|
||||
protected void GenerateKeyAndIv(SymmetricAlgorithm algorithm, byte[] salt, out byte[] key, out byte[] iv)
|
||||
{
|
||||
int keyLength = algorithm.KeySize >> 3;
|
||||
int ivLength = algorithm.BlockSize >> 3;
|
||||
byte[] bytes = DeriveBytes(salt, keyLength + ivLength);
|
||||
key = new byte[keyLength];
|
||||
Buffer.BlockCopy(bytes, 0, key, 0, keyLength);
|
||||
iv = new byte[ivLength];
|
||||
Buffer.BlockCopy(bytes, keyLength, iv, 0, ivLength);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a series of pseudorandom bytes of the specified length based on the current
|
||||
/// password and the given salt.
|
||||
/// </summary>
|
||||
/// <param name="salt">The salt used to derive the bytes.</param>
|
||||
/// <param name="bytes">The number of bits of data to generate.</param>
|
||||
/// <returns>Returns the derived bytes.</returns>
|
||||
protected byte[] DeriveBytes(byte[] salt, int bytes)
|
||||
{
|
||||
Rfc2898DeriveBytes derivedBytes = new Rfc2898DeriveBytes(Password, salt, 1000);
|
||||
return derivedBytes.GetBytes(bytes);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
105
FSI.Lib/EasyEncryption/EncryptionReader.cs
Normal file
105
FSI.Lib/EasyEncryption/EncryptionReader.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace FSI.Lib.EasyEncryption
|
||||
{
|
||||
/// <summary>
|
||||
/// Class that provides streaming decryption functionality.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Using this class is the preferred way to decrypt values from a file or memory.
|
||||
/// Other decryption methods defer to this class for actual decryption.
|
||||
/// </remarks>
|
||||
public class EncryptionReader : BinaryReader, IDisposable
|
||||
{
|
||||
private SymmetricAlgorithm Algorithm;
|
||||
private ICryptoTransform Decryptor;
|
||||
|
||||
internal EncryptionReader(SymmetricAlgorithm algorithm, ICryptoTransform decryptor, Stream stream) : base(stream)
|
||||
{
|
||||
Algorithm = algorithm;
|
||||
Decryptor = decryptor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a <c>DateTime</c> value from the encrypted stream.
|
||||
/// </summary>
|
||||
/// <returns>The decrypted value.</returns>
|
||||
public DateTime ReadDateTime()
|
||||
{
|
||||
return new DateTime(ReadInt64());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a <c>byte[]</c> value from the encrypted stream.
|
||||
/// </summary>
|
||||
/// <returns>The decrypted values.</returns>
|
||||
public byte[] ReadByteArray()
|
||||
{
|
||||
int count = ReadInt32();
|
||||
byte[] bytes = new byte[count];
|
||||
if (count > 0)
|
||||
Read(bytes, 0, count);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a <c>string[]</c> value from the encrypted stream.
|
||||
/// </summary>
|
||||
/// <returns>The decrypted values.</returns>
|
||||
public string[] ReadStringArray()
|
||||
{
|
||||
int count = ReadInt32();
|
||||
string[] strings = new string[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
strings[i] = ReadString();
|
||||
return strings;
|
||||
}
|
||||
|
||||
#region IDisposable implementation
|
||||
|
||||
private bool disposed = false; // To detect redundant calls
|
||||
|
||||
/// <summary>
|
||||
/// Releases all resources used by the current instance of the <c>EncryptionReader</c> class.
|
||||
/// </summary>
|
||||
public new void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases the unmanaged resources used by the <c>EncryptionReader</c> class and optionally
|
||||
/// releases the managed resources.
|
||||
/// </summary>
|
||||
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources;
|
||||
/// <c>false</c> to release only unmanaged resources.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
disposed = true;
|
||||
if (disposing)
|
||||
{
|
||||
// Dispose managed objects
|
||||
base.Dispose(true);
|
||||
Decryptor.Dispose();
|
||||
Algorithm.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destructs this instance of <c>EncryptionReader</c>.
|
||||
/// </summary>
|
||||
~EncryptionReader()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
105
FSI.Lib/EasyEncryption/EncryptionWriter.cs
Normal file
105
FSI.Lib/EasyEncryption/EncryptionWriter.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace FSI.Lib.EasyEncryption
|
||||
{
|
||||
/// <summary>
|
||||
/// Class that provides streaming encryption functionality.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Using this class is the preferred way to encrypt values to a file or memory.
|
||||
/// Other encryption methods defer to this class for actual encryption. Meta data
|
||||
/// that must be stored with the encrypted result is only stored once for all
|
||||
/// data in the stream.
|
||||
/// </remarks>
|
||||
public class EncryptionWriter : BinaryWriter, IDisposable
|
||||
{
|
||||
private readonly SymmetricAlgorithm Algorithm;
|
||||
private readonly ICryptoTransform Encryptor;
|
||||
|
||||
internal EncryptionWriter(SymmetricAlgorithm algorithm, ICryptoTransform encryptor, Stream stream) : base(stream)
|
||||
{
|
||||
Algorithm = algorithm;
|
||||
Encryptor = encryptor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <c>DateTime</c> value to the encrypted stream.
|
||||
/// </summary>
|
||||
/// <param name="value"><c>DateTime</c> value to write.</param>
|
||||
public void Write(DateTime value)
|
||||
{
|
||||
Write(value.Ticks);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <c>byte</c> array to the encrypted stream.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note: Hides <c>BinaryWriter.Write(byte[])</c>.
|
||||
/// </remarks>
|
||||
/// <param name="value"><c>byte[]</c> values to write.</param>
|
||||
public new void Write(byte[] value)
|
||||
{
|
||||
Write(value.Length);
|
||||
Write(value, 0, value.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <c>string</c> to the encrypted stream.
|
||||
/// </summary>
|
||||
/// <param name="value"><c>string[]</c> values to write.</param>
|
||||
public void Write(string[] value)
|
||||
{
|
||||
Write(value.Length);
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
Write(value[i]);
|
||||
}
|
||||
|
||||
#region IDisposable implementation
|
||||
|
||||
private bool disposed = false; // To detect redundant calls
|
||||
|
||||
/// <summary>
|
||||
/// Releases all resources used by the current instance of the <c>EncryptionWriter</c> class.
|
||||
/// </summary>
|
||||
public new void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases the unmanaged resources used by the <c>EncryptionWriter</c> class and optionally
|
||||
/// releases the managed resources.
|
||||
/// </summary>
|
||||
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources;
|
||||
/// <c>false</c> to release only unmanaged resources.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
disposed = true;
|
||||
if (disposing)
|
||||
{
|
||||
// Dispose managed objects
|
||||
base.Dispose(true);
|
||||
Encryptor.Dispose();
|
||||
Algorithm.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destructs this instance of <c>EncryptionWriter</c>.
|
||||
/// </summary>
|
||||
~EncryptionWriter()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
90
FSI.Lib/EasyEncryption/Readme.md
Normal file
90
FSI.Lib/EasyEncryption/Readme.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# EasyEncryption
|
||||
|
||||
[](https://www.nuget.org/packages/SoftCircuits.EasyEncryption/)
|
||||
|
||||
```
|
||||
Install-Package SoftCircuits.EasyEncryption
|
||||
```
|
||||
|
||||
The .NET Framework provides a number of encryption routines. However, these routines generally require a bit of work to set up correctly. Use `EasyEncryption` to make these encryption routines more easily accessible.
|
||||
|
||||
## Encrypting a String
|
||||
|
||||
The `Encrypt()` method can be used to encrypt a string. Use `DecryptString()` to decrypt the string back to the original.
|
||||
|
||||
```cs
|
||||
Encryption encrypt = new Encryption("Password123", EncryptionAlgorithm.TripleDes);
|
||||
|
||||
string original = "This is my message";
|
||||
string cipher = encrypt.Encrypt(original);
|
||||
string result = encrypt.DecryptString(cipher);
|
||||
|
||||
Debug.Assert(result == message);
|
||||
```
|
||||
|
||||
## Encrypting other Types
|
||||
|
||||
The `Encrypt()` method is overloaded to encrypt many different data types. When decrypting, you must use the decryption method specific to the data type you are decrypting. This example encrypts an `int` and `double` value.
|
||||
|
||||
```cs
|
||||
Encryption encrypt = new Encryption("Password123", EncryptionAlgorithm.TripleDes);
|
||||
|
||||
int originalInt = 55;
|
||||
double originalDouble = 123.45;
|
||||
string cipherInt = encrypt.Encrypt(originalInt);
|
||||
string cipherDouble = encrypt.Encrypt(originalDouble);
|
||||
int resultInt = encrypt.DecryptInt32(cipherInt);
|
||||
double resultDouble = encrypt.DecryptDouble(cipherDouble);
|
||||
|
||||
Debug.Assert(resultInt == originalInt);
|
||||
Debug.Assert(resultDouble == originalDouble);
|
||||
```
|
||||
|
||||
## Streams
|
||||
|
||||
`EasyEncryption` also provides the streaming classes `EncryptionWriter` and `EncryptionReader`. These classes work well when encrypting to (or decrypting from) files.
|
||||
|
||||
The following example uses the `CreateStreamWriter()` to encrypt a number of integer values to a file.
|
||||
|
||||
```cs
|
||||
Encryption encrypt = new Encryption("Password123", EncryptionAlgorithm.TripleDes);
|
||||
int[] intValues = { 123, 88, 902, 27, 16, 4, 478, 54 };
|
||||
|
||||
using (EncryptionWriter writer = encrypt.CreateStreamWriter(path))
|
||||
{
|
||||
for (int i = 0; i < intValues.Length; i++)
|
||||
writer.Write(intValues[i]);
|
||||
}
|
||||
```
|
||||
|
||||
Use the `CreateStreamReader()` method to decrypt those integer values from the file.
|
||||
|
||||
```cs
|
||||
Encryption encrypt = new Encryption("Password123", EncryptionAlgorithm.TripleDes);
|
||||
int[] intValues = new int[8];
|
||||
|
||||
using (EncryptionReader reader = encrypt.CreateStreamReader(path))
|
||||
{
|
||||
for (int i = 0; i < intValues.Length; i++)
|
||||
intValues[i] = reader.ReadInt32();
|
||||
}
|
||||
```
|
||||
|
||||
Also, the `CreateStreamWriter()` and `CreateStreamReader()` methods are overloaded to accept a stream argument, allowing you to use custom streams. For example, you could use a `MemoryStream` to encrypt data to memory. This is demonstrated in the following example. It also uses the static method `EncodeBytesToString()` method to convert the results to a string. (Note that there is also a corresponding static `DecodeBytesFromString()` method.)
|
||||
|
||||
```cs
|
||||
Encryption encrypt = new Encryption("Password123", EncryptionAlgorithm.TripleDes);
|
||||
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
using (EncryptionWriter writer = encrypt.CreateStreamWriter(stream))
|
||||
{
|
||||
writer.Write("ABC");
|
||||
writer.Write(123);
|
||||
writer.Write(123.45);
|
||||
string s = Encryption.EncodeBytesToString(stream.ToArray());
|
||||
}
|
||||
```
|
||||
|
||||
Note that the streaming classes are actually the most efficient way to encrypt and decrypt data. In fact the `Encrypt()` and decryption methods create an instance of `EncryptionWriter` internally (using a `MemoryStream`), even when only encrypting or decrypting a single byte.
|
||||
|
||||
In addition, it should be pointed out that the encrypted results produced by these routines include embedded meta data, making the encrypted data slightly larger than it would otherwise be. However, when encrypting to a stream, this data would only be stored once regardless of the number of values added to the stream. The takeaway is that you can use the `Encrypt()` method for a simple encryption, but should use the streaming classes for anything more complex.
|
||||
Reference in New Issue
Block a user