From a635302e9ae4a8ced135620e355697ccf2a27b52 Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Mon, 4 Dec 2017 14:15:48 +0200 Subject: Added Tango.Serialization. Added Tango.Settings. --- .../Tango.Serialization/BinaryDataSerializer.cs | 77 ++++++++++ .../Tango.Serialization/CryptographyHelper.cs | 156 ++++++++++++++++++++ .../Tango.Serialization/IDataSerializer.cs | 47 ++++++ .../Tango.Serialization/JsonDataSerializer.cs | 87 +++++++++++ .../Tango.Serialization/Properties/AssemblyInfo.cs | 6 + .../Tango.Serialization/SerializationHelper.cs | 66 +++++++++ .../Tango.Serialization/Tango.Serialization.csproj | 64 ++++++++ .../Tango.Serialization/XmlDataSerializer.cs | 161 +++++++++++++++++++++ .../Tango.Serialization/packages.config | 5 + 9 files changed, 669 insertions(+) create mode 100644 Software/Visual_Studio/Tango.Serialization/BinaryDataSerializer.cs create mode 100644 Software/Visual_Studio/Tango.Serialization/CryptographyHelper.cs create mode 100644 Software/Visual_Studio/Tango.Serialization/IDataSerializer.cs create mode 100644 Software/Visual_Studio/Tango.Serialization/JsonDataSerializer.cs create mode 100644 Software/Visual_Studio/Tango.Serialization/Properties/AssemblyInfo.cs create mode 100644 Software/Visual_Studio/Tango.Serialization/SerializationHelper.cs create mode 100644 Software/Visual_Studio/Tango.Serialization/Tango.Serialization.csproj create mode 100644 Software/Visual_Studio/Tango.Serialization/XmlDataSerializer.cs create mode 100644 Software/Visual_Studio/Tango.Serialization/packages.config (limited to 'Software/Visual_Studio/Tango.Serialization') diff --git a/Software/Visual_Studio/Tango.Serialization/BinaryDataSerializer.cs b/Software/Visual_Studio/Tango.Serialization/BinaryDataSerializer.cs new file mode 100644 index 000000000..565854804 --- /dev/null +++ b/Software/Visual_Studio/Tango.Serialization/BinaryDataSerializer.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.Serialization.Formatters.Binary; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Serialization +{ + /// + /// Represents a data serializer for serializing data using binary formatter. + /// + public class BinaryDataSerializer : IDataSerializer + { + /// + /// Serialize object to a file. + /// + /// Type of specified object. + /// The specified object. + /// The full path to the file to write. + public void SerializeToFile(T obj, string filePath) + { + using (FileStream fs = new FileStream(filePath,FileMode.Create)) + { + SerializeToStream(obj, fs); + } + } + + /// + /// Deserialize object from a file. + /// + /// Type of object to deserialize. + /// The full path of the data file. + /// The resulting object. + public T DeserializeFromFile(string filePath) + { + using (FileStream fs = new FileStream(filePath, FileMode.Open)) + { + return DeserializeFromStream(fs); + } + } + + /// + /// Serialize object to stream. + /// + /// Type of specified object. + /// The specified object. + /// The stream to write. + public void SerializeToStream(T obj, Stream st) + { + BinaryFormatter f = new BinaryFormatter(); + f.Serialize(st, obj); + } + + /// + /// Deserialize object from stream. + /// + /// Type of object to deserialize. + /// Stream to read from. + /// The resulting object. + public T DeserializeFromStream(Stream st) + { + BinaryFormatter f = new BinaryFormatter(); + return (T)f.Deserialize(st); + } + + /// + /// Returns the serializer full name. + /// + /// + public override string ToString() + { + return SerializationHelper.GetSerializerName(this); + } + } +} diff --git a/Software/Visual_Studio/Tango.Serialization/CryptographyHelper.cs b/Software/Visual_Studio/Tango.Serialization/CryptographyHelper.cs new file mode 100644 index 000000000..e072827fe --- /dev/null +++ b/Software/Visual_Studio/Tango.Serialization/CryptographyHelper.cs @@ -0,0 +1,156 @@ +using System; +using System.Text; +using System.Security.Cryptography; +using System.IO; +using System.Linq; +using System.Security; +using System.Runtime.InteropServices; + +namespace Tango.Serialization +{ + /// + /// Represents a helper class for encryption and decryption of plain text. + /// + internal static class CryptographyHelper + { + private static SecureString passkey; + + /// + /// Initializes the class. + /// + static CryptographyHelper() + { + passkey = new SecureString(); + passkey.AppendChar('S'); + passkey.AppendChar('@'); + passkey.AppendChar('Y'); + passkey.AppendChar('!'); + } + + // This constant is used to determine the keysize of the encryption algorithm in bits. + // We divide this by 8 within the code below to get the equivalent number of bytes. + private const int Keysize = 256; + + // This constant determines the number of iterations for the password bytes generation function. + private const int DerivationIterations = 1000; + + /// + /// Encrypts the specified plain text. + /// + /// The plain text. + /// + public static string Encrypt(string plainText) + { + // Salt and IV is randomly generated each time, but is preprended to encrypted cipher text + // so that the same Salt and IV values can be used when decrypting. + var saltStringBytes = Generate256BitsOfRandomEntropy(); + var ivStringBytes = Generate256BitsOfRandomEntropy(); + var plainTextBytes = Encoding.UTF8.GetBytes(plainText); + using (var password = new Rfc2898DeriveBytes(ConvertSecureStringToString(passkey), saltStringBytes, DerivationIterations)) + { + var keyBytes = password.GetBytes(Keysize / 8); + using (var symmetricKey = new RijndaelManaged()) + { + symmetricKey.BlockSize = 256; + symmetricKey.Mode = CipherMode.CBC; + symmetricKey.Padding = PaddingMode.PKCS7; + using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes)) + { + using (var memoryStream = new MemoryStream()) + { + using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) + { + cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length); + cryptoStream.FlushFinalBlock(); + // Create the final bytes as a concatenation of the random salt bytes, the random iv bytes and the cipher bytes. + var cipherTextBytes = saltStringBytes; + cipherTextBytes = cipherTextBytes.Concat(ivStringBytes).ToArray(); + cipherTextBytes = cipherTextBytes.Concat(memoryStream.ToArray()).ToArray(); + memoryStream.Close(); + cryptoStream.Close(); + return Convert.ToBase64String(cipherTextBytes); + } + } + } + } + } + } + + /// + /// Decrypts the specified cipher text. + /// + /// The cipher text. + /// + public static string Decrypt(string cipherText) + { + // Get the complete stream of bytes that represent: + // [32 bytes of Salt] + [32 bytes of IV] + [n bytes of CipherText] + var cipherTextBytesWithSaltAndIv = Convert.FromBase64String(cipherText); + // Get the saltbytes by extracting the first 32 bytes from the supplied cipherText bytes. + var saltStringBytes = cipherTextBytesWithSaltAndIv.Take(Keysize / 8).ToArray(); + // Get the IV bytes by extracting the next 32 bytes from the supplied cipherText bytes. + var ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(Keysize / 8).Take(Keysize / 8).ToArray(); + // Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string. + var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((Keysize / 8) * 2).Take(cipherTextBytesWithSaltAndIv.Length - ((Keysize / 8) * 2)).ToArray(); + + using (var password = new Rfc2898DeriveBytes(ConvertSecureStringToString(passkey), saltStringBytes, DerivationIterations)) + { + var keyBytes = password.GetBytes(Keysize / 8); + using (var symmetricKey = new RijndaelManaged()) + { + symmetricKey.BlockSize = 256; + symmetricKey.Mode = CipherMode.CBC; + symmetricKey.Padding = PaddingMode.PKCS7; + using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes)) + { + using (var memoryStream = new MemoryStream(cipherTextBytes)) + { + using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)) + { + var plainTextBytes = new byte[cipherTextBytes.Length]; + var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length); + memoryStream.Close(); + cryptoStream.Close(); + return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount); + } + } + } + } + } + } + + /// + /// Generate256s the bits of random entropy. + /// + /// + private static byte[] Generate256BitsOfRandomEntropy() + { + var randomBytes = new byte[32]; // 32 Bytes will give us 256 bits. + using (var rngCsp = new RNGCryptoServiceProvider()) + { + // Fill the array with cryptographically secure random bytes. + rngCsp.GetBytes(randomBytes); + } + return randomBytes; + } + + /// + /// Converts the secure string to string. + /// + /// The value. + /// + private static String ConvertSecureStringToString(SecureString value) + { + IntPtr valuePtr = IntPtr.Zero; + try + { + valuePtr = Marshal.SecureStringToGlobalAllocUnicode(value); + return Marshal.PtrToStringUni(valuePtr); + } + finally + { + Marshal.ZeroFreeGlobalAllocUnicode(valuePtr); + } + } + } +} \ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Serialization/IDataSerializer.cs b/Software/Visual_Studio/Tango.Serialization/IDataSerializer.cs new file mode 100644 index 000000000..93465967e --- /dev/null +++ b/Software/Visual_Studio/Tango.Serialization/IDataSerializer.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Serialization +{ + /// + /// Represent an interface for creating a custom data serializer. + /// + public interface IDataSerializer + { + /// + /// Serialize object to a file. + /// + /// Type of specified object. + /// The specified object. + /// The full path to the file to write. + void SerializeToFile(T obj, String filePath); + + /// + /// Deserialize object from a file. + /// + /// Type of object to deserialize. + /// The full path of the data file. + /// The resulting object. + T DeserializeFromFile(String filePath); + + /// + /// Serialize object to stream. + /// + /// Type of specified object. + /// The specified object. + /// The stream to write. + void SerializeToStream(T obj, Stream st); + + /// + /// Deserialize object from stream. + /// + /// Type of object to deserialize. + /// Stream to read from. + /// The resulting object. + T DeserializeFromStream(Stream st); + } +} diff --git a/Software/Visual_Studio/Tango.Serialization/JsonDataSerializer.cs b/Software/Visual_Studio/Tango.Serialization/JsonDataSerializer.cs new file mode 100644 index 000000000..674f68289 --- /dev/null +++ b/Software/Visual_Studio/Tango.Serialization/JsonDataSerializer.cs @@ -0,0 +1,87 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Serialization +{ + /// + /// Represents a data serializer for serializing data using the light weight textual Json format. + /// + public class JsonDataSerializer : IDataSerializer + { + + /// + /// Serialize object to a file. + /// + /// Type of specified object. + /// The specified object. + /// The full path to the file to write. + public void SerializeToFile(T obj, string filePath) + { + using (FileStream fs = new FileStream(filePath, FileMode.Create)) + { + SerializeToStream(obj, fs); + } + } + + /// + /// Deserialize object from a file. + /// + /// Type of object to deserialize. + /// The full path of the data file. + /// The resulting object. + public T DeserializeFromFile(string filePath) + { + using (FileStream fs = new FileStream(filePath, FileMode.Open)) + { + return DeserializeFromStream(fs); + } + } + + /// + /// Serialize object to stream. + /// + /// Type of specified object. + /// The specified object. + /// The stream to write. + public void SerializeToStream(T obj, Stream st) + { + JsonSerializer serializer = new JsonSerializer(); + using (StreamWriter streamReader = new StreamWriter(st)) + { + serializer.Serialize(streamReader, obj); + } + } + + /// + /// Deserialize object from stream. + /// + /// Type of object to deserialize. + /// Stream to read from. + /// The resulting object. + public T DeserializeFromStream(Stream st) + { + JsonSerializer serializer = new JsonSerializer(); + T data; + using (StreamReader streamReader = new StreamReader(st)) + { + data = (T)serializer.Deserialize(streamReader, typeof(T)); + } + return data; + } + + /// + /// Returns the serializer full name. + /// + /// + public override string ToString() + { + return SerializationHelper.GetSerializerName(this); + } + + } +} diff --git a/Software/Visual_Studio/Tango.Serialization/Properties/AssemblyInfo.cs b/Software/Visual_Studio/Tango.Serialization/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..f3c038f0e --- /dev/null +++ b/Software/Visual_Studio/Tango.Serialization/Properties/AssemblyInfo.cs @@ -0,0 +1,6 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Tango - Serialization Components")] +[assembly: ComVisible(false)] \ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Serialization/SerializationHelper.cs b/Software/Visual_Studio/Tango.Serialization/SerializationHelper.cs new file mode 100644 index 000000000..2d00c8621 --- /dev/null +++ b/Software/Visual_Studio/Tango.Serialization/SerializationHelper.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Serialization +{ + /// + /// Contains a collection of IDataSerializer related helper methods. + /// + public static class SerializationHelper + { + /// + /// Gets a list of all IDataSerializer implemented types. + /// + /// + public static List GetSerializersTypes() + { + var type = typeof(IDataSerializer); + var serializers = System.Reflection.Assembly.GetAssembly(type).GetTypes().Where(x => type.IsAssignableFrom(x) && !x.IsInterface); + return serializers.ToList(); + } + + /// + /// Gets a list of all IDataSerializer implemented instances. + /// + /// + public static List GetSerializersInstances() + { + var types = GetSerializersTypes(); + + List serializers = new List(); + + foreach (var type in types) + { + var instance = Activator.CreateInstance(type) as IDataSerializer; + serializers.Add(instance); + } + + return serializers; + } + + /// + /// Returns a serializer instance by type name. + /// + /// Name of IDataSerializer type. + /// + public static IDataSerializer GetSerializerByName(String name) + { + var types = GetSerializersTypes(); + var type = types.SingleOrDefault(x => x.Name == name); + return Activator.CreateInstance(type) as IDataSerializer; + } + + /// + /// Returns the name of the specified IDataSerializer. + /// + /// The specified IDataSerializer. + /// + public static String GetSerializerName(IDataSerializer serializer) + { + return serializer.GetType().Name; + } + } +} diff --git a/Software/Visual_Studio/Tango.Serialization/Tango.Serialization.csproj b/Software/Visual_Studio/Tango.Serialization/Tango.Serialization.csproj new file mode 100644 index 000000000..453d317f5 --- /dev/null +++ b/Software/Visual_Studio/Tango.Serialization/Tango.Serialization.csproj @@ -0,0 +1,64 @@ + + + + + Debug + AnyCPU + {22F87980-E990-4686-BE81-BE63D562C4D5} + Library + Properties + Tango.Serialization + Tango.Serialization + v4.6 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Google.Protobuf.3.5.0\lib\net45\Google.Protobuf.dll + + + ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll + + + + + + + + + + + + + GlobalVersionInfo.cs + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Serialization/XmlDataSerializer.cs b/Software/Visual_Studio/Tango.Serialization/XmlDataSerializer.cs new file mode 100644 index 000000000..0453e9120 --- /dev/null +++ b/Software/Visual_Studio/Tango.Serialization/XmlDataSerializer.cs @@ -0,0 +1,161 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Serialization; + +namespace Tango.Serialization +{ + /// + /// Represents a data serializer for serializing data using standard xml serializer. + /// + public class XmlDataSerializer : IDataSerializer + { + + /// + /// Serialize object to a file. + /// + /// Type of specified object. + /// The specified object. + /// The full path to the file to write. + public void SerializeToFile(T obj, string filePath) + { + using (FileStream fs = new FileStream(filePath, FileMode.Create)) + { + SerializeToStream(obj, fs); + } + } + + /// + /// Serialize object to encrypted file. + /// + /// Type of specified object. + /// The specified object. + /// The full path to the file to write. + public void SerializeToEncryptedFile(T obj, string filePath) + { + var plainText = SerializeToString(obj); + var cypherText = CryptographyHelper.Encrypt(plainText); + File.WriteAllText(filePath, cypherText); + } + + /// + /// Serialize object to encrypted string. + /// + /// Type of specified object. + /// The specified object. + public String SerializeToEncryptedString(T obj) + { + var plainText = SerializeToString(obj); + var cypherText = CryptographyHelper.Encrypt(plainText); + return cypherText; + } + + /// + /// Deserialize object from encrypted file. + /// + /// Type of object to deserialize. + /// The full path of the data file. + /// The resulting object. + public T DeserializeFromEncryptedFile(string filePath) + { + var cypherText = File.ReadAllText(filePath); + var plainText = CryptographyHelper.Decrypt(cypherText); + return DeserializeFromString(plainText); + } + + /// + /// Deserialize object from encrypted string. + /// + /// Type of object to deserialize. + /// The resulting object. + public T DeserializeFromEncryptedString(string encyptedString) + { + var plainText = CryptographyHelper.Decrypt(encyptedString); + return DeserializeFromString(plainText); + } + + /// + /// Deserialize object from a file. + /// + /// Type of object to deserialize. + /// The full path of the data file. + /// The resulting object. + public T DeserializeFromFile(string filePath) + { + using (FileStream fs = new FileStream(filePath, FileMode.Open)) + { + return DeserializeFromStream(fs); + } + } + + + /// + /// Serialize object to stream. + /// + /// Type of specified object. + /// The specified object. + /// The stream to write. + public void SerializeToStream(T obj, Stream st) + { + XmlSerializer f = XmlSerializer.FromTypes(new[] { typeof(T) })[0]; //Microsoft bug workaround. + f.Serialize(st, obj); + } + + /// + /// Serialize object to string. + /// + /// Type of specified object. + /// The specified object. + /// + public String SerializeToString(T obj) + { + XmlSerializer f = XmlSerializer.FromTypes(new[] { typeof(T) })[0]; //Microsoft bug workaround. + + using (StringWriter textWriter = new StringWriter()) + { + f.Serialize(textWriter, obj); + return textWriter.ToString(); + } + } + + /// + /// Deserialize object from stream. + /// + /// Type of object to deserialize. + /// Stream to read from. + /// The resulting object. + public T DeserializeFromStream(Stream st) + { + XmlSerializer f = XmlSerializer.FromTypes(new[] { typeof(T) })[0]; //Microsoft bug workaround. + return (T)f.Deserialize(st); + } + + /// + /// Deserialize object from string. + /// + /// Type of specified object. + /// The specified object. + /// + public T DeserializeFromString(String str) + { + XmlSerializer f = XmlSerializer.FromTypes(new[] { typeof(T) })[0]; //Microsoft bug workaround. + using (TextReader reader = new StringReader(str)) + { + return (T)f.Deserialize(reader); + } + } + + /// + /// Returns the serializer full name. + /// + /// + public override string ToString() + { + return SerializationHelper.GetSerializerName(this); + } + + } +} diff --git a/Software/Visual_Studio/Tango.Serialization/packages.config b/Software/Visual_Studio/Tango.Serialization/packages.config new file mode 100644 index 000000000..dbb73d29f --- /dev/null +++ b/Software/Visual_Studio/Tango.Serialization/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file -- cgit v1.3.1