You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
4.8 KiB
125 lines
4.8 KiB
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using System.Security.Cryptography; |
|
using System.Text; |
|
using System.Threading.Tasks; |
|
|
|
namespace AX.WebDrillServer.Middlewares |
|
{ |
|
/// <summary> |
|
/// 非对称RSA加密辅助类。 |
|
/// </summary> |
|
/// <remarks> |
|
/// 切记:公钥验签。 |
|
/// </remarks> |
|
public static class RSAHelper |
|
{ |
|
/// <summary> |
|
/// 根据公钥对数据签名进行验证。 |
|
/// </summary> |
|
/// <param name="publicKey">公钥</param> |
|
/// <param name="data">要验证的数据</param> |
|
/// <param name="signdata">数据签名</param> |
|
/// <param name="hashAlgorithm">散列算法</param> |
|
/// <param name="padding">填充方式</param> |
|
/// <returns></returns> |
|
public static bool VerifyData( |
|
string? publicKey, |
|
string? data, |
|
string? signdata, |
|
string hashAlgorithm = nameof(HashAlgorithmName.SHA256), |
|
RSASignaturePadding? padding = null) |
|
{ |
|
if (string.IsNullOrWhiteSpace(publicKey)) |
|
throw new ArgumentException($"{publicKey}不能为空!"); |
|
|
|
if (string.IsNullOrWhiteSpace(data)) |
|
throw new ArgumentException($"{data}不能为空!"); |
|
|
|
if (string.IsNullOrWhiteSpace(signdata)) |
|
throw new ArgumentException($"{signdata}不能为空!"); |
|
|
|
HashAlgorithmName hash = hashAlgorithm switch |
|
{ |
|
nameof(HashAlgorithmName.MD5) => HashAlgorithmName.MD5, |
|
nameof(HashAlgorithmName.SHA1) => HashAlgorithmName.SHA1, |
|
nameof(HashAlgorithmName.SHA256) => HashAlgorithmName.SHA256, |
|
nameof(HashAlgorithmName.SHA384) => HashAlgorithmName.SHA384, |
|
nameof(HashAlgorithmName.SHA512) => HashAlgorithmName.SHA512, |
|
_ => throw new ArgumentOutOfRangeException(nameof(hashAlgorithm)), |
|
}; |
|
if (padding == null) |
|
padding = RSASignaturePadding.Pkcs1; |
|
|
|
using RSA rsa = RSA.Create(); |
|
rsa.ImportKey(publicKey, false); |
|
|
|
var dataBytes = Encoding.UTF8.GetBytes(data); |
|
var signBytes = Convert.FromBase64String(signdata); |
|
var result = rsa.VerifyData(dataBytes, signBytes, hash, padding); |
|
|
|
return result; |
|
} |
|
} |
|
|
|
internal static class RSAExtensions |
|
{ |
|
private static RSAParameters privateKey; |
|
private static RSAParameters publicKey; |
|
|
|
public static void ImportKey(this RSA rsa, string key, bool isPrivate) |
|
{ |
|
if (isPrivate) |
|
{ |
|
if (privateKey.D == null || |
|
privateKey.DP == null || |
|
privateKey.DQ == null || |
|
privateKey.Exponent == null || |
|
privateKey.InverseQ == null || |
|
privateKey.Modulus == null || |
|
privateKey.P == null || |
|
privateKey.Q == null) |
|
{ |
|
privateKey.D = new byte[256]; |
|
privateKey.DP = new byte[128]; |
|
privateKey.DQ = new byte[128]; |
|
privateKey.Exponent = new byte[3]; |
|
privateKey.InverseQ = new byte[128]; |
|
privateKey.Modulus = new byte[256]; |
|
privateKey.P = new byte[128]; |
|
privateKey.Q = new byte[128]; |
|
|
|
var bytes = Convert.FromBase64String(key); |
|
|
|
Buffer.BlockCopy(bytes, 0, privateKey.D, 0, 256); |
|
Buffer.BlockCopy(bytes, 256, privateKey.DP, 0, 128); |
|
Buffer.BlockCopy(bytes, 256 + 128, privateKey.DQ, 0, 128); |
|
Buffer.BlockCopy(bytes, 256 + 128 + 128, privateKey.Exponent, 0, 3); |
|
Buffer.BlockCopy(bytes, 256 + 128 + 128 + 3, privateKey.InverseQ, 0, 128); |
|
Buffer.BlockCopy(bytes, 256 + 128 + 128 + 3 + 128, privateKey.Modulus, 0, 256); |
|
Buffer.BlockCopy(bytes, 256 + 128 + 128 + 3 + 128 + 256, privateKey.P, 0, 128); |
|
Buffer.BlockCopy(bytes, 256 + 128 + 128 + 3 + 128 + 256 + 128, privateKey.Q, 0, 128); |
|
} |
|
|
|
rsa.ImportParameters(privateKey); |
|
} |
|
else |
|
{ |
|
if (publicKey.Exponent == null || |
|
publicKey.Modulus == null) |
|
{ |
|
publicKey.Exponent = new byte[3]; |
|
publicKey.Modulus = new byte[256]; |
|
|
|
var bytes = Convert.FromBase64String(key); |
|
|
|
Buffer.BlockCopy(bytes, 0, publicKey.Exponent, 0, 3); |
|
Buffer.BlockCopy(bytes, 3, publicKey.Modulus, 0, 256); |
|
} |
|
|
|
rsa.ImportParameters(publicKey); |
|
} |
|
} |
|
} |
|
}
|
|
|