Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion PCL.Core/PCL.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="System.Management" Version="10.0.3" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="10.0.3" />
<PackageReference Include="PlainToolkit.CngProtectedData" Version="1.0.0" />
<!-- 归档文件 -->
<PackageReference Include="SharpZipLib" Version="1.4.2" />
<!-- 配置文件和数据库 -->
Expand Down Expand Up @@ -100,4 +101,4 @@
<AdditionalFiles Include="App\IoC\LifecycleState.cs" />
<ProjectReference Include="..\PCL.Core.SourceGenerators\PCL.Core.SourceGenerators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>
</Project>
</Project>
15 changes: 15 additions & 0 deletions PCL.Core/Utils/Exts/StringExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -282,6 +283,20 @@ 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);

public byte[] GetBytes(Encoding? encode = null)
{
encode ??= Encoding.UTF8;
return encode.GetBytes(str);
}
}
extension(ReadOnlySpan<char> str){

public int GetBytes(Span<byte> destination, Encoding? encode = null)
{
encode ??= Encoding.UTF8;
return encode.GetBytes(str, destination);
}
}

extension(string hex)
Expand Down
45 changes: 24 additions & 21 deletions PCL.Core/Utils/Secret/EncryptHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@
using PCL.Core.App;
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 static readonly byte[] Key = "PCL CE Encryption Key".GetBytes();
public static (IEncryptionProvider Provider, uint Version) DefaultProvider => _DefaultProvider.Value;
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
private static readonly Lazy<(IEncryptionProvider Provider, uint Version)> _DefaultProvider = new(_SelectBestEncryption);

Expand Down Expand Up @@ -137,8 +142,7 @@ public static bool IsValid(ReadOnlySpan<byte> 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<byte[]> _EncryptionKey = new(_GetKey);

Expand All @@ -151,32 +155,31 @@ private static byte[] _GetKey()
var data = EncryptionData.FromBytes(buf);
return data.Version switch
{
1 => ProtectedData.Unprotect(data.Data, _IdentifyEntropy, DataProtectionScope.CurrentUser),
1 => ProtectedData.Unprotect(data.Data, Key, DataProtectionScope.CurrentUser),
2 => CngProtectedData.Unprotect(data.Data, Key, CngDataProtectionScope.CurrentUser),
_ => 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, Key, 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
}
}
Loading