Skip to content

Commit 3d65a51

Browse files
committed
feat(加密): 添加RSA签名与验签功能支持PKCS#8和PKCS#1格式
实现使用SHA256哈希算法进行RSA签名和验签功能,支持自动识别PKCS#8和PKCS#1格式的密钥。添加参数校验和异常处理,确保数据完整性和安全性。
1 parent cab2555 commit 3d65a51

1 file changed

Lines changed: 91 additions & 0 deletions

File tree

GameFrameX.Foundation.Encryption/RsaHelper.cs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,97 @@ namespace GameFrameX.Foundation.Encryption;
1111
/// </summary>
1212
public sealed class RsaHelper
1313
{
14+
/// <summary>
15+
/// 使用私钥对数据进行签名(SHA256 哈希算法)。
16+
/// 本方法支持 PKCS#8 与 PKCS#1 两种私钥格式,自动识别并导入。
17+
/// 签名过程采用 SHA256 哈希算法与 PKCS#1 填充模式,确保数据完整性与不可否认性。
18+
/// </summary>
19+
/// <remarks>
20+
/// 调用过程:
21+
/// 1. 将待签名内容按 UTF-8 编码转为字节数组;
22+
/// 2. 使用 RSA 私钥对哈希值进行签名;
23+
/// 3. 返回 Base64 编码的签名结果,便于网络传输与存储。
24+
///
25+
/// 异常处理:
26+
/// - 私钥格式非法或导入失败时抛出 <see cref="CryptographicException"/>;
27+
/// - 参数为 null 或空字符串时抛出 <see cref="ArgumentException"/>。
28+
/// </remarks>
29+
/// <param name="privateKey">Base64 格式的私钥字符串,支持 PKCS#8 与 PKCS#1 两种编码。</param>
30+
/// <param name="content">待签名的明文字符串,将使用 UTF-8 编码转换为字节数组。</param>
31+
/// <returns>Base64 格式的签名结果,可直接用于网络传输或持久化存储。</returns>
32+
/// <exception cref="ArgumentException">当 <paramref name="privateKey"/> 或 <paramref name="content"/> 为 null 或空字符串时抛出。</exception>
33+
/// <exception cref="CryptographicException">当私钥格式非法或签名过程失败时抛出。</exception>
34+
public static string Sign(string privateKey, string content)
35+
{
36+
ArgumentException.ThrowIfNullOrEmpty(privateKey, nameof(privateKey));
37+
ArgumentException.ThrowIfNullOrEmpty(content, nameof(content));
38+
39+
using var rsa = RSA.Create();
40+
try
41+
{
42+
// 尝试导入 PKCS#8 格式私钥
43+
rsa.ImportPkcs8PrivateKey(Convert.FromBase64String(privateKey), out _);
44+
}
45+
catch (CryptographicException)
46+
{
47+
// 尝试导入 PKCS#1 格式私钥
48+
rsa.ImportRSAPrivateKey(Convert.FromBase64String(privateKey), out _);
49+
}
50+
51+
52+
var data = Encoding.UTF8.GetBytes(content);
53+
var signature = rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
54+
return Convert.ToBase64String(signature);
55+
}
56+
57+
/// <summary>
58+
/// 使用公钥验证数据签名(SHA256 哈希算法)。
59+
/// 本方法支持 SubjectPublicKeyInfo(PKCS#8)与 RSAPublicKey(PKCS#1)两种公钥格式,自动识别并导入。
60+
/// 验签过程采用 SHA256 哈希算法与 PKCS#1 填充模式,确保签名真实性与数据完整性。
61+
/// </summary>
62+
/// <remarks>
63+
/// 调用过程:
64+
/// 1. 将待验签内容按 UTF-8 编码转为字节数组;
65+
/// 2. 将 Base64 格式的签名解码为字节数组;
66+
/// 3. 使用 RSA 公钥对签名进行验证;
67+
/// 4. 返回验签结果,true 表示签名有效,false 表示签名无效。
68+
///
69+
/// 异常处理:
70+
/// - 公钥格式非法或导入失败时抛出 <see cref="CryptographicException"/>;
71+
/// - 参数为 null 或空字符串时抛出 <see cref="ArgumentException"/>;
72+
/// - 签名不是合法 Base64 字符串时抛出 <see cref="FormatException"/>。
73+
/// </remarks>
74+
/// <param name="publicKey">Base64 格式的公钥字符串,支持 SubjectPublicKeyInfo(PKCS#8)与 RSAPublicKey(PKCS#1)两种编码。</param>
75+
/// <param name="content">待验签的明文字符串,将使用 UTF-8 编码转换为字节数组。</param>
76+
/// <param name="sign">Base64 格式的签名结果,需与 <see cref="Sign"/> 方法生成的格式保持一致。</param>
77+
/// <returns>验签结果,true 表示签名有效,false 表示签名无效。</returns>
78+
/// <exception cref="ArgumentException">当 <paramref name="publicKey"/>、<paramref name="content"/> 或 <paramref name="sign"/> 为 null 或空字符串时抛出。</exception>
79+
/// <exception cref="FormatException">当 <paramref name="sign"/> 不是合法的 Base64 字符串时抛出。</exception>
80+
/// <exception cref="CryptographicException">当公钥格式非法或验签过程失败时抛出。</exception>
81+
public static bool Verify(string publicKey, string content, string sign)
82+
{
83+
ArgumentException.ThrowIfNullOrEmpty(publicKey, nameof(publicKey));
84+
ArgumentException.ThrowIfNullOrEmpty(content, nameof(content));
85+
ArgumentException.ThrowIfNullOrEmpty(sign, nameof(sign));
86+
87+
using var rsa = RSA.Create();
88+
try
89+
{
90+
// 尝试导入 SubjectPublicKeyInfo 格式公钥
91+
rsa.ImportSubjectPublicKeyInfo(Convert.FromBase64String(publicKey), out _);
92+
}
93+
catch (CryptographicException)
94+
{
95+
// 尝试导入 RSAPublicKey (PKCS#1) 格式公钥
96+
rsa.ImportRSAPublicKey(Convert.FromBase64String(publicKey), out _);
97+
}
98+
99+
100+
var data = Encoding.UTF8.GetBytes(content);
101+
var signature = Convert.FromBase64String(sign);
102+
return rsa.VerifyData(data, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
103+
}
104+
14105
/// <summary>
15106
/// 使用公钥加密数据(支持Base64格式公钥)
16107
/// </summary>

0 commit comments

Comments
 (0)