C#、Golang、Python、Java(Android)之間Des、Rsa加解密互通系列之C#

前言

C#有自己的一套生成密鑰、加解密的庫,但是跟其他文互通比較費勁,經過一翻比較後,筆者選擇了BouncyCastle這套庫,而這套庫的缺點是文檔很少,只能參考Java的代碼才把需求的功能實現。筆者下面提供的代碼是經過多語言環境驗證,可以與其他語言互通。

  1. C#、Golang、Python、Java(Android)之間Des、Rsa加解密互通系列之前言
  2. C#、Golang、Python、Java(Android)之間Des、Rsa加解密互通系列之C#
  3. C#、Golang、Python、Java(Android)之間Des、Rsa加解密互通系列之Golang
  4. C#、Golang、Python、Java(Android)之間Des、Rsa加解密互通系列之Python
  5. C#、Golang、Python、Java(Android)之間Des、Rsa加解密互通系列之Java(Android)

代碼

Des對稱加密工具類

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace lhtzbj12.Encryption
{
    /// <summary>
    /// Des對稱加密工具類
    /// </summary>
    public class DesHelper
    {
        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="data">待加密的數據</param>
        /// <param name="key">加/解密key 8位</param>
        /// <param name="iv">偏移向量 8位</param>
        /// <param name="model">密碼模式</param>
        /// <param name="padding">填充方式</param>
        /// <returns></returns>
        public static string Encrypt(string data, string key, string iv, CipherMode model = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
        {
            byte[] _KeyByte = null;
            if (!string.IsNullOrWhiteSpace(key))
            {
                _KeyByte = Encoding.UTF8.GetBytes(key);
            }

            byte[] _IVByte = null;
            if (!string.IsNullOrWhiteSpace(iv))
            {
                _IVByte = Encoding.UTF8.GetBytes(iv);
            }

            var sa = new DESCryptoServiceProvider();
            sa.Mode = model;
            sa.Padding = padding;           
            var ct = sa.CreateEncryptor(_KeyByte, _IVByte);

            MemoryStream ms = new MemoryStream();
            CryptoStream cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
            byte[] byt = Encoding.UTF8.GetBytes(data);
            cs.Write(byt, 0, byt.Length);
            cs.FlushFinalBlock();
            cs.Close();
            return Convert.ToBase64String(ms.ToArray());
        }
        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="encData">加密生成的Base64密文</param>
        /// <param name="key">加/解密key 8位</param>
        /// <param name="iv">偏移向量 8位</param>
        /// <param name="model">密碼模式</param>
        /// <param name="padding">填充方式</param>
        /// <returns></returns>
        public static string Decrypt(string encData, string key, string iv, CipherMode model = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
        {
            byte[] _KeyByte = null;
            if (!string.IsNullOrWhiteSpace(key))
            {
                _KeyByte = Encoding.UTF8.GetBytes(key);
            }

            byte[] _IVByte = null;
            if (!string.IsNullOrWhiteSpace(iv))
            {
                _IVByte = Encoding.UTF8.GetBytes(iv);
            }

            using (ICryptoTransform ct = new DESCryptoServiceProvider()
            { Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 }.CreateDecryptor(_KeyByte, _IVByte))
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
                    {
                        byte[] byt = Convert.FromBase64String(encData);
                        try
                        {
                            cs.Write(byt, 0, byt.Length);
                            cs.FlushFinalBlock();
                            cs.Close();
                        }
                        catch (Exception)
                        {
                            return string.Empty;
                        }
                    }
                    return Encoding.UTF8.GetString(ms.ToArray());
                }
            }
        }
    }
}

Rsa密鑰對生成、加載(讀取)工具類

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
using System.IO;
using System.Text.RegularExpressions;

namespace lhtzbj12.Encryption
{
    /// <summary>
    /// Rsa密鑰對生成工具
    /// </summary>
    public class RsaKeyHelper
    {
        public static void GenKey(out string publicKey, out string privateKey, out string privateKeyPk8)
        {
            publicKey = string.Empty;
            privateKey = string.Empty;
            privateKeyPk8 = string.Empty;
            try
            {
                //RSA密鑰對的構造器 
                RsaKeyPairGenerator r = new RsaKeyPairGenerator();
                //RSA密鑰構造器的參數 
                RsaKeyGenerationParameters param = new RsaKeyGenerationParameters(
                    Org.BouncyCastle.Math.BigInteger.ValueOf(3),
                    new SecureRandom(),
                    1024,   //密鑰長度 
                    25);
                r.Init(param);
                AsymmetricCipherKeyPair keyPair = r.GenerateKeyPair();
                //獲取公鑰和密鑰 
                AsymmetricKeyParameter private_key = keyPair.Private;
                AsymmetricKeyParameter public_key = keyPair.Public;
                if (((RsaKeyParameters)public_key).Modulus.BitLength < 1024)
                {
                    Console.WriteLine("failed key generation (1024) length test");
                }
                using (TextWriter textWriter = new StringWriter())
                {
                    PemWriter pemWriter = new PemWriter(textWriter);
                    pemWriter.WriteObject(keyPair.Private);
                    pemWriter.Writer.Flush();
                    privateKey = textWriter.ToString();
                }
                using (TextWriter textpubWriter = new StringWriter())
                {
                    PemWriter pempubWriter = new PemWriter(textpubWriter);
                    pempubWriter.WriteObject(keyPair.Public);
                    pempubWriter.Writer.Flush();
                    publicKey = textpubWriter.ToString();                   
                }
                //keyPair = ReadPem(privateKey); // 直接讀取字符串生成密碼鑰                 
                //public_key = keyPair.Public;//公鑰  
                //private_key = keyPair.Private;//私鑰 
                // 前面私鑰爲pkcs1格式,經過下面處理後,變成pkcs8格式
                SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(public_key);
                PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(private_key);
                Asn1Object asn1ObjectPublic = subjectPublicKeyInfo.ToAsn1Object();
                byte[] publicInfoByte = asn1ObjectPublic.GetEncoded();
                Asn1Object asn1ObjectPrivate = privateKeyInfo.ToAsn1Object();
                byte[] privateInfoByte = asn1ObjectPrivate.GetEncoded();

                var pubkeyb64 = Convert.ToBase64String(publicInfoByte);
                // 這裏生成的是Pkcs8的密鑰
                privateKeyPk8 = PrivateKeyPk8Format(Convert.ToBase64String(privateInfoByte));

                privateKey = PrivateKeyFormat(privateKey);
                publicKey = PublicKeyFormat(publicKey);
            }
            catch (Exception ex) {
                throw ex;
            }            
        }

        /// <summary>
        /// 加載Pkcs8格式的私鑰
        /// </summary>
        /// <param name="privateKey"></param>
        /// <returns></returns>
        public static AsymmetricKeyParameter loadPrivateKeyPk8(string privateKey)
        {
            try
            {
                privateKey = KeyClear(privateKey);
                byte[] prikey = Convert.FromBase64String(privateKey);
                Asn1Object priKeyObj = Asn1Object.FromByteArray(prikey);//這裏也可以從流中讀取,從本地導入
                AsymmetricKeyParameter priKey = PrivateKeyFactory.CreateKey(PrivateKeyInfo.GetInstance(priKeyObj));
                return priKey;
            }
            catch (Exception)
            {
                throw new Exception("密鑰格式不正確");
            }
        }

        /// <summary>
        /// 加載Pkcs1格式的私鑰
        /// </summary>
        /// <param name="privateKey"></param>
        /// <returns></returns>
        public static AsymmetricKeyParameter loadPrivateKeyPk1(string privateKey)
        {
            AsymmetricCipherKeyPair keyPair = null;
            try
            {
                keyPair = ReadPem(privateKey); // 直接讀取字符串生成密碼鑰
            }
            catch (Exception)
            {
                throw new Exception("密鑰格式不正確");
            }
            try
            {
                AsymmetricKeyParameter private_key = keyPair.Private;             
                // 前面私鑰爲pkcs1格式,經過下面處理後,變成pkcs8格式              
                PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(private_key);              
                Asn1Object asn1ObjectPrivate = privateKeyInfo.ToAsn1Object();              
                AsymmetricKeyParameter priKey = PrivateKeyFactory.CreateKey(PrivateKeyInfo.GetInstance(asn1ObjectPrivate));
                return priKey;
            }
            catch (Exception)
            {
                throw new Exception("加載失敗");
            }          
        }

        /// <summary>
        /// 加載公鑰
        /// </summary>
        /// <param name="publicKey"></param>
        /// <returns></returns>
        public static AsymmetricKeyParameter loadPublicKey(string publicKey)
        {
            try
            {
                publicKey = KeyClear(publicKey);
                byte[] pubkey = Convert.FromBase64String(publicKey);
                Asn1Object pubKeyObj = Asn1Object.FromByteArray(pubkey);//這裏也可以從流中讀取,從本地導入   
                AsymmetricKeyParameter pubKey = PublicKeyFactory.CreateKey(SubjectPublicKeyInfo.GetInstance(pubKeyObj));
                return pubKey;
            }
            catch (Exception)
            {
                throw new Exception("密鑰格式不正確");
            }
        }

        /// <summary>
        /// 將Pkcs1格式的私轉成Pkcs8格式
        /// </summary>
        /// <param name="privateKey"></param>
        /// <returns></returns>
        public static string ConvertPriPk1ToPk8(string privateKey)
        {
            AsymmetricCipherKeyPair keyPair = null;
            try
            {
                keyPair = ReadPem(privateKey); // 直接讀取字符串生成密碼鑰
            }
            catch (Exception)
            {
                throw new Exception("密鑰格式不正確");
            }
            try
            {
                AsymmetricKeyParameter private_key = keyPair.Private;
                AsymmetricKeyParameter public_key = keyPair.Public;
                // 前面私鑰爲pkcs1格式,經過下面處理後,變成pkcs8格式
                SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(public_key);
                PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(private_key);
                Asn1Object asn1ObjectPublic = subjectPublicKeyInfo.ToAsn1Object();
                byte[] publicInfoByte = asn1ObjectPublic.GetEncoded();
                Asn1Object asn1ObjectPrivate = privateKeyInfo.ToAsn1Object();
                byte[] privateInfoByte = asn1ObjectPrivate.GetEncoded();
                var pubkeyb64 = Convert.ToBase64String(publicInfoByte);
                // 這裏生成的是Pkcs8的密鑰
                return PrivateKeyFormat(Convert.ToBase64String(privateInfoByte));

            }
            catch (Exception)
            {
                throw new Exception("轉換失敗");
            }
        }

        public static string KeyClear(string key)
        {
            key = Regex.Replace(key, @"(-----BEGIN PRIVATE KEY-----)|(-----END PRIVATE KEY-----)|(-----BEGIN RSA PRIVATE KEY-----)|(-----END RSA PRIVATE KEY-----)|(-----BEGIN PUBLIC KEY-----)|(-----END PUBLIC KEY-----)|(-----BEGIN RSA PUBLIC KEY-----)|(-----END RSA PUBLIC KEY-----)|\n|\r", "");
            return key;
        }

        private static string PrivateKeyFormat(string privateKey)
        {
            privateKey = KeyClear(privateKey);
            privateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" + privateKey + "\r\n-----END RSA PRIVATE KEY-----";
            return privateKey;
        }

        private static string PrivateKeyPk8Format(string privateKey)
        {
            privateKey = KeyClear(privateKey);
            privateKey = "-----BEGIN PRIVATE KEY-----\r\n" + privateKey + "\r\n-----END PRIVATE KEY-----";
            return privateKey;
        }

        private static string PublicKeyFormat(string publicKey)
        {
            publicKey = KeyClear(publicKey);
            publicKey = "-----BEGIN PUBLIC KEY-----\r\n" + publicKey + "\r\n-----END PUBLIC KEY-----";
            return publicKey;
        }
        static AsymmetricCipherKeyPair ReadPem(string pem)
        {
            using (TextReader reader = new StringReader(pem))
            {
                var obj = new Org.BouncyCastle.OpenSsl.PemReader(reader).ReadObject();
                return obj as AsymmetricCipherKeyPair;
            }
        }
    }
}

Rsa加密、解密、簽名、驗籤工具類

using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace lhtzbj12.Encryption
{
    /// <summary>
    /// Rsa非對稱加密工具類
    /// </summary>
    public  class RsaBCHelper
    {      
        /// <summary>    
        /// 簽名    
        /// </summary>    
        /// <param name="content">待簽名字符串</param>    
        /// <param name="privateKey">私鑰</param>   
       
        /// <returns>簽名後字符串</returns>    
        public static string Sign(string content, string privateKey)
        {
            AsymmetricKeyParameter priKey = RsaKeyHelper.loadPrivateKeyPk1(privateKey);
            ISigner sig = SignerUtilities.GetSigner("SHA256withRSA"); //其他算法 如SHA1withRSA
            sig.Init(true, priKey);
            var bytes = Encoding.UTF8.GetBytes(content);
            sig.BlockUpdate(bytes, 0, bytes.Length);
            byte[] signature = sig.GenerateSignature();
            var signedString = Convert.ToBase64String(signature);
            return signedString;
        }

        /// <summary>    
        /// 驗籤    
        /// </summary>    
        /// <param name="content">待驗簽字符串</param>    
        /// <param name="signedString">簽名</param>    
        /// <param name="publicKey">公鑰</param> 
        /// <returns>true(通過),false(不通過)</returns>    
        public static bool Verify(string content, string signedString, string publicKey)
        {
            AsymmetricKeyParameter pubKey = RsaKeyHelper.loadPublicKey(publicKey);
            ISigner signer = SignerUtilities.GetSigner("SHA256withRSA"); //其他算法 如SHA1withRSA
            signer.Init(false, pubKey);
            var expectedSig = Convert.FromBase64String(signedString);
            var msgBytes = Encoding.UTF8.GetBytes(content);
            signer.BlockUpdate(msgBytes, 0, msgBytes.Length);
            return signer.VerifySignature(expectedSig);
        }       

        /// <summary>    
        /// 公鑰加密    
        /// </summary>    
        /// <param name="resData">需要加密的字符串</param>    
        /// <param name="publicKey">公鑰</param>  
        /// <returns>明文</returns>    
        public static string Encrypt(string resData, string publicKey)
        {
            try
            {
                AsymmetricKeyParameter pubKey = RsaKeyHelper.loadPublicKey(publicKey);
                IBufferedCipher cipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");
                cipher.Init(true, pubKey);//true表示加密  
                var data = Encoding.UTF8.GetBytes(resData.Trim());
                byte[] encryptData = cipher.DoFinal(data);
                return Convert.ToBase64String(encryptData);
            }
            catch (Exception)
            {
                throw new Exception("加密失敗");
            }
        }

        /// <summary>    
        /// 私鑰解密
        /// </summary>    
        /// <param name="resData">加密字符串</param>    
        /// <param name="privateKey">私鑰</param>    
        /// <param name="input_charset">編碼格式</param>    
        /// <returns>明文</returns>    
        public static string Decrypt(string resData, string privateKey)
        {
            try
            {
                AsymmetricKeyParameter priKey = RsaKeyHelper.loadPrivateKeyPk1(privateKey);
                IBufferedCipher cipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");
                cipher.Init(false, priKey);//false表示解密  
                var encryptData = Convert.FromBase64String(resData);
                var decryptData = cipher.DoFinal(encryptData);
                return Encoding.UTF8.GetString(decryptData);
            }
            catch (Exception) {
                throw new Exception("解密失敗");
            }
            
        }
        /// <summary>    
        /// 私鑰加密    
        /// </summary>    
        /// <param name="resData">需要加密的字符串</param>    
        /// <param name="privateKey">私鑰</param>  
        /// <returns>明文</returns>    
        public static string EncryptByPrivateKey(string resData, string privateKey)
        {
            try
            {
                AsymmetricKeyParameter priKey = RsaKeyHelper.loadPrivateKeyPk1(privateKey);
                IBufferedCipher cipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");
                cipher.Init(true, priKey);//true表示加密  
                var data = Encoding.UTF8.GetBytes(resData.Trim());
                byte[] encryptData = cipher.DoFinal(data);
                return Convert.ToBase64String(encryptData);
            }
            catch (Exception)
            {
                throw new Exception("加密失敗");
            }
        }

        /// <summary>    
        /// 公鑰解密
        /// </summary>    
        /// <param name="resData">加密字符串</param>    
        /// <param name="publicKey">公鑰</param>           
        /// <returns>明文</returns>    
        public static string DecryptByPublicKey(string resData, string publicKey)
        {
            try
            {
                AsymmetricKeyParameter pubKey = RsaKeyHelper.loadPublicKey(publicKey);
                IBufferedCipher cipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");
                cipher.Init(false, pubKey);//false表示解密  
                var encryptData = Convert.FromBase64String(resData);
                var decryptData = cipher.DoFinal(encryptData);
                return Encoding.UTF8.GetString(decryptData);
            }
            catch (Exception)
            {
                throw new Exception("解密失敗");
            }

        }       
    }
}

github工程源碼

https://github.com/lhtzbj12/csharp_encryption

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章