// Copyright Keysight Technologies 2012-2019 // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, you can obtain one at http://mozilla.org/MPL/2.0/. using System; using System.Xml.Linq; using System.Security.Cryptography; using System.Text; using System.IO; namespace OpenTap.Plugins { internal static class CryptographyHelper { private static readonly int iterations = 3; private static readonly int nofKeyBytes = 32; // 256/8 private static readonly string hashMethod = "SHA1"; // 20B private static readonly byte[] iv = ASCIIEncoding.ASCII.GetBytes("dqg63928163gdg19"); // initialization vector private static readonly byte[] salt = ASCIIEncoding.ASCII.GetBytes("b37vrg37r83g8v36"); // salt as byte array internal static string Encrypt(string input, string password) { byte[] output; byte[] inputAsBytes = UTF8Encoding.UTF8.GetBytes(input); using (Aes aesAlgo = Aes.Create()) { byte[] keyBytes = new PasswordDeriveBytes(password, salt, hashMethod, iterations).GetBytes(nofKeyBytes); aesAlgo.Mode = CipherMode.ECB; using (MemoryStream memoryStreamDestination = new MemoryStream()) { using (ICryptoTransform encryptor = aesAlgo.CreateEncryptor(keyBytes, iv)) { using (CryptoStream writer = new CryptoStream(memoryStreamDestination, encryptor, CryptoStreamMode.Write)) { writer.Write(inputAsBytes, 0, inputAsBytes.Length); writer.FlushFinalBlock(); output = memoryStreamDestination.ToArray(); } } } aesAlgo.Clear(); } return Convert.ToBase64String(output); } internal static string Decrypt(string input, string password) { string result = String.Empty; int decryptedBytesCount = 0; byte[] output; byte[] inputAsBytes = Convert.FromBase64String(input); using (Aes aesAlgo = Aes.Create()) { byte[] keyBytes = new PasswordDeriveBytes(password, salt, hashMethod, iterations).GetBytes(nofKeyBytes); aesAlgo.Mode = CipherMode.ECB; try { using (MemoryStream inputStream = new MemoryStream(inputAsBytes)) { using (ICryptoTransform decryptor = aesAlgo.CreateDecryptor(keyBytes, iv)) { using (CryptoStream reader = new CryptoStream(inputStream, decryptor, CryptoStreamMode.Read)) { output = new byte[inputAsBytes.Length]; decryptedBytesCount = reader.Read(output, 0, output.Length); result = Encoding.UTF8.GetString(output, 0, decryptedBytesCount); } } } } catch (Exception) { // swallow exception } aesAlgo.Clear(); } return result; } } /// Serializer implementation for SecureStrings. internal class SecureStringSerializer : TapSerializerPlugin { private const string password = "P4ssw0rdF0rS3r1al1z1ngS3cur3Str1ngs"; /// Deserialization implementation for SecureString. /// /// /// /// public override bool Deserialize(XElement node, ITypeData targetType, Action setResult) { if (targetType.IsA(typeof(System.Security.SecureString)) == false) return false; string valueString = node.Value; var result = new System.Security.SecureString(); setResult(result); try { string encryptedString = CryptographyHelper.Decrypt(valueString, password); foreach (var c in encryptedString) result.AppendChar(c); return true; } catch { return true; } } /// /// Serialization implementation for SecureString. /// /// /// /// /// public override bool Serialize(XElement elem, object obj, ITypeData expectedType) { if (obj is System.Security.SecureString == false) return false; var sec = (System.Security.SecureString)obj; var unsec = sec.ConvertToUnsecureString(); elem.Value = CryptographyHelper.Encrypt(unsec, password); return true; } } }