c\#RSA 비대 칭 암호 화 알고리즘 실현
공개 키 와 비밀 키 는 쌍 을 이 루 는 것 이다.일반적으로 우 리 는 공개 키 암호 화,비밀 키 복호화,비밀 키 서명,공개 키 검증 이 라 고 생각한다.어떤 사람 은 비밀 키 암호 화,공개 키 복호화 시 옳지 않다 고 말한다.
공개 키 와 비밀 키 의 생 성 은 여러 가지 방식 이 있 습 니 다.프로그램 을 통 해 생 성 할 수 있 습 니 다(아래 의 구체 적 인 실현).openssl 도 구 를 통 해 생 성 할 수 있 습 니 다.
# , 1024 , pem -out , PKCS1
openssl genrsa -out rsa.pem 1024
# , Subject Public Key, PKCS8
openssl rsa -in rsa.pem -pubout -out rsa.pub
RSA 생 성 키 와 비밀 키 는 보통 두 가지 형식 이 있 습 니 다.PKCS 1 과 PKCS 8 은 위의 명령 으로 생 성 된 비밀 키 는 PKCS 1 형식 이 고 공개 키 는 Subject Public Key 입 니 다.보통 PKCS 8 형식 에 맞 춰 비밀 키 를 사용 하기 때문에 PKCS 1 과 PKCS 8 간 의 전환 과 관련 될 수 있 습 니 다.
# PKCS1 PKCS8 , -out
openssl pkcs8 -topk8 -inform PEM -in rsa.pem -outform pem -nocrypt -out rsa_pkcs8.pem
# PKCS8 PKCS1 , -out
openssl rsa -in rsa_pkcs8.pem -out rsa_pkcs1.pem
# PKCS1 PKCS8 ,
openssl rsa -pubin -in rsa.pub -RSAPublicKey_out
# PKCS8 PKCS1 ,
openssl rsa -RSAPublicKey_in -pubout -in rsa.pub
현실 에서 우 리 는 pem,crt,pfx 파일 에서 공사 와 비밀 키 를 얻 습 니 다.crt,pfx 의 제작 은 참고 할 수 있 습 니 다.ssl 인증 서 를 간단하게 만 들 고 nginx 와 IIS 에서 사용 합 니 다. 또는 기 존의 https://pan.baidu.com/s/1MJ5YmuZiLBnf-DfNR_6D7A(추출 코드:c6tj)을 사용 할 수 있 습 니 다.비밀 번 호 는 모두 123456 입 니 다.C\#실현
pem,crt,pfx 파일 의 공사 와 비밀 키 를 쉽게 읽 기 위해 서 저 는 제3자 가방 을 사 용 했 습 니 다:Portable.Busy Castle,NuGet 설치:Install-Package Portable.Busy Castle 을 사용 할 수 있 습 니 다.
이어서 저 는 RsaHelper 보조 클래스 를 봉 하여 각종 RSA 암호 화 과정 을 실 현 했 습 니 다.
using Org.BouncyCastle.Utilities.IO.Pem;
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
namespace ConsoleApp1
{
public class RsaHelper
{
#region key
/// <summary>
/// Pem
/// </summary>
/// <param name="isPrivateKey"></param>
/// <param name="buffer"></param>
/// <param name="pemFileName"></param>
/// <returns></returns>
public static void WriteToPem(byte[] buffer, bool isPrivateKey, string pemFileName)
{
PemObject pemObject = new PemObject(isPrivateKey ? "RSA PRIVATE KEY" : "RSA PUBLIC KEY", buffer);
if (File.Exists(pemFileName))
{
File.Delete(pemFileName);
}
using (var fileStream = new FileStream(pemFileName, FileMode.OpenOrCreate, FileAccess.Write))
{
using (var sw = new StreamWriter(fileStream))
{
var writer = new PemWriter(sw);
writer.WriteObject(pemObject);
sw.Flush();
}
}
}
/// <summary>
/// Pem
/// </summary>
/// <param name="pemFileName"></param>
/// <returns></returns>
public static byte[] ReadFromPem(string pemFileName)
{
using (var fileStream = new FileStream(pemFileName, FileMode.Open, FileAccess.Read))
{
using (var sw = new StreamReader(fileStream))
{
var writer = new PemReader(sw);
return writer.ReadPemObject().Content;
}
}
}
/// <summary>
/// xml
/// </summary>
/// <param name="xml"></param>
/// <param name="isPrivateKey"></param>
/// <param name="usePkcs8"></param>
/// <returns></returns>
public static byte[] ReadFromXml(string xml, bool isPrivateKey, bool usePkcs8)
{
using (var rsa = new RSACryptoServiceProvider())
{
rsa.FromXmlString(xml);
if (isPrivateKey)
{
return usePkcs8 ? rsa.ExportPkcs8PrivateKey() : rsa.ExportRSAPrivateKey();
}
return usePkcs8 ? rsa.ExportSubjectPublicKeyInfo() : rsa.ExportRSAPublicKey();
}
}
/// <summary>
/// xml
/// </summary>
/// <param name="buffer"></param>
/// <param name="isPrivateKey"></param>
/// <param name="usePkcs8"></param>
/// <returns></returns>
public static string WriteToXml(byte[] buffer, bool isPrivateKey, bool usePkcs8)
{
using (var rsa = CreateRSACryptoServiceProvider(buffer, isPrivateKey, usePkcs8))
{
return rsa.ToXmlString(isPrivateKey);
}
}
/// <summary>
/// RSA Key
/// </summary>
/// <param name="publicKey"></param>
/// <param name="privateKey"></param>
public static void GenerateRsaKey(bool usePKCS8, out byte[] publicKey, out byte[] privateKey)
{
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.KeySize = 1024;//1024
if (usePKCS8)
{
// pkcs8
publicKey = rsa.ExportSubjectPublicKeyInfo();//
privateKey = rsa.ExportPkcs8PrivateKey();//
}
else
{
// pkcs1
publicKey = rsa.ExportRSAPublicKey();//
privateKey = rsa.ExportRSAPrivateKey();//
}
}
}
/// <summary>
/// Pfx RSA Key
/// </summary>
/// <param name="pfxFileName"></param>
/// <param name="publicKey"></param>
/// <param name="privateKey"></param>
public static void ReadFromPfx(string pfxFileName, string password, out byte[] publicKey, out byte[] privateKey)
{
X509Certificate2 x509Certificate2 = new X509Certificate2(pfxFileName, password, X509KeyStorageFlags.Exportable);
publicKey = x509Certificate2.GetRSAPublicKey().ExportRSAPublicKey();
privateKey = x509Certificate2.GetRSAPrivateKey().ExportRSAPrivateKey();
}
/// <summary>
/// Crt
/// </summary>
/// <param name="crtFileName"></param>
/// <param name="password"></param>
/// <returns></returns>
public static byte[] ReadPublicKeyFromCrt(string crtFileName, string password)
{
X509Certificate2 x509Certificate2 = new X509Certificate2(crtFileName, password, X509KeyStorageFlags.Exportable);
var publicKey = x509Certificate2.GetRSAPublicKey().ExportRSAPublicKey();
return publicKey;
}
#endregion
#region Pkcs1 and Pkcs8
/// <summary>
/// Pkcs1 Pkcs8
/// </summary>
/// <param name="isPrivateKey"></param>
/// <param name="buffer"></param>
/// <returns></returns>
public static byte[] Pkcs1ToPkcs8(bool isPrivateKey, byte[] buffer)
{
using (var rsa = new RSACryptoServiceProvider())
{
if (isPrivateKey)
{
rsa.ImportRSAPrivateKey(buffer, out _);
return rsa.ExportPkcs8PrivateKey();
}
else
{
rsa.ImportRSAPublicKey(buffer, out _);
return rsa.ExportSubjectPublicKeyInfo();
}
}
}
/// <summary>
/// Pkcs8 Pkcs1
/// </summary>
/// <param name="isPrivateKey"></param>
/// <param name="buffer"></param>
/// <returns></returns>
public static byte[] Pkcs8ToPkcs1(bool isPrivateKey, byte[] buffer)
{
using (var rsa = new RSACryptoServiceProvider())
{
if (isPrivateKey)
{
rsa.ImportPkcs8PrivateKey(buffer, out _);
return rsa.ExportRSAPrivateKey();
}
else
{
rsa.ImportSubjectPublicKeyInfo(buffer, out _);
return rsa.ExportRSAPublicKey();
}
}
}
#endregion
#region RSA
/// <summary>
/// RSACryptoServiceProvider
/// </summary>
/// <param name="isPrivateKey"></param>
/// <param name="buffer"></param>
/// <param name="usePkcs8"></param>
/// <returns></returns>
public static RSACryptoServiceProvider CreateRSACryptoServiceProvider(byte[] buffer, bool isPrivateKey, bool usePkcs8 = false)
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
if (isPrivateKey)
{
if (usePkcs8)
rsa.ImportPkcs8PrivateKey(buffer, out _);
else
rsa.ImportRSAPrivateKey(buffer, out _);
}
else
{
if (usePkcs8)
rsa.ImportSubjectPublicKeyInfo(buffer, out _);
else
rsa.ImportRSAPublicKey(buffer, out _);
}
return rsa;
}
/// <summary>
/// RSA
/// </summary>
/// <param name="value"> </param>
/// <param name="publicKey"> </param>
/// <param name="usePkcs8"> pkcs8 </param>
/// <returns></returns>
public static string RsaEncrypt(string value, byte[] publicKey, bool usePkcs8 = false)
{
if (string.IsNullOrEmpty(value)) return value;
using (RSACryptoServiceProvider rsa = CreateRSACryptoServiceProvider(publicKey, false, usePkcs8))
{
var buffer = Encoding.UTF8.GetBytes(value);
buffer = rsa.Encrypt(buffer, false);
// hex
StringBuilder result = new StringBuilder();
foreach (byte b in buffer)
{
result.AppendFormat("{0:x2}", b);
}
return result.ToString();
//
//return BitConverter.ToString(buffer).Replace("-", "").ToLower();
}
}
/// <summary>
/// RSA
/// </summary>
/// <param name="value"> </param>
/// <param name="privateKey"> </param>
/// <param name="usePkcs8"> pkcs8 </param>
/// <returns></returns>
public static string RsaDecrypt(string value, byte[] privateKey, bool usePkcs8 = false)
{
if (string.IsNullOrEmpty(value)) return value;
using (RSACryptoServiceProvider rsa = CreateRSACryptoServiceProvider(privateKey, true, usePkcs8))
{
// hex byte
var buffer = new byte[value.Length / 2];
for (var i = 0; i < buffer.Length; i++)
{
buffer[i] = (byte)Convert.ToInt32(value.Substring(i * 2, 2), 16);
}
buffer = rsa.Decrypt(buffer, false);
return Encoding.UTF8.GetString(buffer);
}
}
/// <summary>
/// RSA
/// </summary>
/// <param name="value"> </param>
/// <param name="publicKey"> </param>
/// <param name="halg"> hash :SHA,SHA1,MD5,SHA256,SHA384,SHA512</param>
/// <param name="usePkcs8"> pkcs8 </param>
/// <returns></returns>
public static string Sign(string value, byte[] privateKey, string halg = "MD5", bool usePkcs8 = false)
{
if (string.IsNullOrEmpty(value)) return value;
using (RSACryptoServiceProvider rsa = CreateRSACryptoServiceProvider(privateKey, true, usePkcs8))
{
byte[] buffer = Encoding.UTF8.GetBytes(value);
buffer = rsa.SignData(buffer, HashAlgorithm.Create(halg));
// hex
StringBuilder result = new StringBuilder();
foreach (byte b in buffer)
{
result.AppendFormat("{0:x2}", b);
}
return result.ToString();
//
//return BitConverter.ToString(buffer).Replace("-", "").ToLower();
}
}
/// <summary>
/// RSA
/// </summary>
/// <param name="value"> </param>
/// <param name="publicKey"> </param>
/// <param name="signature"> </param>
/// <param name="halg"> hash :SHA,SHA1,MD5,SHA256,SHA384,SHA512</param>
/// <param name="usePkcs8"> pkcs8 </param>
/// <returns></returns>
public static bool Verify(string value, byte[] publicKey, string signature, string halg = "MD5", bool usePkcs8 = false)
{
if (string.IsNullOrEmpty(value)) return false;
using (RSACryptoServiceProvider rsa = CreateRSACryptoServiceProvider(publicKey, false, usePkcs8))
{
// hex byte
var buffer = new byte[signature.Length / 2];
for (var i = 0; i < buffer.Length; i++)
{
buffer[i] = (byte)Convert.ToInt32(signature.Substring(i * 2, 2), 16);
}
return rsa.VerifyData(Encoding.UTF8.GetBytes(value), HashAlgorithm.Create(halg), buffer);
}
}
#endregion
}
}
RSA 생 성의 비밀 키 를 사용 할 수 있 습 니 다:
//
RsaHelper.GenerateRsaKey(usePKCS8, out publicKey, out privateKey);
비밀 키 를 생 성 한 후 저장 해 야 합 니 다.보통 pem 파일 에 저장 합 니 다:
// Pem ,filePath
RsaHelper.WriteToPem(publicKey, false, Path.Combine(filePath, "rsa.pub"));
RsaHelper.WriteToPem(privateKey, true, Path.Combine(filePath, "rsa.pem"));
공개 키 와 비밀 키 를 xml 형식 으로 출력 합 니 다.
// xml
string publicKeyXml = RsaHelper.WriteToXml(publicKey, false, usePKCS8);
string privateKeyXml = RsaHelper.WriteToXml(privateKey, true, usePKCS8);
pem 파일 과 xml 에 저장 한 후에 도 읽 을 수 있 습 니 다.
// Pem ,filePath
publicKey = RsaHelper.ReadFromPem(Path.Combine(filePath, "rsa.pub"));
privateKey = RsaHelper.ReadFromPem(Path.Combine(filePath, "rsa.pem"));
// xml
publicKey = RsaHelper.ReadFromXml(publicKeyXml, false, usePKCS8);
privateKey = RsaHelper.ReadFromXml(privateKeyXml, true, usePKCS8);
crt 인증서 에서 공개 키 를 읽 을 수 있 습 니 다.crt 파일 에는 비밀 키 가 포함 되 어 있 지 않 기 때문에 개인 키 를 따로 가 져 와 야 합 니 다.
// crt ,filePath
publicKey = RsaHelper.ReadPublicKeyFromCrt(Path.Combine(filePath, "demo.crt"), "");
privateKey = RsaHelper.ReadFromPem(Path.Combine(filePath, "demo.key"));
pfx 파일 에는 공개 키 와 비밀 키 가 포함 되 어 있어 서 쉽게 읽 을 수 있 습 니 다.
// demo.pfx (demo.pfx pkcs1),filePath
RsaHelper.ReadFromPfx(Path.Combine(filePath, "demo.pfx"), "123456", out publicKey, out privateKey);
때때로 우 리 는 비밀 키 의 전환 이 필요 할 수도 있다.
// Pkcs8 Pkcs1
publicKey = RsaHelper.Pkcs8ToPkcs1(false, publicKey);
// Pkcs8 Pkcs1
privateKey = RsaHelper.Pkcs8ToPkcs1(true, privateKey);
// Pkcs1 Pkcs8
publicKey = RsaHelper.Pkcs1ToPkcs8(false, publicKey);
// Pkcs1 Pkcs8
privateKey = RsaHelper.Pkcs1ToPkcs8(true, privateKey);
공개 키 와 비밀 키 가 있 으 면 암호 화,복호화,서명,서명 검증 등 작업 을 할 수 있 습 니 다.
string encryptText = RsaHelper.RsaEncrypt(text, publicKey, usePKCS8);
Console.WriteLine($"【{text}】 【RSA】 :{encryptText}");
string decryptText = RsaHelper.RsaDecrypt(encryptText, privateKey, usePKCS8);
Console.WriteLine($"【{encryptText}】 【RSA】 :{decryptText}");
string signature = RsaHelper.Sign(text, privateKey, "MD5", usePKCS8);
Console.WriteLine($"【{text}】 【RSA】 :{signature}");
bool result = RsaHelper.Verify(text, publicKey, signature, "MD5", usePKCS8);
Console.WriteLine($"【{text}】 【{signature}】 【RSA】 :{result}");
전체 demo 코드:
using System;
using System.IO;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
string text = " ";
bool usePKCS8 = true;// usePKCS8=true PKCS8 , PKCS1
string filePath = Directory.GetCurrentDirectory();
Console.WriteLine($" :{filePath}");// pem,crt,pfx
byte[] publicKey, privateKey;//
//
RsaHelper.GenerateRsaKey(usePKCS8, out publicKey, out privateKey);
// Pem ,filePath
//publicKey = RsaHelper.ReadFromPem(Path.Combine(filePath, "rsa.pub"));
//privateKey = RsaHelper.ReadFromPem(Path.Combine(filePath, "rsa.pem"));
// demo.pfx (demo.pfx pkcs1),filePath
//RsaHelper.ReadFromPfx(Path.Combine(filePath, "demo.pfx"), "123456", out publicKey, out privateKey);
// crt ,filePath
//publicKey = RsaHelper.ReadPublicKeyFromCrt(Path.Combine(filePath, "demo.crt"), "");
//privateKey = RsaHelper.ReadFromPem(Path.Combine(filePath, "demo.key"));
// Pem ,filePath
RsaHelper.WriteToPem(publicKey, false, Path.Combine(filePath, "rsa.pub"));
RsaHelper.WriteToPem(privateKey, true, Path.Combine(filePath, "rsa.pem"));
// xml
string publicKeyXml = RsaHelper.WriteToXml(publicKey, false, usePKCS8);
string privateKeyXml = RsaHelper.WriteToXml(privateKey, true, usePKCS8);
// xml
publicKey = RsaHelper.ReadFromXml(publicKeyXml, false, usePKCS8);
privateKey = RsaHelper.ReadFromXml(privateKeyXml, true, usePKCS8);
// Pkcs8 Pkcs1
publicKey = RsaHelper.Pkcs8ToPkcs1(false, publicKey);
// Pkcs8 Pkcs1
privateKey = RsaHelper.Pkcs8ToPkcs1(true, privateKey);
// Pkcs1 Pkcs8
publicKey = RsaHelper.Pkcs1ToPkcs8(false, publicKey);
// Pkcs1 Pkcs8
privateKey = RsaHelper.Pkcs1ToPkcs8(true, privateKey);
string encryptText = RsaHelper.RsaEncrypt(text, publicKey, usePKCS8);
Console.WriteLine($"【{text}】 【RSA】 :{encryptText}");
string decryptText = RsaHelper.RsaDecrypt(encryptText, privateKey, usePKCS8);
Console.WriteLine($"【{encryptText}】 【RSA】 :{decryptText}");
string signature = RsaHelper.Sign(text, privateKey, "MD5", usePKCS8);
Console.WriteLine($"【{text}】 【RSA】 :{signature}");
bool result = RsaHelper.Verify(text, publicKey, signature, "MD5", usePKCS8);
Console.WriteLine($"【{text}】 【{signature}】 【RSA】 :{result}");
}
}
}
이상 은 c\#RSA 비대 칭 암호 화 알고리즘 을 실현 하 는 상세 한 내용 입 니 다.c\#RSA 비대 칭 암호 화 알고리즘 에 관 한 자 료 는 다른 관련 글 을 주목 하 십시오!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
C#Task를 사용하여 비동기식 작업을 수행하는 방법라인이 완성된 후에 이 라인을 다시 시작할 수 없습니다.반대로 조인(Join)만 결합할 수 있습니다 (프로세스가 현재 라인을 막습니다). 임무는 조합할 수 있는 것이다. 연장을 사용하여 그것들을 한데 연결시키는 것이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.