132 lines
5.0 KiB
C#
132 lines
5.0 KiB
C#
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);
|
||
}
|
||
}
|
||
}
|
||
}
|