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 비대 칭 암호 화 알고리즘 에 관 한 자 료 는 다른 관련 글 을 주목 하 십시오!

좋은 웹페이지 즐겨찾기