From a0095a0516508418fb4a058648f49f867f64592e Mon Sep 17 00:00:00 2001 From: maier_S Date: Wed, 23 Mar 2022 10:15:26 +0100 Subject: [PATCH] Squashed 'FSI.Lib/' content from commit 6aa4846 git-subtree-dir: FSI.Lib git-subtree-split: 6aa48465a834a7bfdd9cbeae8d2e4f769d0c0ff8 --- .gitignore | 390 +++++ FSI.Lib.sln | 25 + FSI.Lib/DeEncryptString/DeEncrypt.cs | 78 + FSI.Lib/EasyEncryption/Encryption.cs | 704 +++++++++ FSI.Lib/EasyEncryption/EncryptionReader.cs | 105 ++ FSI.Lib/EasyEncryption/EncryptionWriter.cs | 105 ++ FSI.Lib/EasyEncryption/Readme.md | 90 ++ FSI.Lib/FSI.Lib.csproj | 34 + FSI.Lib/Guis/AutoPw/FrmMain.xaml | 54 + FSI.Lib/Guis/AutoPw/FrmMain.xaml.cs | 79 + FSI.Lib/Guis/DeEncryptMessage/FrmMain.xaml | 55 + FSI.Lib/Guis/DeEncryptMessage/FrmMain.xaml.cs | 61 + FSI.Lib/Guis/Pdf.Mgt/Cmds.cs | 116 ++ FSI.Lib/Guis/Pdf.Mgt/FrmMain.xaml | 68 + FSI.Lib/Guis/Pdf.Mgt/FrmMain.xaml.cs | 71 + FSI.Lib/Guis/Prj.Mgt/FrmMain.xaml | 185 +++ FSI.Lib/Guis/Prj.Mgt/FrmMain.xaml.cs | 64 + FSI.Lib/Guis/Prj.Mgt/Model/Prj.cs | 25 + .../Guis/Prj.Mgt/ViewModel/ViewModelPrj.cs | 208 +++ .../Convert_SINAMICS_trace_CSV.exe | Bin 0 -> 3817904 bytes .../Guis/SieStarterCsvExporter/FrmMain.xaml | 54 + .../SieStarterCsvExporter/FrmMain.xaml.cs | 111 ++ FSI.Lib/Guis/SieTiaWinCCMsgMgt/FrmMain.xaml | 59 + .../Guis/SieTiaWinCCMsgMgt/FrmMain.xaml.cs | 57 + FSI.Lib/Guis/SieTiaWinCCMsgMgt/WinCC.cs | 172 +++ FSI.Lib/Helpers/IdentityHelpers.cs | 16 + FSI.Lib/Icons/Cross.png | Bin 0 -> 23205 bytes FSI.Lib/Icons/FondiumU.ico | Bin 0 -> 5534 bytes FSI.Lib/Icons/Open.png | Bin 0 -> 11322 bytes FSI.Lib/LnkParser/ShortCut.cs | 57 + FSI.Lib/MVVM/DelegateCommand.cs | 43 + FSI.Lib/MVVM/RelayCommand.cs | 77 + .../MVVM/ViewModel/CurrentTimeViewModel.cs | 40 + FSI.Lib/MVVM/ViewModelBase.cs | 61 + FSI.Lib/TimeStamp.cs | 16 + FSI.Lib/WinSettings/ArrayToString.cs | 90 ++ .../WinSettings/EncryptedSettingAttribute.cs | 13 + .../WinSettings/ExcludedSettingAttribute.cs | 13 + FSI.Lib/WinSettings/IniFile.cs | 421 ++++++ FSI.Lib/WinSettings/IniSettings.cs | 142 ++ FSI.Lib/WinSettings/Readme.md | 180 +++ FSI.Lib/WinSettings/RegistrySettings.cs | 154 ++ FSI.Lib/WinSettings/Setting.cs | 117 ++ FSI.Lib/WinSettings/Settings.cs | 106 ++ FSI.Lib/WinSettings/XmlSettings.cs | 155 ++ FSI.Lib/Wpf/Converter/BooleanConverter.cs | 27 + .../Converters/InvertedBoolenConverter .cs | 22 + FSI.Lib/Wpf/Ctrls/ChbWindowsTopMost.xaml | 16 + FSI.Lib/Wpf/Ctrls/ChbWindowsTopMost.xaml.cs | 89 ++ .../Ctrls/FilterDataGrid/DataGridColumn.cs | 78 + .../Wpf/Ctrls/FilterDataGrid/FilterCommon.cs | 319 ++++ .../Ctrls/FilterDataGrid/FilterDataGrid.cs | 1309 +++++++++++++++++ .../FilterDataGridDictionary.cs | 20 + .../Wpf/Ctrls/FilterDataGrid/FilterHelpers.cs | 396 +++++ .../Wpf/Ctrls/FilterDataGrid/FilterItem.cs | 147 ++ FSI.Lib/Wpf/Ctrls/FilterDataGrid/Loc.cs | 235 +++ FSI.Lib/Wpf/Ctrls/FilterDataGrid/Readme.md | 1 + .../FilterDataGrid/StringFormatConverter.cs | 36 + .../FilterDataGrid/Themes/FilterDataGrid.xaml | 880 +++++++++++ .../Ctrls/FilterDataGrid/Themes/Generic.xaml | 18 + FSI.Lib/Wpf/WindowExtensions.cs | 138 ++ README.md | 3 + 62 files changed, 8405 insertions(+) create mode 100644 .gitignore create mode 100644 FSI.Lib.sln create mode 100644 FSI.Lib/DeEncryptString/DeEncrypt.cs create mode 100644 FSI.Lib/EasyEncryption/Encryption.cs create mode 100644 FSI.Lib/EasyEncryption/EncryptionReader.cs create mode 100644 FSI.Lib/EasyEncryption/EncryptionWriter.cs create mode 100644 FSI.Lib/EasyEncryption/Readme.md create mode 100644 FSI.Lib/FSI.Lib.csproj create mode 100644 FSI.Lib/Guis/AutoPw/FrmMain.xaml create mode 100644 FSI.Lib/Guis/AutoPw/FrmMain.xaml.cs create mode 100644 FSI.Lib/Guis/DeEncryptMessage/FrmMain.xaml create mode 100644 FSI.Lib/Guis/DeEncryptMessage/FrmMain.xaml.cs create mode 100644 FSI.Lib/Guis/Pdf.Mgt/Cmds.cs create mode 100644 FSI.Lib/Guis/Pdf.Mgt/FrmMain.xaml create mode 100644 FSI.Lib/Guis/Pdf.Mgt/FrmMain.xaml.cs create mode 100644 FSI.Lib/Guis/Prj.Mgt/FrmMain.xaml create mode 100644 FSI.Lib/Guis/Prj.Mgt/FrmMain.xaml.cs create mode 100644 FSI.Lib/Guis/Prj.Mgt/Model/Prj.cs create mode 100644 FSI.Lib/Guis/Prj.Mgt/ViewModel/ViewModelPrj.cs create mode 100644 FSI.Lib/Guis/SieStarterCsvExporter/Convert_SINAMICS_trace_CSV.exe create mode 100644 FSI.Lib/Guis/SieStarterCsvExporter/FrmMain.xaml create mode 100644 FSI.Lib/Guis/SieStarterCsvExporter/FrmMain.xaml.cs create mode 100644 FSI.Lib/Guis/SieTiaWinCCMsgMgt/FrmMain.xaml create mode 100644 FSI.Lib/Guis/SieTiaWinCCMsgMgt/FrmMain.xaml.cs create mode 100644 FSI.Lib/Guis/SieTiaWinCCMsgMgt/WinCC.cs create mode 100644 FSI.Lib/Helpers/IdentityHelpers.cs create mode 100644 FSI.Lib/Icons/Cross.png create mode 100644 FSI.Lib/Icons/FondiumU.ico create mode 100644 FSI.Lib/Icons/Open.png create mode 100644 FSI.Lib/LnkParser/ShortCut.cs create mode 100644 FSI.Lib/MVVM/DelegateCommand.cs create mode 100644 FSI.Lib/MVVM/RelayCommand.cs create mode 100644 FSI.Lib/MVVM/ViewModel/CurrentTimeViewModel.cs create mode 100644 FSI.Lib/MVVM/ViewModelBase.cs create mode 100644 FSI.Lib/TimeStamp.cs create mode 100644 FSI.Lib/WinSettings/ArrayToString.cs create mode 100644 FSI.Lib/WinSettings/EncryptedSettingAttribute.cs create mode 100644 FSI.Lib/WinSettings/ExcludedSettingAttribute.cs create mode 100644 FSI.Lib/WinSettings/IniFile.cs create mode 100644 FSI.Lib/WinSettings/IniSettings.cs create mode 100644 FSI.Lib/WinSettings/Readme.md create mode 100644 FSI.Lib/WinSettings/RegistrySettings.cs create mode 100644 FSI.Lib/WinSettings/Setting.cs create mode 100644 FSI.Lib/WinSettings/Settings.cs create mode 100644 FSI.Lib/WinSettings/XmlSettings.cs create mode 100644 FSI.Lib/Wpf/Converter/BooleanConverter.cs create mode 100644 FSI.Lib/Wpf/Converters/InvertedBoolenConverter .cs create mode 100644 FSI.Lib/Wpf/Ctrls/ChbWindowsTopMost.xaml create mode 100644 FSI.Lib/Wpf/Ctrls/ChbWindowsTopMost.xaml.cs create mode 100644 FSI.Lib/Wpf/Ctrls/FilterDataGrid/DataGridColumn.cs create mode 100644 FSI.Lib/Wpf/Ctrls/FilterDataGrid/FilterCommon.cs create mode 100644 FSI.Lib/Wpf/Ctrls/FilterDataGrid/FilterDataGrid.cs create mode 100644 FSI.Lib/Wpf/Ctrls/FilterDataGrid/FilterDataGridDictionary.cs create mode 100644 FSI.Lib/Wpf/Ctrls/FilterDataGrid/FilterHelpers.cs create mode 100644 FSI.Lib/Wpf/Ctrls/FilterDataGrid/FilterItem.cs create mode 100644 FSI.Lib/Wpf/Ctrls/FilterDataGrid/Loc.cs create mode 100644 FSI.Lib/Wpf/Ctrls/FilterDataGrid/Readme.md create mode 100644 FSI.Lib/Wpf/Ctrls/FilterDataGrid/StringFormatConverter.cs create mode 100644 FSI.Lib/Wpf/Ctrls/FilterDataGrid/Themes/FilterDataGrid.xaml create mode 100644 FSI.Lib/Wpf/Ctrls/FilterDataGrid/Themes/Generic.xaml create mode 100644 FSI.Lib/Wpf/WindowExtensions.cs create mode 100644 README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..61c5d57 --- /dev/null +++ b/.gitignore @@ -0,0 +1,390 @@ +# ---> VisualStudio +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Nuget personal access tokens and Credentials +nuget.config + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +.idea/ +*.sln.iml + diff --git a/FSI.Lib.sln b/FSI.Lib.sln new file mode 100644 index 0000000..602fb0e --- /dev/null +++ b/FSI.Lib.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31321.278 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FSI.Lib", "FSI.Lib\FSI.Lib.csproj", "{1394B606-4AAC-4D8D-BAF4-DB38E1FCEAAA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1394B606-4AAC-4D8D-BAF4-DB38E1FCEAAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1394B606-4AAC-4D8D-BAF4-DB38E1FCEAAA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1394B606-4AAC-4D8D-BAF4-DB38E1FCEAAA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1394B606-4AAC-4D8D-BAF4-DB38E1FCEAAA}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0198E104-F95E-49D7-8FA5-9366011FAA9A} + EndGlobalSection +EndGlobal diff --git a/FSI.Lib/DeEncryptString/DeEncrypt.cs b/FSI.Lib/DeEncryptString/DeEncrypt.cs new file mode 100644 index 0000000..d8e490b --- /dev/null +++ b/FSI.Lib/DeEncryptString/DeEncrypt.cs @@ -0,0 +1,78 @@ +using System; +using System.IO; +using System.Security.Cryptography; + +namespace FSI.Lib.DeEncryptString +{ + public static class DeEncrypt + { + /// + /// Encrypts the string. + /// + /// The clear text. + /// The key. + /// The IV. + /// + private static byte[] CryptString(byte[] clearText, byte[] Key, byte[] IV) + { + MemoryStream ms = new MemoryStream(); + Rijndael alg = Rijndael.Create(); + alg.Key = Key; + alg.IV = IV; + CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write); + cs.Write(clearText, 0, clearText.Length); + cs.Close(); + byte[] encryptedData = ms.ToArray(); + return encryptedData; + } + + /// + /// Encrypts the string. + /// + /// The clear text. + /// The password. + /// + public static string CryptString(string clearText, string Password) + { + byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(clearText); + PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }); + byte[] encryptedData = CryptString(clearBytes, pdb.GetBytes(32), pdb.GetBytes(16)); + return Convert.ToBase64String(encryptedData); + } + + /// + /// Decrypts the string. + /// + /// The cipher data. + /// The key. + /// The IV. + /// + private static byte[] DecryptString(byte[] cipherData, byte[] Key, byte[] IV) + { + MemoryStream ms = new MemoryStream(); + var alg = Rijndael.Create(); + alg.Key = Key; + alg.IV = IV; + CryptoStream cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write); + cs.Write(cipherData, 0, cipherData.Length); + cs.Close(); + byte[] decryptedData = ms.ToArray(); + return decryptedData; + } + + /// + /// Decrypts the string. + /// + /// The cipher text. + /// The password. + /// + public static string DecryptString(string cipherText, string Password) + { + byte[] cipherBytes = Convert.FromBase64String(cipherText); + PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }); + byte[] decryptedData = DecryptString(cipherBytes, pdb.GetBytes(32), pdb.GetBytes(16)); + return System.Text.Encoding.Unicode.GetString(decryptedData); + } + + } +} diff --git a/FSI.Lib/EasyEncryption/Encryption.cs b/FSI.Lib/EasyEncryption/Encryption.cs new file mode 100644 index 0000000..a3135ec --- /dev/null +++ b/FSI.Lib/EasyEncryption/Encryption.cs @@ -0,0 +1,704 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Security.Cryptography; + +namespace FSI.Lib.EasyEncryption +{ + /// + /// Encryption algorithm types. + /// + public enum EncryptionAlgorithm + { + /// + /// Specifies the Advanced Encryption Standard (AES) symmetric encryption algorithm. + /// + Aes, + + /// + /// Specifies the Data Encryption Standard (DES) symmetric encryption algorithm. + /// + Des, + + /// + /// Specifies the RC2 symmetric encryption algorithm. + /// + Rc2, + + /// + /// Specifies the Rijndael symmetric encryption algorithm. + /// + Rijndael, + + /// + /// Specifies the TripleDES symmetric encryption algorithm. + /// + TripleDes + } + + /// + /// Class to provide encryption and decryption services. + /// + /// + /// + /// The Encryption class performs encryption and decryption using the specified algorithm. + /// + /// + /// 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 or + /// methods to work with the streaming classes + /// instead. + /// + /// + public class Encryption + { + private static readonly int SaltLength = 8; + + private static readonly Dictionary AlgorithmLookup = new Dictionary + { + [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; } + + /// + /// Converts a byte array to a string. + /// + /// The byte array to be converted. + /// Returns the converted string. + public static string EncodeBytesToString(byte[] bytes) => Convert.ToBase64String(bytes); + + /// + /// Converts a string to a byte array. + /// + /// The string to be converted. + /// Returns the converted byte array. + public static byte[] DecodeBytesFromString(string s) => Convert.FromBase64String(s); + + /// + /// Constructs a new Encryption instance. + /// + /// Specifies the encryption password. Leading and trailing spaces are removed. + /// Specifies which encryption algorithm is used. + 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 + + /// + /// Creates an instance using the specified stream. + /// + /// + /// The 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. + /// + /// The stream the encrypted data will be written to. + /// An instance of the class. + 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); + } + + /// + /// Creates an instance using the specified file name. + /// + /// + /// The 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. + /// + /// The file name the encrypted data will be written to. + /// An instance of the class. + public EncryptionWriter CreateStreamWriter(string path) + { + return CreateStreamWriter(File.Open(path, FileMode.OpenOrCreate, FileAccess.Write)); + } + + /// + /// Creates an instance using the specified stream. + /// + /// + /// The 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. + /// + /// The stream the encrypted data will be read from. + /// An instance of the class. + 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); + } + + /// + /// Creates an instance using the specified file name. + /// + /// + /// The 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. + /// + /// The file name the encrypted data will be read from. + /// An instance of the class. + public EncryptionReader CreateStreamReader(string path) + { + return CreateStreamReader(File.Open(path, FileMode.Open, FileAccess.Read)); + } + + #endregion + + #region Encryption + + /// + /// Encrypts a string value. + /// + /// + /// 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 + /// to create a instead. + /// + /// The value to decrypt. + /// Returns the encrypted value + public string Encrypt(string value) => Encrypt(w => w.Write(value ?? string.Empty)); + + /// + /// Encrypts a bool value. + /// + /// + /// 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 + /// to create a instead. + /// + /// The value to decrypt. + /// Returns the encrypted value + public string Encrypt(bool value) => Encrypt(w => w.Write(value)); + + /// + /// Encrypts a char value. + /// + /// + /// 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 + /// to create a instead. + /// + /// The value to decrypt. + /// Returns the encrypted value + public string Encrypt(char value) => Encrypt(w => w.Write(value)); + + /// + /// Encrypts a sbyte value. + /// + /// + /// 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 + /// to create a instead. + /// + /// The value to decrypt. + /// Returns the encrypted value + public string Encrypt(sbyte value) => Encrypt(w => w.Write(value)); + + /// + /// Encrypts a byte value. + /// + /// + /// 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 + /// to create a instead. + /// + /// The value to decrypt. + /// Returns the encrypted value + public string Encrypt(byte value) => Encrypt(w => w.Write(value)); + + /// + /// Encrypts a short value. + /// + /// + /// 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 + /// to create a instead. + /// + /// The value to decrypt. + /// Returns the encrypted value + public string Encrypt(short value) => Encrypt(w => w.Write(value)); + + /// + /// Encrypts a ushort value. + /// + /// + /// 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 + /// to create a instead. + /// + /// The value to decrypt. + /// Returns the encrypted value + public string Encrypt(ushort value) => Encrypt(w => w.Write(value)); + + /// + /// Encrypts a int value. + /// + /// + /// 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 + /// to create a instead. + /// + /// The value to decrypt. + /// Returns the encrypted value + public string Encrypt(int value) => Encrypt(w => w.Write(value)); + + /// + /// Encrypts a uint value. + /// + /// + /// 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 + /// to create a instead. + /// + /// The value to decrypt. + /// Returns the encrypted value + public string Encrypt(uint value) => Encrypt(w => w.Write(value)); + + /// + /// Encrypts a long value. + /// + /// + /// 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 + /// to create a instead. + /// + /// The value to decrypt. + /// Returns the encrypted value + public string Encrypt(long value) => Encrypt(w => w.Write(value)); + + /// + /// Encrypts a ulong value. + /// + /// + /// 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 + /// to create a instead. + /// + /// The value to decrypt. + /// Returns the encrypted value + public string Encrypt(ulong value) => Encrypt(w => w.Write(value)); + + /// + /// Encrypts a float value. + /// + /// + /// 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 + /// to create a instead. + /// + /// The value to decrypt. + /// Returns the encrypted value + public string Encrypt(float value) => Encrypt(w => w.Write(value)); + + /// + /// Encrypts a double value. + /// + /// + /// 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 + /// to create a instead. + /// + /// The value to decrypt. + /// Returns the encrypted value + public string Encrypt(double value) => Encrypt(w => w.Write(value)); + + /// + /// Encrypts a decimal value. + /// + /// + /// 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 + /// to create a instead. + /// + /// The value to decrypt. + /// Returns the encrypted value + public string Encrypt(decimal value) => Encrypt(w => w.Write(value)); + + /// + /// Encrypts a DateTime value. + /// + /// + /// 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 + /// to create a instead. + /// + /// The value to decrypt. + /// Returns the encrypted value + public string Encrypt(DateTime value) => Encrypt(w => w.Write(value)); + + /// + /// Encrypts a byte[] value. + /// + /// + /// 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 + /// to create a instead. + /// + /// The value to decrypt. + /// Returns the encrypted value + public string Encrypt(byte[] value) => Encrypt(w => w.Write(value)); + + /// + /// Encrypts a string[] value. + /// + /// + /// 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 + /// to create a instead. + /// + /// The value to decrypt. + /// Returns the encrypted value + public string Encrypt(string[] value) => Encrypt(w => w.Write(value)); + + private string Encrypt(Action action) + { + using (MemoryStream stream = new MemoryStream()) + using (EncryptionWriter writer = CreateStreamWriter(stream)) + { + action(writer); + return EncodeBytesToString(stream.ToArray()); + } + } + + #endregion + + #region Decryption + + /// + /// Decrypts a string value encrypted with . + /// + /// The value to decrypt. + /// Returns the decrypted value + public string DecryptString(string encryptedValue) => (string)Decrypt(encryptedValue, r => r.ReadString()); + + /// + /// Decrypts a bool value encrypted with . + /// + /// The value to decrypt. + /// Returns the decrypted value + public bool DecryptBoolean(string encryptedValue) => (bool)Decrypt(encryptedValue, r => r.ReadBoolean()); + + /// + /// Decrypts a char value encrypted with . + /// + /// The value to decrypt. + /// Returns the decrypted value + public char DecryptChar(string encryptedValue) => (char)Decrypt(encryptedValue, r => r.ReadChar()); + + /// + /// Decrypts a sbyte value encrypted with . + /// + /// The value to decrypt. + /// Returns the decrypted value + public sbyte DecryptSByte(string encryptedValue) => (sbyte)Decrypt(encryptedValue, r => r.ReadSByte()); + + /// + /// Decrypts a byte value encrypted with . + /// + /// The value to decrypt. + /// Returns the decrypted value + public byte DecryptByte(string encryptedValue) => (byte)Decrypt(encryptedValue, r => r.ReadByte()); + + /// + /// Decrypts a short value encrypted with . + /// + /// The value to decrypt. + /// Returns the decrypted value + public short DecryptInt16(string encryptedValue) => (short)Decrypt(encryptedValue, r => r.ReadInt16()); + + /// + /// Decrypts a ushort value encrypted with . + /// + /// The value to decrypt. + /// Returns the decrypted value + public ushort DecryptUInt16(string encryptedValue) => (ushort)Decrypt(encryptedValue, r => r.ReadUInt16()); + + /// + /// Decrypts a int value encrypted with . + /// + /// The value to decrypt. + /// Returns the decrypted value + public int DecryptInt32(string encryptedValue) => (int)Decrypt(encryptedValue, r => r.ReadInt32()); + + /// + /// Decrypts a uint value encrypted with . + /// + /// The value to decrypt. + /// Returns the decrypted value + public uint DecryptUInt32(string encryptedValue) => (uint)Decrypt(encryptedValue, r => r.ReadUInt32()); + + /// + /// Decrypts a long value encrypted with . + /// + /// The value to decrypt. + /// Returns the decrypted value + public long DecryptInt64(string encryptedValue) => (long)Decrypt(encryptedValue, r => r.ReadInt64()); + + /// + /// Decrypts a ulong value encrypted with . + /// + /// The value to decrypt. + /// Returns the decrypted value + public ulong DecryptUInt64(string encryptedValue) => (ulong)Decrypt(encryptedValue, r => r.ReadUInt64()); + + /// + /// Decrypts a float value encrypted with . + /// + /// The value to decrypt. + /// Returns the decrypted value + public float DecryptSingle(string encryptedValue) => (float)Decrypt(encryptedValue, r => r.ReadSingle()); + + /// + /// Decrypts a double value encrypted with . + /// + /// The value to decrypt. + /// Returns the decrypted value + public double DecryptDouble(string encryptedValue) => (double)Decrypt(encryptedValue, r => r.ReadDouble()); + + /// + /// Decrypts a decimal value encrypted with . + /// + /// The value to decrypt. + /// Returns the decrypted value + public decimal DecryptDecimal(string encryptedValue) => (decimal)Decrypt(encryptedValue, r => r.ReadDecimal()); + + /// + /// Decrypts a DateTime value encrypted with . + /// + /// The value to decrypt. + /// Returns the decrypted value + public DateTime DecryptDateTime(string encryptedValue) => (DateTime)Decrypt(encryptedValue, r => r.ReadDateTime()); + + /// + /// Decrypts a byte[] value encrypted with . + /// + /// The value to decrypt. + /// Returns the decrypted value + public byte[] DecryptByteArray(string encryptedValue) => (byte[])Decrypt(encryptedValue, r => r.ReadByteArray()); + + /// + /// Decrypts a string[] value encrypted with . + /// + /// The value to decrypt. + /// Returns the decrypted value + public string[] DecryptStringArray(string encryptedValue) => (string[])Decrypt(encryptedValue, r => r.ReadStringArray()); + + private object Decrypt(string encryptedValue, Func action) + { + using (MemoryStream stream = new MemoryStream(DecodeBytesFromString(encryptedValue))) + using (EncryptionReader reader = CreateStreamReader(stream)) + { + return action(reader); + } + } + + #endregion + + #region Encryption/decryption of objects + + /// + /// Class to hold encrypt/decrypt functions for each supported data type. + /// + private class TypeInfo + { + public Func Encrypt { get; set; } + public Func Decrypt { get; set; } + + public TypeInfo(Func encrypt, Func decrypt) + { + Encrypt = encrypt; + Decrypt = decrypt; + } + } + + private static readonly Dictionary TypeInfoLookup = new Dictionary() + { + [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)), + }; + + /// + /// Indicates if the specified data type is supported by the encryption and decryption methods. + /// + /// + /// The encryption code supports all basic .NET data types in addition to byte[] + /// and string[]. More complex data types are not supported. + /// + /// The data type to be tested. + /// True if the specified type is supported. False otherwise. + public static bool IsTypeSupported(Type type) => TypeInfoLookup.ContainsKey(type); + + /// + /// Encrypts an object value. The object must hold one of the supported data types. + /// + /// Object to be encrypted. + /// holds an unsupported data type. + /// An encrypted string that can be decrypted using Decrypt. + 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())); + } + + /// + /// Decrypts an object value of the specified type. + /// + /// The encrypted string to be decrypted. + /// The type of data that was originally encrypted into . + /// + /// Returns the decrypted value. + 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 + + /// + /// Creates a SymmetricAlgorithm instance for the current encryption algorithm. + /// + /// + /// Returns the created SymmetricAlgorithm instance. + /// + protected SymmetricAlgorithm CreateAlgorithm() + { + MethodInfo method = AlgorithmType.GetMethod("Create", Array.Empty()); + if (method != null) + { + if (method.Invoke(null, null) is SymmetricAlgorithm algorithm) + return algorithm; + } + throw new Exception($"Unable to create instance of {AlgorithmType.FullName}."); + } + + /// + /// Generates a salt that contains a cryptographically strong sequence of random values. + /// + /// The generated salt value. + private byte[] CreateSalt() + { + byte[] salt = new byte[SaltLength]; + using (RNGCryptoServiceProvider generator = new RNGCryptoServiceProvider()) + { + generator.GetBytes(salt); + } + return salt; + } + + /// + /// Generates a pseudorandom key and initialization vector from the current password and the + /// given salt. + /// + /// being used to encrypt. + /// The salt used to derive the key and initialization vector. + /// Returns the generated key. + /// Returns the generated initialization vector. + 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); + } + + /// + /// Generates a series of pseudorandom bytes of the specified length based on the current + /// password and the given salt. + /// + /// The salt used to derive the bytes. + /// The number of bits of data to generate. + /// Returns the derived bytes. + protected byte[] DeriveBytes(byte[] salt, int bytes) + { + Rfc2898DeriveBytes derivedBytes = new Rfc2898DeriveBytes(Password, salt, 1000); + return derivedBytes.GetBytes(bytes); + } + + #endregion + + } +} diff --git a/FSI.Lib/EasyEncryption/EncryptionReader.cs b/FSI.Lib/EasyEncryption/EncryptionReader.cs new file mode 100644 index 0000000..225d231 --- /dev/null +++ b/FSI.Lib/EasyEncryption/EncryptionReader.cs @@ -0,0 +1,105 @@ +using System; +using System.IO; +using System.Security.Cryptography; + +namespace FSI.Lib.EasyEncryption +{ + /// + /// Class that provides streaming decryption functionality. + /// + /// + /// 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. + /// + 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; + } + + /// + /// Reads a DateTime value from the encrypted stream. + /// + /// The decrypted value. + public DateTime ReadDateTime() + { + return new DateTime(ReadInt64()); + } + + /// + /// Reads a byte[] value from the encrypted stream. + /// + /// The decrypted values. + public byte[] ReadByteArray() + { + int count = ReadInt32(); + byte[] bytes = new byte[count]; + if (count > 0) + Read(bytes, 0, count); + return bytes; + } + + /// + /// Reads a string[] value from the encrypted stream. + /// + /// The decrypted values. + 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 + + /// + /// Releases all resources used by the current instance of the EncryptionReader class. + /// + public new void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases the unmanaged resources used by the EncryptionReader class and optionally + /// releases the managed resources. + /// + /// true to release both managed and unmanaged resources; + /// false to release only unmanaged resources. + protected override void Dispose(bool disposing) + { + if (!disposed) + { + disposed = true; + if (disposing) + { + // Dispose managed objects + base.Dispose(true); + Decryptor.Dispose(); + Algorithm.Dispose(); + } + } + } + + /// + /// Destructs this instance of EncryptionReader. + /// + ~EncryptionReader() + { + Dispose(false); + } + + #endregion + + } +} diff --git a/FSI.Lib/EasyEncryption/EncryptionWriter.cs b/FSI.Lib/EasyEncryption/EncryptionWriter.cs new file mode 100644 index 0000000..dbccfe6 --- /dev/null +++ b/FSI.Lib/EasyEncryption/EncryptionWriter.cs @@ -0,0 +1,105 @@ +using System; +using System.IO; +using System.Security.Cryptography; + +namespace FSI.Lib.EasyEncryption +{ + /// + /// Class that provides streaming encryption functionality. + /// + /// + /// 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. + /// + 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; + } + + /// + /// Writes a DateTime value to the encrypted stream. + /// + /// DateTime value to write. + public void Write(DateTime value) + { + Write(value.Ticks); + } + + /// + /// Writes a byte array to the encrypted stream. + /// + /// + /// Note: Hides BinaryWriter.Write(byte[]). + /// + /// byte[] values to write. + public new void Write(byte[] value) + { + Write(value.Length); + Write(value, 0, value.Length); + } + + /// + /// Writes a string to the encrypted stream. + /// + /// string[] values to write. + 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 + + /// + /// Releases all resources used by the current instance of the EncryptionWriter class. + /// + public new void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases the unmanaged resources used by the EncryptionWriter class and optionally + /// releases the managed resources. + /// + /// true to release both managed and unmanaged resources; + /// false to release only unmanaged resources. + protected override void Dispose(bool disposing) + { + if (!disposed) + { + disposed = true; + if (disposing) + { + // Dispose managed objects + base.Dispose(true); + Encryptor.Dispose(); + Algorithm.Dispose(); + } + } + } + + /// + /// Destructs this instance of EncryptionWriter. + /// + ~EncryptionWriter() + { + Dispose(false); + } + + #endregion + + } +} diff --git a/FSI.Lib/EasyEncryption/Readme.md b/FSI.Lib/EasyEncryption/Readme.md new file mode 100644 index 0000000..c7b28a6 --- /dev/null +++ b/FSI.Lib/EasyEncryption/Readme.md @@ -0,0 +1,90 @@ +# EasyEncryption + +[![NuGet version (SoftCircuits.EasyEncryption)](https://img.shields.io/nuget/v/SoftCircuits.EasyEncryption.svg?style=flat-square)](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. \ No newline at end of file diff --git a/FSI.Lib/FSI.Lib.csproj b/FSI.Lib/FSI.Lib.csproj new file mode 100644 index 0000000..5551135 --- /dev/null +++ b/FSI.Lib/FSI.Lib.csproj @@ -0,0 +1,34 @@ + + + + net472;net6.0-windows + Library + true + true + true + 3.0 + + + + + + + + + + + + + + + + + + Always + + + + + + + diff --git a/FSI.Lib/Guis/AutoPw/FrmMain.xaml b/FSI.Lib/Guis/AutoPw/FrmMain.xaml new file mode 100644 index 0000000..ef039a6 --- /dev/null +++ b/FSI.Lib/Guis/AutoPw/FrmMain.xaml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + +