From f7840c96ba2eccd14b6d9e56a49759eb19c86792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E8=BD=BB=E8=AF=AD?= Date: Sun, 31 May 2026 11:55:03 +0800 Subject: [PATCH 01/13] =?UTF-8?q?refactor:=20=E6=8D=A2=E7=94=A8=20CNG=20DP?= =?UTF-8?q?API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PCL.Core/PCL.Core.csproj | 2 ++ PCL.Core/Utils/Secret/EncryptHelper.cs | 49 ++++++++++++++------------ 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/PCL.Core/PCL.Core.csproj b/PCL.Core/PCL.Core.csproj index 7f5c81a4b..1067b71d6 100644 --- a/PCL.Core/PCL.Core.csproj +++ b/PCL.Core/PCL.Core.csproj @@ -9,6 +9,7 @@ Copyright © PCL Community 1.0.0.0 1.0.0.0 + true Debug @@ -53,6 +54,7 @@ + diff --git a/PCL.Core/Utils/Secret/EncryptHelper.cs b/PCL.Core/Utils/Secret/EncryptHelper.cs index 65d832d2d..c6d0a834a 100644 --- a/PCL.Core/Utils/Secret/EncryptHelper.cs +++ b/PCL.Core/Utils/Secret/EncryptHelper.cs @@ -1,19 +1,21 @@ using System; -using System.Buffers; using System.Buffers.Binary; -using System.Collections.Generic; using System.IO; using System.Security.Cryptography; using System.Text; using PCL.Core.App; -using PCL.Core.IO; using PCL.Core.Utils.Encryption; using PCL.Core.Utils.Exts; +using PlainToolkit.CngProtectedData; +using DataProtectionScope = System.Security.Cryptography.DataProtectionScope; +using CngDataProtectionScope = PlainToolkit.CngProtectedData.DataProtectionScope; + namespace PCL.Core.Utils.Secret; public static class EncryptHelper { + private const string Key = "PCL CE Encryption Key"; public static (IEncryptionProvider Provider, uint Version) DefaultProvider => _DefaultProvider.Value; private static readonly Lazy<(IEncryptionProvider Provider, uint Version)> _DefaultProvider = new(_SelectBestEncryption); @@ -140,8 +142,7 @@ public static bool IsValid(ReadOnlySpan data) #endregion #region "密钥存储和获取" - - private static readonly byte[] _IdentifyEntropy = Encoding.UTF8.GetBytes("PCL CE Encryption Key"); + internal static byte[] EncryptionKey { get => _EncryptionKey.Value; } private static readonly Lazy _EncryptionKey = new(_GetKey); @@ -152,33 +153,35 @@ private static byte[] _GetKey() { var buf = File.ReadAllBytes(keyFile); var data = EncryptionData.FromBytes(buf); + Span store = stackalloc byte[22]; + Key.GetBytes(Encoding.UTF8, store); + var space = (ReadOnlySpan)store; return data.Version switch { - 1 => ProtectedData.Unprotect(data.Data, _IdentifyEntropy, DataProtectionScope.CurrentUser), + 1 => ProtectedData.Unprotect(data.Data.AsSpan(), DataProtectionScope.CurrentUser, space), + 2 => CngProtectedData.Unprotect(data.Data.AsSpan(), CngDataProtectionScope.CurrentUser, space), _ => throw new NotSupportedException("Unsupported key version") }; } - else + + var randomKey = new byte[32]; + RandomNumberGenerator.Fill(randomKey); + var storeData = EncryptionData.ToBytes(new EncryptionData { - var randomKey = new byte[32]; - RandomNumberGenerator.Fill(randomKey); - var storeData = EncryptionData.ToBytes(new EncryptionData - { - Version = 1, - Data = ProtectedData.Protect(randomKey, _IdentifyEntropy, DataProtectionScope.CurrentUser) - }); + Version = 2, + Data = CngProtectedData.Protect(randomKey, CngDataProtectionScope.CurrentUser) + }); - var tmpFile = $"{keyFile}.tmp{RandomUtils.NextInt(10000, 99999)}"; - using (var fs = new FileStream(tmpFile, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) - { - fs.Write(storeData); - fs.Flush(true); - } + var tmpFile = $"{keyFile}.tmp{RandomUtils.NextInt(10000, 99999)}"; + using (var fs = new FileStream(tmpFile, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) + { + fs.Write(storeData); + fs.Flush(true); + } - File.Move(tmpFile, keyFile, true); + File.Move(tmpFile, keyFile, true); - return randomKey; - } + return randomKey; } #endregion From 3d3bab29e524c40ce0cd1daec959c9fa271d45f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E8=BD=BB=E8=AF=AD?= Date: Sun, 31 May 2026 11:56:51 +0800 Subject: [PATCH 02/13] chore: remove debug property --- PCL.Core/PCL.Core.csproj | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/PCL.Core/PCL.Core.csproj b/PCL.Core/PCL.Core.csproj index 1067b71d6..a1cdbf405 100644 --- a/PCL.Core/PCL.Core.csproj +++ b/PCL.Core/PCL.Core.csproj @@ -9,7 +9,6 @@ Copyright © PCL Community 1.0.0.0 1.0.0.0 - true Debug @@ -100,4 +99,4 @@ - \ No newline at end of file + From 61879f04fb67755e66cbe9cd6a61fdfde909df08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E8=BD=BB=E8=AF=AD?= Date: Sun, 31 May 2026 12:06:29 +0800 Subject: [PATCH 03/13] =?UTF-8?q?fix:=20=E6=B2=A1=E6=9C=89=E4=BC=A0?= =?UTF-8?q?=E9=80=92=E7=86=B5=E5=AF=BC=E8=87=B4=E8=A7=A3=E5=AF=86=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PCL.Core/Utils/Secret/EncryptHelper.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PCL.Core/Utils/Secret/EncryptHelper.cs b/PCL.Core/Utils/Secret/EncryptHelper.cs index c6d0a834a..e97dd9633 100644 --- a/PCL.Core/Utils/Secret/EncryptHelper.cs +++ b/PCL.Core/Utils/Secret/EncryptHelper.cs @@ -148,14 +148,14 @@ public static bool IsValid(ReadOnlySpan data) private static byte[] _GetKey() { + Span store = stackalloc byte[Encoding.UTF8.GetByteCount(Key)]; + Key.GetBytes(Encoding.UTF8, store); + var space = (ReadOnlySpan)store; var keyFile = Path.Combine(Paths.SharedData, "UserKey.bin"); if (File.Exists(keyFile)) { var buf = File.ReadAllBytes(keyFile); var data = EncryptionData.FromBytes(buf); - Span store = stackalloc byte[22]; - Key.GetBytes(Encoding.UTF8, store); - var space = (ReadOnlySpan)store; return data.Version switch { 1 => ProtectedData.Unprotect(data.Data.AsSpan(), DataProtectionScope.CurrentUser, space), @@ -169,7 +169,7 @@ private static byte[] _GetKey() var storeData = EncryptionData.ToBytes(new EncryptionData { Version = 2, - Data = CngProtectedData.Protect(randomKey, CngDataProtectionScope.CurrentUser) + Data = CngProtectedData.Protect(randomKey, CngDataProtectionScope.CurrentUser, space) }); var tmpFile = $"{keyFile}.tmp{RandomUtils.NextInt(10000, 99999)}"; From 8e7054558985384848ef12e5233fc4e5ef9079da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E8=BD=BB=E8=AF=AD?= Date: Sun, 31 May 2026 12:08:26 +0800 Subject: [PATCH 04/13] chore: add extension method --- PCL.Core/Utils/Exts/StringExtension.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/PCL.Core/Utils/Exts/StringExtension.cs b/PCL.Core/Utils/Exts/StringExtension.cs index 14d941e56..e362de4aa 100644 --- a/PCL.Core/Utils/Exts/StringExtension.cs +++ b/PCL.Core/Utils/Exts/StringExtension.cs @@ -7,6 +7,7 @@ using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; +using System.Text; using System.Text.RegularExpressions; namespace PCL.Core.Utils.Exts; @@ -283,4 +284,19 @@ public int LastIndexOfF(string subStr, bool ignoreCase = false) public int LastIndexOfF(string subStr, int startIndex, bool ignoreCase = false) => str.LastIndexOf(subStr, startIndex, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal); } + + extension(ReadOnlySpan str) + { + public byte[] GetBytes(Encoding? encode = null) + { + encode ??= Encoding.UTF8; + return encode.GetBytes(str.ToString()); + } + + public void GetBytes(Encoding? encode, Span space) + { + encode ??= Encoding.UTF8; + encode.GetBytes(str, space); + } + } } From f125b50092ef0d673a33de30f868d8eb4b0903f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E8=BD=BB=E8=AF=AD?= Date: Mon, 1 Jun 2026 20:05:35 +0800 Subject: [PATCH 05/13] =?UTF-8?q?chore:=20=E7=A7=BB=E9=99=A4=20stackalloc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PCL.Core/Utils/Secret/EncryptHelper.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/PCL.Core/Utils/Secret/EncryptHelper.cs b/PCL.Core/Utils/Secret/EncryptHelper.cs index e97dd9633..b43c2ec38 100644 --- a/PCL.Core/Utils/Secret/EncryptHelper.cs +++ b/PCL.Core/Utils/Secret/EncryptHelper.cs @@ -148,9 +148,7 @@ public static bool IsValid(ReadOnlySpan data) private static byte[] _GetKey() { - Span store = stackalloc byte[Encoding.UTF8.GetByteCount(Key)]; - Key.GetBytes(Encoding.UTF8, store); - var space = (ReadOnlySpan)store; + var space = Key.GetBytes(); var keyFile = Path.Combine(Paths.SharedData, "UserKey.bin"); if (File.Exists(keyFile)) { @@ -158,8 +156,8 @@ private static byte[] _GetKey() var data = EncryptionData.FromBytes(buf); return data.Version switch { - 1 => ProtectedData.Unprotect(data.Data.AsSpan(), DataProtectionScope.CurrentUser, space), - 2 => CngProtectedData.Unprotect(data.Data.AsSpan(), CngDataProtectionScope.CurrentUser, space), + 1 => ProtectedData.Unprotect(data.Data, DataProtectionScope.CurrentUser, space), + 2 => CngProtectedData.Unprotect(data.Data, CngDataProtectionScope.CurrentUser, space), _ => throw new NotSupportedException("Unsupported key version") }; } @@ -185,4 +183,4 @@ private static byte[] _GetKey() } #endregion -} \ No newline at end of file +} From f50c8f583b1bb50305d05e3c5f8530f96f2d8a66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E8=BD=BB=E8=AF=AD?= Date: Thu, 4 Jun 2026 12:48:56 +0800 Subject: [PATCH 06/13] =?UTF-8?q?chore(exts):=20=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E6=9C=89=E6=95=88=E5=AD=97=E8=8A=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> --- PCL.Core/Utils/Exts/StringExtension.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PCL.Core/Utils/Exts/StringExtension.cs b/PCL.Core/Utils/Exts/StringExtension.cs index e362de4aa..cb32664d9 100644 --- a/PCL.Core/Utils/Exts/StringExtension.cs +++ b/PCL.Core/Utils/Exts/StringExtension.cs @@ -293,10 +293,10 @@ public byte[] GetBytes(Encoding? encode = null) return encode.GetBytes(str.ToString()); } - public void GetBytes(Encoding? encode, Span space) + public int GetBytes(Encoding? encode = null, Span destination) { encode ??= Encoding.UTF8; - encode.GetBytes(str, space); + return encode.GetBytes(str, destination); } } } From af6c5390dcc93aeca807a4d57565213107e42250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E8=BD=BB=E8=AF=AD?= Date: Thu, 4 Jun 2026 13:02:44 +0800 Subject: [PATCH 07/13] =?UTF-8?q?fix:(method-argument):=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=20Optional=20=E5=8F=82=E6=95=B0=E9=A1=BA=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No AI --- PCL.Core/Utils/Exts/StringExtension.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PCL.Core/Utils/Exts/StringExtension.cs b/PCL.Core/Utils/Exts/StringExtension.cs index cb32664d9..00e38b986 100644 --- a/PCL.Core/Utils/Exts/StringExtension.cs +++ b/PCL.Core/Utils/Exts/StringExtension.cs @@ -293,7 +293,7 @@ public byte[] GetBytes(Encoding? encode = null) return encode.GetBytes(str.ToString()); } - public int GetBytes(Encoding? encode = null, Span destination) + public int GetBytes(Span destination, Encoding? encode = null) { encode ??= Encoding.UTF8; return encode.GetBytes(str, destination); From 598eea67132892f9a909553a912e04a222439652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E8=BD=BB=E8=AF=AD?= Date: Thu, 4 Jun 2026 13:06:34 +0800 Subject: [PATCH 08/13] =?UTF-8?q?refactor:=20=E5=8E=BB=E9=99=A4=E4=B8=8D?= =?UTF-8?q?=E5=BF=85=E8=A6=81=E7=9A=84=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changed Key to a readonly byte array and updated usage in _GetKey method. --- PCL.Core/Utils/Secret/EncryptHelper.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/PCL.Core/Utils/Secret/EncryptHelper.cs b/PCL.Core/Utils/Secret/EncryptHelper.cs index b43c2ec38..94be11934 100644 --- a/PCL.Core/Utils/Secret/EncryptHelper.cs +++ b/PCL.Core/Utils/Secret/EncryptHelper.cs @@ -15,7 +15,7 @@ namespace PCL.Core.Utils.Secret; public static class EncryptHelper { - private const string Key = "PCL CE Encryption Key"; + private static readnoly byte[] Key = "PCL CE Encryption Key".GetBytes(); public static (IEncryptionProvider Provider, uint Version) DefaultProvider => _DefaultProvider.Value; private static readonly Lazy<(IEncryptionProvider Provider, uint Version)> _DefaultProvider = new(_SelectBestEncryption); @@ -148,7 +148,6 @@ public static bool IsValid(ReadOnlySpan data) private static byte[] _GetKey() { - var space = Key.GetBytes(); var keyFile = Path.Combine(Paths.SharedData, "UserKey.bin"); if (File.Exists(keyFile)) { @@ -156,8 +155,8 @@ private static byte[] _GetKey() var data = EncryptionData.FromBytes(buf); return data.Version switch { - 1 => ProtectedData.Unprotect(data.Data, DataProtectionScope.CurrentUser, space), - 2 => CngProtectedData.Unprotect(data.Data, CngDataProtectionScope.CurrentUser, space), + 1 => ProtectedData.Unprotect(data.Data, Key, DataProtectionScope.CurrentUser), + 2 => CngProtectedData.Unprotect(data.Data, Key, CngDataProtectionScope.CurrentUser), _ => throw new NotSupportedException("Unsupported key version") }; } From f2d25029c9b0787811e3410996267176b9f4a04b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E8=BD=BB=E8=AF=AD?= Date: Thu, 4 Jun 2026 13:09:13 +0800 Subject: [PATCH 09/13] fix: incorrect declared. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 珍爱生命,远离 GitHub WebEditor --- PCL.Core/Utils/Secret/EncryptHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PCL.Core/Utils/Secret/EncryptHelper.cs b/PCL.Core/Utils/Secret/EncryptHelper.cs index 94be11934..6cd6a75c6 100644 --- a/PCL.Core/Utils/Secret/EncryptHelper.cs +++ b/PCL.Core/Utils/Secret/EncryptHelper.cs @@ -15,7 +15,7 @@ namespace PCL.Core.Utils.Secret; public static class EncryptHelper { - private static readnoly byte[] Key = "PCL CE Encryption Key".GetBytes(); + private static readonly byte[] Key = "PCL CE Encryption Key".GetBytes(); public static (IEncryptionProvider Provider, uint Version) DefaultProvider => _DefaultProvider.Value; private static readonly Lazy<(IEncryptionProvider Provider, uint Version)> _DefaultProvider = new(_SelectBestEncryption); From 403b385d2206ec203d6d3e0eb1a72c4b04b9556f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E8=BD=BB=E8=AF=AD?= Date: Thu, 4 Jun 2026 13:18:58 +0800 Subject: [PATCH 10/13] =?UTF-8?q?refactor:=20=E4=BB=8E=20extension(Readonl?= =?UTF-8?q?y)=20=E7=A7=BB=E9=99=A4=20byte[]=20GetBytes=20=E5=AE=9A?= =?UTF-8?q?=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor StringExtension methods to improve performance and readability. --- PCL.Core/Utils/Exts/StringExtension.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/PCL.Core/Utils/Exts/StringExtension.cs b/PCL.Core/Utils/Exts/StringExtension.cs index 00e38b986..576acb7f9 100644 --- a/PCL.Core/Utils/Exts/StringExtension.cs +++ b/PCL.Core/Utils/Exts/StringExtension.cs @@ -283,16 +283,15 @@ public int LastIndexOfF(string subStr, bool ignoreCase = false) public int LastIndexOfF(string subStr, int startIndex, bool ignoreCase = false) => str.LastIndexOf(subStr, startIndex, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal); - } - - extension(ReadOnlySpan str) - { + public byte[] GetBytes(Encoding? encode = null) { encode ??= Encoding.UTF8; - return encode.GetBytes(str.ToString()); + return encode.GetBytes(str); } - + } + extension(Readonly str){ + public int GetBytes(Span destination, Encoding? encode = null) { encode ??= Encoding.UTF8; From 50799ccc87b90d3f72bb22f08d6ccdf3dfe3d5ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E8=BD=BB=E8=AF=AD?= Date: Thu, 4 Jun 2026 13:20:45 +0800 Subject: [PATCH 11/13] fix: undeclared member --- PCL.Core/Utils/Secret/EncryptHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PCL.Core/Utils/Secret/EncryptHelper.cs b/PCL.Core/Utils/Secret/EncryptHelper.cs index 6cd6a75c6..403dc5e17 100644 --- a/PCL.Core/Utils/Secret/EncryptHelper.cs +++ b/PCL.Core/Utils/Secret/EncryptHelper.cs @@ -166,7 +166,7 @@ private static byte[] _GetKey() var storeData = EncryptionData.ToBytes(new EncryptionData { Version = 2, - Data = CngProtectedData.Protect(randomKey, CngDataProtectionScope.CurrentUser, space) + Data = CngProtectedData.Protect(randomKey, Key, CngDataProtectionScope.CurrentUser) }); var tmpFile = $"{keyFile}.tmp{RandomUtils.NextInt(10000, 99999)}"; From 3c4ad2ca7857f21ed07cb5cac85268f8146ff20c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E8=BD=BB=E8=AF=AD?= Date: Thu, 4 Jun 2026 13:22:49 +0800 Subject: [PATCH 12/13] fix: invalid type --- PCL.Core/Utils/Exts/StringExtension.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PCL.Core/Utils/Exts/StringExtension.cs b/PCL.Core/Utils/Exts/StringExtension.cs index 576acb7f9..8b776f707 100644 --- a/PCL.Core/Utils/Exts/StringExtension.cs +++ b/PCL.Core/Utils/Exts/StringExtension.cs @@ -290,7 +290,7 @@ public byte[] GetBytes(Encoding? encode = null) return encode.GetBytes(str); } } - extension(Readonly str){ + extension(ReadonlySpan str){ public int GetBytes(Span destination, Encoding? encode = null) { From 70e55da36616d811997c78ea7a4c558822f2e540 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E8=BD=BB=E8=AF=AD?= Date: Thu, 4 Jun 2026 13:26:33 +0800 Subject: [PATCH 13/13] fix: upper case only --- PCL.Core/Utils/Exts/StringExtension.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PCL.Core/Utils/Exts/StringExtension.cs b/PCL.Core/Utils/Exts/StringExtension.cs index 8b776f707..bd9e4db24 100644 --- a/PCL.Core/Utils/Exts/StringExtension.cs +++ b/PCL.Core/Utils/Exts/StringExtension.cs @@ -290,7 +290,7 @@ public byte[] GetBytes(Encoding? encode = null) return encode.GetBytes(str); } } - extension(ReadonlySpan str){ + extension(ReadOnlySpan str){ public int GetBytes(Span destination, Encoding? encode = null) {