From 78d1925ef5e76e211be8413cd273b0d97a5fc986 Mon Sep 17 00:00:00 2001 From: Falcon <12919280+falconfly@user.noreply.gitee.com> Date: Fri, 24 Oct 2025 09:54:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E6=A1=86=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 358 ++++++++++++++++++++ PrivateBox.sln | 25 ++ PrivateBox/App.config | 6 + PrivateBox/AppConfig.cs | 22 ++ PrivateBox/DataContext/DbContext.cs | 34 ++ PrivateBox/DataContext/UserKeys.cs | 12 + PrivateBox/EncryptionService.cs | 150 ++++++++ PrivateBox/MainForm.Designer.cs | 195 +++++++++++ PrivateBox/MainForm.cs | 22 ++ PrivateBox/MainForm.resx | 151 +++++++++ PrivateBox/PrivateBox.csproj | 31 ++ PrivateBox/Program.cs | 36 ++ PrivateBox/Properties/Resources.Designer.cs | 63 ++++ PrivateBox/Properties/Resources.resx | 120 +++++++ 14 files changed, 1225 insertions(+) create mode 100644 .gitignore create mode 100644 PrivateBox.sln create mode 100644 PrivateBox/App.config create mode 100644 PrivateBox/AppConfig.cs create mode 100644 PrivateBox/DataContext/DbContext.cs create mode 100644 PrivateBox/DataContext/UserKeys.cs create mode 100644 PrivateBox/EncryptionService.cs create mode 100644 PrivateBox/MainForm.Designer.cs create mode 100644 PrivateBox/MainForm.cs create mode 100644 PrivateBox/MainForm.resx create mode 100644 PrivateBox/PrivateBox.csproj create mode 100644 PrivateBox/Program.cs create mode 100644 PrivateBox/Properties/Resources.Designer.cs create mode 100644 PrivateBox/Properties/Resources.resx diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7e42ad8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,358 @@ +# ---> 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/ +[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/ + +# 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 +*.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, .xml, .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 + +# 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/ + +# ԿͻĿ +/src/ClientApp/ +/src/ApiService/Local.db diff --git a/PrivateBox.sln b/PrivateBox.sln new file mode 100644 index 0000000..908b2d5 --- /dev/null +++ b/PrivateBox.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33829.357 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PrivateBox", "PrivateBox\PrivateBox.csproj", "{CE1A4FB9-53F4-49C8-B22B-232A673093EB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CE1A4FB9-53F4-49C8-B22B-232A673093EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CE1A4FB9-53F4-49C8-B22B-232A673093EB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CE1A4FB9-53F4-49C8-B22B-232A673093EB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CE1A4FB9-53F4-49C8-B22B-232A673093EB}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AC9BD483-D25D-4702-901B-F0F5357C601B} + EndGlobalSection +EndGlobal diff --git a/PrivateBox/App.config b/PrivateBox/App.config new file mode 100644 index 0000000..544cd51 --- /dev/null +++ b/PrivateBox/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/PrivateBox/AppConfig.cs b/PrivateBox/AppConfig.cs new file mode 100644 index 0000000..01fde87 --- /dev/null +++ b/PrivateBox/AppConfig.cs @@ -0,0 +1,22 @@ +using System.Configuration; + +namespace PrivateBox +{ + /// + /// 应用配置 + /// + public class AppConfig + { + /// + /// 获取配置值 + /// + /// 配置的键 + /// 配置值,默认string.Empty + public string GetValue(string key) => ConfigurationManager.AppSettings[key] ?? string.Empty; + + /// + /// sqliteFile名 + /// + public string SqliteFileName => GetValue("sqliteFile") ?? ""; + } +} diff --git a/PrivateBox/DataContext/DbContext.cs b/PrivateBox/DataContext/DbContext.cs new file mode 100644 index 0000000..a805fd9 --- /dev/null +++ b/PrivateBox/DataContext/DbContext.cs @@ -0,0 +1,34 @@ +using Microsoft.Extensions.DependencyInjection; +using SqlSugar; +using System.Runtime.CompilerServices; + +namespace PrivateBox +{ + /// + /// 数据库上下文 + /// + public class DbContext:SqlSugarClient + { + public AppConfig Config { get; init; } + + public DbContext(IServiceProvider provider,AppConfig config) : base(new ConnectionConfig { + DbType = DbType.Sqlite, + ConnectionString = config.SqliteFileName, + IsAutoCloseConnection = false, + + }) { + this.Config = config; + } + + /// + /// 初始化数据库 + /// + public void DbInit() { + this.CodeFirst.SetStringDefaultLength(200); + //db.CodeFirst.InitTables(); + //db.CodeFirst.InitTables(); + //db.CodeFirst.InitTables(); + + } + } +} diff --git a/PrivateBox/DataContext/UserKeys.cs b/PrivateBox/DataContext/UserKeys.cs new file mode 100644 index 0000000..d250449 --- /dev/null +++ b/PrivateBox/DataContext/UserKeys.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PrivateBox.DataContext +{ + internal class UserKeys + { + } +} diff --git a/PrivateBox/EncryptionService.cs b/PrivateBox/EncryptionService.cs new file mode 100644 index 0000000..b889929 --- /dev/null +++ b/PrivateBox/EncryptionService.cs @@ -0,0 +1,150 @@ +using System.Security.Cryptography; + +/// +/// 加密解密服务接口 +/// +public interface IEncryptionService +{ + /// + /// 加密字符串 + /// + /// 原始字符串 + /// 加密密钥(任意长度) + /// 加密后的Base64字符串(包含盐值,格式:[加密数据][盐值]) + string Encrypt(string plainText,string key); + + /// + /// 解密字符串 + /// + /// 加密的Base64字符串(包含盐值) + /// 解密密钥(与加密密钥相同) + /// 解密后的原始字符串 + string Decrypt(string cipherText,string key); +} + + +/// +/// AES加密解密服务实现(动态盐值+密钥派生) +/// +public class AesEncryptionService:IEncryptionService +{ + // 配置参数(可通过依赖注入从配置文件读取) + private const int SaltSize = 16; // 盐值长度(16字节,推荐值) + private const int KeySize = 16; // 派生密钥长度(16字节 = AES-128) + private const int Iterations = 10000; // 密钥派生迭代次数(平衡安全性和性能) + private static readonly HashAlgorithmName HashAlgorithm = HashAlgorithmName.SHA256; + + public string Encrypt(string plainText,string key) { + // 验证输入 + if(string.IsNullOrEmpty(plainText)) + throw new ArgumentException("原始字符串不能为空",nameof(plainText)); + if(string.IsNullOrEmpty(key)) + throw new ArgumentException("密钥不能为空",nameof(key)); + + // 1. 随机生成盐值(.NET 7+ 安全随机数生成) + byte[] salt = RandomNumberGenerator.GetBytes(SaltSize); + + // 2. 从原始密钥和盐值派生AES密钥 + byte[] derivedKey = DeriveKey(key,salt); + + // 3. AES加密逻辑 + byte[] encryptedData; + using(Aes aes = Aes.Create()) { + aes.Key = derivedKey; + aes.GenerateIV(); // 生成随机IV(初始化向量) + aes.Mode = CipherMode.CBC; + aes.Padding = PaddingMode.PKCS7; + + // 创建加密器 + ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key,aes.IV); + + using(MemoryStream msEncrypt = new MemoryStream()) { + // 先写入IV(解密时需要) + msEncrypt.Write(aes.IV,0,aes.IV.Length); + + // 写入加密数据 + using(CryptoStream csEncrypt = new CryptoStream(msEncrypt,encryptor,CryptoStreamMode.Write)) + using(StreamWriter swEncrypt = new StreamWriter(csEncrypt)) { + swEncrypt.Write(plainText); + } + + encryptedData = msEncrypt.ToArray(); + } + } + + // 4. 拼接加密数据和盐值(格式:[加密数据][盐值]) + byte[] result = new byte[encryptedData.Length + SaltSize]; + Array.Copy(encryptedData,0,result,0,encryptedData.Length); + Array.Copy(salt,0,result,encryptedData.Length,SaltSize); + + // 转换为Base64返回 + return Convert.ToBase64String(result); + } + + public string Decrypt(string cipherText,string key) { + // 验证输入 + if(string.IsNullOrEmpty(cipherText)) + throw new ArgumentException("加密字符串不能为空",nameof(cipherText)); + if(string.IsNullOrEmpty(key)) + throw new ArgumentException("密钥不能为空",nameof(key)); + + // 1. 转换Base64为字节数组 + byte[] fullData; + try { + fullData = Convert.FromBase64String(cipherText); + } + catch(FormatException) { + throw new ArgumentException("加密字符串不是有效的Base64格式",nameof(cipherText)); + } + + // 2. 验证数据长度(至少包含IV+盐值) + if(fullData.Length < 16 + SaltSize) // IV固定16字节 + 盐值长度 + throw new ArgumentException("加密字符串无效(长度不足)",nameof(cipherText)); + + // 3. 提取盐值(从尾部提取) + byte[] salt = new byte[SaltSize]; + Array.Copy(fullData,fullData.Length - SaltSize,salt,0,SaltSize); + + // 4. 提取加密数据(排除尾部盐值) + byte[] encryptedData = new byte[fullData.Length - SaltSize]; + Array.Copy(fullData,0,encryptedData,0,encryptedData.Length); + + // 5. 从原始密钥和盐值派生AES密钥(与加密时一致) + byte[] derivedKey = DeriveKey(key,salt); + + // 6. AES解密逻辑 + using(Aes aes = Aes.Create()) { + aes.Key = derivedKey; + aes.Mode = CipherMode.CBC; + aes.Padding = PaddingMode.PKCS7; + + // 提取IV(加密数据的前16字节) + byte[] iv = new byte[16]; + Array.Copy(encryptedData,0,iv,0,iv.Length); + aes.IV = iv; + + // 创建解密器 + ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key,aes.IV); + + // 解密数据(排除IV部分) + using(MemoryStream msDecrypt = new MemoryStream(encryptedData,16,encryptedData.Length - 16)) + using(CryptoStream csDecrypt = new CryptoStream(msDecrypt,decryptor,CryptoStreamMode.Read)) + using(StreamReader srDecrypt = new StreamReader(csDecrypt)) { + return srDecrypt.ReadToEnd(); + } + } + } + + /// + /// 基于PBKDF2算法派生密钥 + /// + private byte[] DeriveKey(string rawKey,byte[] salt) { + using(Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes( + rawKey, + salt, + Iterations, + HashAlgorithm)) { + return deriveBytes.GetBytes(KeySize); + } + } +} \ No newline at end of file diff --git a/PrivateBox/MainForm.Designer.cs b/PrivateBox/MainForm.Designer.cs new file mode 100644 index 0000000..a88ee60 --- /dev/null +++ b/PrivateBox/MainForm.Designer.cs @@ -0,0 +1,195 @@ +namespace PrivateBox +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) { + if(disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + toolStripContainer1 = new ToolStripContainer(); + splitContainer1 = new SplitContainer(); + lbKeyList = new ListBox(); + splitContainer2 = new SplitContainer(); + toolStrip1 = new ToolStrip(); + btEdit = new ToolStripButton(); + btSave = new ToolStripButton(); + btCancel = new ToolStripButton(); + tbMessage = new RichTextBox(); + toolStripContainer1.ContentPanel.SuspendLayout(); + toolStripContainer1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)splitContainer1).BeginInit(); + splitContainer1.Panel1.SuspendLayout(); + splitContainer1.Panel2.SuspendLayout(); + splitContainer1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)splitContainer2).BeginInit(); + splitContainer2.Panel1.SuspendLayout(); + splitContainer2.Panel2.SuspendLayout(); + splitContainer2.SuspendLayout(); + toolStrip1.SuspendLayout(); + SuspendLayout(); + // + // toolStripContainer1 + // + // + // toolStripContainer1.ContentPanel + // + toolStripContainer1.ContentPanel.Controls.Add(splitContainer1); + toolStripContainer1.ContentPanel.Size = new Size(756,379); + toolStripContainer1.Dock = DockStyle.Fill; + toolStripContainer1.Location = new Point(0,0); + toolStripContainer1.Name = "toolStripContainer1"; + toolStripContainer1.Size = new Size(756,404); + toolStripContainer1.TabIndex = 0; + toolStripContainer1.Text = "toolStripContainer1"; + // + // splitContainer1 + // + splitContainer1.Dock = DockStyle.Fill; + splitContainer1.Location = new Point(0,0); + splitContainer1.Name = "splitContainer1"; + // + // splitContainer1.Panel1 + // + splitContainer1.Panel1.Controls.Add(lbKeyList); + // + // splitContainer1.Panel2 + // + splitContainer1.Panel2.Controls.Add(splitContainer2); + splitContainer1.Size = new Size(756,379); + splitContainer1.SplitterDistance = 285; + splitContainer1.TabIndex = 0; + // + // lbKeyList + // + lbKeyList.Dock = DockStyle.Fill; + lbKeyList.FormattingEnabled = true; + lbKeyList.ItemHeight = 17; + lbKeyList.Location = new Point(0,0); + lbKeyList.Name = "lbKeyList"; + lbKeyList.Size = new Size(285,379); + lbKeyList.TabIndex = 0; + // + // splitContainer2 + // + splitContainer2.Dock = DockStyle.Fill; + splitContainer2.Location = new Point(0,0); + splitContainer2.Name = "splitContainer2"; + splitContainer2.Orientation = Orientation.Horizontal; + // + // splitContainer2.Panel1 + // + splitContainer2.Panel1.Controls.Add(toolStrip1); + // + // splitContainer2.Panel2 + // + splitContainer2.Panel2.Controls.Add(tbMessage); + splitContainer2.Size = new Size(467,379); + splitContainer2.SplitterDistance = 25; + splitContainer2.TabIndex = 1; + // + // toolStrip1 + // + toolStrip1.Items.AddRange(new ToolStripItem[] { btEdit,btSave,btCancel }); + toolStrip1.Location = new Point(0,0); + toolStrip1.Name = "toolStrip1"; + toolStrip1.Size = new Size(467,27); + toolStrip1.TabIndex = 0; + toolStrip1.Text = "toolStrip1"; + // + // btEdit + // + btEdit.DisplayStyle = ToolStripItemDisplayStyle.Text; + btEdit.Image = (Image)resources.GetObject("btEdit.Image"); + btEdit.ImageTransparentColor = Color.Magenta; + btEdit.Margin = new Padding(3); + btEdit.Name = "btEdit"; + btEdit.Size = new Size(36,21); + btEdit.Text = "编辑"; + // + // btSave + // + btSave.DisplayStyle = ToolStripItemDisplayStyle.Text; + btSave.Image = (Image)resources.GetObject("btSave.Image"); + btSave.ImageTransparentColor = Color.Magenta; + btSave.Margin = new Padding(3); + btSave.Name = "btSave"; + btSave.Size = new Size(36,21); + btSave.Text = "保存"; + // + // btCancel + // + btCancel.DisplayStyle = ToolStripItemDisplayStyle.Text; + btCancel.Image = (Image)resources.GetObject("btCancel.Image"); + btCancel.ImageTransparentColor = Color.Magenta; + btCancel.Margin = new Padding(3); + btCancel.Name = "btCancel"; + btCancel.Size = new Size(36,21); + btCancel.Text = "取消"; + // + // tbMessage + // + tbMessage.Dock = DockStyle.Fill; + tbMessage.Location = new Point(0,0); + tbMessage.Name = "tbMessage"; + tbMessage.Size = new Size(467,350); + tbMessage.TabIndex = 0; + tbMessage.Text = "tbMessage"; + // + // MainForm + // + AutoScaleDimensions = new SizeF(7F,17F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(756,404); + Controls.Add(toolStripContainer1); + Name = "MainForm"; + Text = "主窗口"; + toolStripContainer1.ContentPanel.ResumeLayout(false); + toolStripContainer1.ResumeLayout(false); + toolStripContainer1.PerformLayout(); + splitContainer1.Panel1.ResumeLayout(false); + splitContainer1.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)splitContainer1).EndInit(); + splitContainer1.ResumeLayout(false); + splitContainer2.Panel1.ResumeLayout(false); + splitContainer2.Panel1.PerformLayout(); + splitContainer2.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)splitContainer2).EndInit(); + splitContainer2.ResumeLayout(false); + toolStrip1.ResumeLayout(false); + toolStrip1.PerformLayout(); + ResumeLayout(false); + } + + #endregion + + private ToolStripContainer toolStripContainer1; + private SplitContainer splitContainer1; + private ListBox lbKeyList; + private RichTextBox tbMessage; + private SplitContainer splitContainer2; + private ToolStrip toolStrip1; + private ToolStripButton btEdit; + private ToolStripButton btSave; + private ToolStripButton btCancel; + } +} \ No newline at end of file diff --git a/PrivateBox/MainForm.cs b/PrivateBox/MainForm.cs new file mode 100644 index 0000000..9dafedb --- /dev/null +++ b/PrivateBox/MainForm.cs @@ -0,0 +1,22 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace PrivateBox +{ + public partial class MainForm:Form + { + public IEncryptionService Encrytion { get; init; } + public MainForm(IServiceProvider provider) { + InitializeComponent(); + this.Encrytion = provider.GetRequiredService(); + } + } +} diff --git a/PrivateBox/MainForm.resx b/PrivateBox/MainForm.resx new file mode 100644 index 0000000..a03afcd --- /dev/null +++ b/PrivateBox/MainForm.resx @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACRSURBVDhPY/j27dt/SjDYACcnJ7IwigEf3n8kCZNswPNb + J/+f6DYF0yA+yQac6Db5f6hWCmwIiE+mC0wIu2DS2Vf/F1x6DefjwlgNyNr34r/0wkdgTMgQDAOQNRNj + CIoBOg0rMTTDMLIhIHbriZeYBmDTiIxBGkEYxge5liQDsGGQqykyAISpZwAlmIEywMAAAAc1/Jwvt6sN + AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACRSURBVDhPY/j27dt/SjDYACcnJ7IwigEf3n8kCZNswPNb + J/+f6DYF0yA+yQac6Db5f6hWCmwIiE+mC0wIu2DS2Vf/F1x6DefjwlgNyNr34r/0wkdgTMgQDAOQNRNj + CIoBOg0rMTTDMLIhIHbriZeYBmDTiIxBGkEYxge5liQDsGGQqykyAISpZwAlmIEywMAAAAc1/Jwvt6sN + AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACRSURBVDhPY/j27dt/SjDYACcnJ7IwigEf3n8kCZNswPNb + J/+f6DYF0yA+yQac6Db5f6hWCmwIiE+mC0wIu2DS2Vf/F1x6DefjwlgNyNr34r/0wkdgTMgQDAOQNRNj + CIoBOg0rMTTDMLIhIHbriZeYBmDTiIxBGkEYxge5liQDsGGQqykyAISpZwAlmIEywMAAAAc1/Jwvt6sN + AAAAAElFTkSuQmCC + + + \ No newline at end of file diff --git a/PrivateBox/PrivateBox.csproj b/PrivateBox/PrivateBox.csproj new file mode 100644 index 0000000..f89cb0b --- /dev/null +++ b/PrivateBox/PrivateBox.csproj @@ -0,0 +1,31 @@ + + + + WinExe + net7.0-windows + enable + true + enable + + + + + + + + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + \ No newline at end of file diff --git a/PrivateBox/Program.cs b/PrivateBox/Program.cs new file mode 100644 index 0000000..e3ec641 --- /dev/null +++ b/PrivateBox/Program.cs @@ -0,0 +1,36 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace PrivateBox +{ + internal static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() { + ApplicationConfiguration.Initialize(); + + IServiceCollection services = new ServiceCollection(); + var appConfig = new AppConfig(); + services.AddSingleton(appConfig); + AddServices(services,appConfig); + using ServiceProvider provider = GetServiceProvider(services); + var mainForm = provider.GetRequiredService(); + Application.Run(mainForm); + } + + static void AddServices(IServiceCollection services,AppConfig config) { + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + } + + static ServiceProvider GetServiceProvider(IServiceCollection services) { + ServiceProvider? provider = null; + services.AddSingleton(sp => provider!); + provider = services.BuildServiceProvider(); + return provider; + } + } +} \ No newline at end of file diff --git a/PrivateBox/Properties/Resources.Designer.cs b/PrivateBox/Properties/Resources.Designer.cs new file mode 100644 index 0000000..6ecc401 --- /dev/null +++ b/PrivateBox/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace PrivateBox.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PrivateBox.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性,对 + /// 使用此强类型资源类的所有资源查找执行重写。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/PrivateBox/Properties/Resources.resx b/PrivateBox/Properties/Resources.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/PrivateBox/Properties/Resources.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file