网页版推演服务器
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

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);
}
}
}
}