LMS.service/LMS.Common/RSAKey/RsaKeyPairGenerator.cs
2024-10-13 17:04:47 +08:00

132 lines
5.0 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using LMS.Common.RSAKey;
using System.Security.Cryptography;
using System.Text;
namespace LMS.Common.RSAKey
{
public static class RsaKeyPairGenerator
{
/// <summary>
/// 初始化一个RSA密钥对
/// </summary>
/// <returns></returns>
public static RSAKeyGenerateModel InitRsaKey()
{
using RSACryptoServiceProvider rsa = new(2048);
string publicKeyPem = ExportPublicKeyToPem(rsa);
string privateKeyPem = ExportPrivateKeyToPem(rsa);
// 随机生成一个AES密钥
byte[] aesKey = GenerateRandomAesKey(32);
byte[] aesIv = GenerateRandomAesKey(16);
// 通过随机的密钥开始AES加密私钥
string encryptPrivateKey = AESGenerate.Encrypt(privateKeyPem, aesKey, aesIv);
return new RSAKeyGenerateModel
{
PublicKey = publicKeyPem,
EncryptedPrivateKey = encryptPrivateKey,
EncryptedKey = Convert.ToBase64String(ComplexKeyObfuscator.Obfuscate(aesKey)),
EncryptionIV = Convert.ToBase64String(ComplexKeyObfuscator.Obfuscate(aesIv))
};
}
private static byte[] GenerateRandomAesKey(int bits)
{
using var randomNumberGenerator = RandomNumberGenerator.Create();
var randomBytes = new byte[bits]; // 256 bits
randomNumberGenerator.GetBytes(randomBytes);
return randomBytes;
}
public static void GenerateRsaKeyPair()
{
using RSACryptoServiceProvider rsa = new(2048);
string publicKeyPem = ExportPublicKeyToPem(rsa);
string privateKeyPem = ExportPrivateKeyToPem(rsa);
Console.WriteLine("公钥 (PEM)\n" + publicKeyPem);
Console.WriteLine("私钥 (PEM)\n" + privateKeyPem);
Console.WriteLine();
string original = "Hello, RSA!";
var encrypted = Encrypt(publicKeyPem, original);
Console.WriteLine("Encrypted: " + encrypted);
Console.WriteLine();
var decrypted = Decrypt(privateKeyPem, encrypted);
Console.WriteLine("Decrypted: " + decrypted);
var signData = SignData(privateKeyPem, original);
Console.WriteLine("SignData: " + signData);
var isVerify = VerifySignData(publicKeyPem, original, signData);
Console.WriteLine("VerifySign: " + isVerify);
}
private static string ExportPublicKeyToPem(RSA rsa)
{
var publicKey = rsa.ExportSubjectPublicKeyInfo();
var base64 = Convert.ToBase64String(publicKey);
return $"-----BEGIN PUBLIC KEY-----\n{InsertNewLines(base64)}\n-----END PUBLIC KEY-----";
}
private static string ExportPrivateKeyToPem(RSA rsa)
{
var privateKey = rsa.ExportPkcs8PrivateKey();
var base64 = Convert.ToBase64String(privateKey);
return $"-----BEGIN PRIVATE KEY-----\n{InsertNewLines(base64)}\n-----END PRIVATE KEY-----";
}
private static string InsertNewLines(string input)
{
return string.Join("\n", Enumerable.Range(0, input.Length / 64 + 1)
.Select(i => input.Substring(i * 64, Math.Min(64, input.Length - i * 64))));
}
public static string Encrypt(string publicKeyPem, string data)
{
using (var rsa = RSA.Create())
{
rsa.ImportFromPem(publicKeyPem);
byte[] encryptedData = rsa.Encrypt(Encoding.UTF8.GetBytes(data), RSAEncryptionPadding.OaepSHA256);
return Convert.ToBase64String(encryptedData);
}
}
public static string Decrypt(string privateKeyPem, string data)
{
using (var rsa = RSA.Create())
{
rsa.ImportFromPem(privateKeyPem);
byte[] decryptedData = rsa.Decrypt(Convert.FromBase64String(data), RSAEncryptionPadding.OaepSHA256);
return Encoding.UTF8.GetString(decryptedData);
}
}
public static string SignData(string privateKeyPem, string data)
{
using (var rsa = RSA.Create())
{
rsa.ImportFromPem(privateKeyPem);
var inputBytes = Encoding.UTF8.GetBytes(data);
var resultBytes = rsa.SignData(inputBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
return Convert.ToBase64String(resultBytes);
}
}
public static bool VerifySignData(string publicKeyPem, string data, string sign)
{
using (var rsa = RSA.Create())
{
rsa.ImportFromPem(publicKeyPem);
var dataBytes = Encoding.UTF8.GetBytes(data);
var signBytes = Convert.FromBase64String(sign);
return rsa.VerifyData(dataBytes, signBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
}
}
}