C#通過java生成的RSA公鑰加密和解密

風靈使發表於2018-09-04

最近工作需要將對方公司生成的RSA加密公鑰進行明文加密和解密,發現了幾點貼出來做個筆記。

RSA單次加密是有長度限制!微軟封裝的加密方法如果出現長度超出指定範圍的話報錯是直接報“該項不適於在指定狀態下使用”…

如需加密只能分段加密!

直接將現在使用的封裝類貼出來吧。

新建一個類,裡面有很多擴充套件函式

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Org.BouncyCastle;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.Utilities.Collections;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Asn1;

namespace TAPI.Common
{
    public static class RSAExtensions
    {
        /// <summary>
        ///  把java的私鑰轉換成.net的xml格式
        /// </summary>
        /// <param name="rsa"></param>
        /// <param name="privateJavaKey"></param>
        /// <returns></returns>
        public static string ConvertToXmlPrivateKey(this RSA rsa, string privateJavaKey)
        {
            RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateJavaKey));
            string xmlPrivateKey = string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>",
                         Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()),
                         Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()),
                         Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()),
                         Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()),
                         Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()),
                         Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()),
                         Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()),
                         Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned()));
            return xmlPrivateKey;
        }
        /// <summary>
        /// RSA載入JAVA  PrivateKey
        /// </summary>
        /// <param name="privateJavaKey">java提供的第三方私鑰</param>
        /// <returns></returns>
        public static void FromPrivateKeyJavaString(this RSA rsa, string privateJavaKey)
        {
            string xmlPrivateKey = rsa.ConvertToXmlPrivateKey(privateJavaKey);
            rsa.FromXmlString(xmlPrivateKey);
        }

        /// <summary>
        /// 把java的公鑰轉換成.net的xml格式
        /// </summary>
        /// <param name="publicJavaKey">java提供的第三方公鑰</param>
        /// <returns></returns>
        public static string ConvertToXmlPublicJavaKey(this RSA rsa, string publicJavaKey)
        {
            RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicJavaKey));
            string xmlpublicKey = string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
              Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),
              Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));
            return xmlpublicKey;
        }

        /// <summary>
        /// 把java的私鑰轉換成.net的xml格式
        /// </summary>
        /// <param name="publicJavaKey">java提供的第三方公鑰</param>
        /// <returns></returns>
        public static void FromPublicKeyJavaString(this RSA rsa, string publicJavaKey)
        {
            string xmlpublicKey = rsa.ConvertToXmlPublicJavaKey(publicJavaKey);
            rsa.FromXmlString(xmlpublicKey);
        }
        ///// <summary>
        ///// RSA公鑰格式轉換,java->.net
        ///// </summary>
        ///// <param name="publicKey">java生成的公鑰</param>
        ///// <returns></returns>
        //private static string ConvertJavaPublicKeyToDotNet(this RSA rsa,string publicKey)
        //{           
        //    RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey));
        //    return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
        //        Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),
        //        Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));
        //}

        /// <summary>Extension method for initializing a RSACryptoServiceProvider from PEM data string.</summary>

        #region Methods

        /// <summary>Extension method which initializes an RSACryptoServiceProvider from a DER public key blob.</summary>
        public static void LoadPublicKeyDER(this RSACryptoServiceProvider provider, byte[] DERData)
        {
            byte[] RSAData = GetRSAFromDER(DERData);
            byte[] publicKeyBlob = GetPublicKeyBlobFromRSA(RSAData);
            provider.ImportCspBlob(publicKeyBlob);
        }

        /// <summary>Extension method which initializes an RSACryptoServiceProvider from a DER private key blob.</summary>
        public static void LoadPrivateKeyDER(this RSACryptoServiceProvider provider, byte[] DERData)
        {
            byte[] privateKeyBlob = GetPrivateKeyDER(DERData);
            provider.ImportCspBlob(privateKeyBlob);
        }

        /// <summary>Extension method which initializes an RSACryptoServiceProvider from a PEM public key string.</summary>
        public static void LoadPublicKeyPEM(this RSACryptoServiceProvider provider, string sPEM)
        {
            byte[] DERData = GetDERFromPEM(sPEM);
            LoadPublicKeyDER(provider, DERData);
        }

        /// <summary>Extension method which initializes an RSACryptoServiceProvider from a PEM private key string.</summary>
        public static void LoadPrivateKeyPEM(this RSACryptoServiceProvider provider, string sPEM)
        {
            byte[] DERData = GetDERFromPEM(sPEM);
            LoadPrivateKeyDER(provider, DERData);
        }

        /// <summary>Returns a public key blob from an RSA public key.</summary>
        internal static byte[] GetPublicKeyBlobFromRSA(byte[] RSAData)
        {
            byte[] data = null;
            UInt32 dwCertPublicKeyBlobSize = 0;
            if (CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING,
                new IntPtr((int)CRYPT_OUTPUT_TYPES.RSA_CSP_PUBLICKEYBLOB), RSAData, (UInt32)RSAData.Length, CRYPT_DECODE_FLAGS.NONE,
                data, ref dwCertPublicKeyBlobSize))
            {
                data = new byte[dwCertPublicKeyBlobSize];
                if (!CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING,
                    new IntPtr((int)CRYPT_OUTPUT_TYPES.RSA_CSP_PUBLICKEYBLOB), RSAData, (UInt32)RSAData.Length, CRYPT_DECODE_FLAGS.NONE,
                    data, ref dwCertPublicKeyBlobSize))
                    throw new Win32Exception(Marshal.GetLastWin32Error());
            }
            else
                throw new Win32Exception(Marshal.GetLastWin32Error());
            return data;
        }

        /// <summary>Converts DER binary format to a CAPI CRYPT_PRIVATE_KEY_INFO structure.</summary>
        internal static byte[] GetPrivateKeyDER(byte[] DERData)
        {
            byte[] data = null;
            UInt32 dwRSAPrivateKeyBlobSize = 0;
            IntPtr pRSAPrivateKeyBlob = IntPtr.Zero;
            if (CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING, new IntPtr((int)CRYPT_OUTPUT_TYPES.PKCS_RSA_PRIVATE_KEY),
                DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, ref dwRSAPrivateKeyBlobSize))
            {
                data = new byte[dwRSAPrivateKeyBlobSize];
                if (!CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING, new IntPtr((int)CRYPT_OUTPUT_TYPES.PKCS_RSA_PRIVATE_KEY),
                    DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, ref dwRSAPrivateKeyBlobSize))
                    throw new Win32Exception(Marshal.GetLastWin32Error());
            }
            else
                throw new Win32Exception(Marshal.GetLastWin32Error());
            return data;
        }

        /// <summary>Converts DER binary format to a CAPI CERT_PUBLIC_KEY_INFO structure containing an RSA key.</summary>
        internal static byte[] GetRSAFromDER(byte[] DERData)
        {
            byte[] data = null;
            byte[] publicKey = null;
            CERT_PUBLIC_KEY_INFO info;
            UInt32 dwCertPublicKeyInfoSize = 0;
            IntPtr pCertPublicKeyInfo = IntPtr.Zero;
            if (CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING, new IntPtr((int)CRYPT_OUTPUT_TYPES.X509_PUBLIC_KEY_INFO),
                DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, ref dwCertPublicKeyInfoSize))
            {
                data = new byte[dwCertPublicKeyInfoSize];
                if (CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING, new IntPtr((int)CRYPT_OUTPUT_TYPES.X509_PUBLIC_KEY_INFO),
                    DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, ref dwCertPublicKeyInfoSize))
                {
                    GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
                    try
                    {
                        info = (CERT_PUBLIC_KEY_INFO)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(CERT_PUBLIC_KEY_INFO));
                        publicKey = new byte[info.PublicKey.cbData];
                        Marshal.Copy(info.PublicKey.pbData, publicKey, 0, publicKey.Length);
                    }
                    finally
                    {
                        handle.Free();
                    }
                }
                else
                    throw new Win32Exception(Marshal.GetLastWin32Error());
            }
            else
                throw new Win32Exception(Marshal.GetLastWin32Error());
            return publicKey;
        }

        /// <summary>Extracts the binary data from a PEM file.</summary>
        internal static byte[] GetDERFromPEM(string sPEM)
        {
            UInt32 dwSkip, dwFlags;
            UInt32 dwBinarySize = 0;

            if (!CryptStringToBinary(sPEM, (UInt32)sPEM.Length, CRYPT_STRING_FLAGS.CRYPT_STRING_BASE64HEADER, null, ref dwBinarySize, out dwSkip, out dwFlags))
                throw new Win32Exception(Marshal.GetLastWin32Error());

            byte[] decodedData = new byte[dwBinarySize];
            if (!CryptStringToBinary(sPEM, (UInt32)sPEM.Length, CRYPT_STRING_FLAGS.CRYPT_STRING_BASE64HEADER, decodedData, ref dwBinarySize, out dwSkip, out dwFlags))
                throw new Win32Exception(Marshal.GetLastWin32Error());
            return decodedData;
        }

        #endregion Methods

        #region P/Invoke Constants

        /// <summary>Enumeration derived from Crypto API.</summary>
        internal enum CRYPT_ACQUIRE_CONTEXT_FLAGS : uint
        {
            CRYPT_NEWKEYSET = 0x8,
            CRYPT_DELETEKEYSET = 0x10,
            CRYPT_MACHINE_KEYSET = 0x20,
            CRYPT_SILENT = 0x40,
            CRYPT_DEFAULT_CONTAINER_OPTIONAL = 0x80,
            CRYPT_VERIFYCONTEXT = 0xF0000000
        }

        /// <summary>Enumeration derived from Crypto API.</summary>
        internal enum CRYPT_PROVIDER_TYPE : uint
        {
            PROV_RSA_FULL = 1
        }

        /// <summary>Enumeration derived from Crypto API.</summary>
        internal enum CRYPT_DECODE_FLAGS : uint
        {
            NONE = 0,
            CRYPT_DECODE_ALLOC_FLAG = 0x8000
        }

        /// <summary>Enumeration derived from Crypto API.</summary>
        internal enum CRYPT_ENCODING_FLAGS : uint
        {
            PKCS_7_ASN_ENCODING = 0x00010000,
            X509_ASN_ENCODING = 0x00000001,
        }

        /// <summary>Enumeration derived from Crypto API.</summary>
        internal enum CRYPT_OUTPUT_TYPES : int
        {
            X509_PUBLIC_KEY_INFO = 8,
            RSA_CSP_PUBLICKEYBLOB = 19,
            PKCS_RSA_PRIVATE_KEY = 43,
            PKCS_PRIVATE_KEY_INFO = 44
        }

        /// <summary>Enumeration derived from Crypto API.</summary>
        internal enum CRYPT_STRING_FLAGS : uint
        {
            CRYPT_STRING_BASE64HEADER = 0,
            CRYPT_STRING_BASE64 = 1,
            CRYPT_STRING_BINARY = 2,
            CRYPT_STRING_BASE64REQUESTHEADER = 3,
            CRYPT_STRING_HEX = 4,
            CRYPT_STRING_HEXASCII = 5,
            CRYPT_STRING_BASE64_ANY = 6,
            CRYPT_STRING_ANY = 7,
            CRYPT_STRING_HEX_ANY = 8,
            CRYPT_STRING_BASE64X509CRLHEADER = 9,
            CRYPT_STRING_HEXADDR = 10,
            CRYPT_STRING_HEXASCIIADDR = 11,
            CRYPT_STRING_HEXRAW = 12,
            CRYPT_STRING_NOCRLF = 0x40000000,
            CRYPT_STRING_NOCR = 0x80000000
        }

        #endregion P/Invoke Constants

        #region P/Invoke Structures

        /// <summary>Structure from Crypto API.</summary>
        [StructLayout(LayoutKind.Sequential)]
        internal struct CRYPT_OBJID_BLOB
        {
            internal UInt32 cbData;
            internal IntPtr pbData;
        }

        /// <summary>Structure from Crypto API.</summary>
        [StructLayout(LayoutKind.Sequential)]
        internal struct CRYPT_ALGORITHM_IDENTIFIER
        {
            internal IntPtr pszObjId;
            internal CRYPT_OBJID_BLOB Parameters;
        }

        /// <summary>Structure from Crypto API.</summary>
        [StructLayout(LayoutKind.Sequential)]
        struct CRYPT_BIT_BLOB
        {
            internal UInt32 cbData;
            internal IntPtr pbData;
            internal UInt32 cUnusedBits;
        }

        /// <summary>Structure from Crypto API.</summary>
        [StructLayout(LayoutKind.Sequential)]
        struct CERT_PUBLIC_KEY_INFO
        {
            internal CRYPT_ALGORITHM_IDENTIFIER Algorithm;
            internal CRYPT_BIT_BLOB PublicKey;
        }

        #endregion P/Invoke Structures

        #region P/Invoke Functions

        /// <summary>Function for Crypto API.</summary>
        [DllImport("advapi32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool CryptDestroyKey(IntPtr hKey);

        /// <summary>Function for Crypto API.</summary>
        [DllImport("advapi32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool CryptImportKey(IntPtr hProv, byte[] pbKeyData, UInt32 dwDataLen, IntPtr hPubKey, UInt32 dwFlags, ref IntPtr hKey);

        /// <summary>Function for Crypto API.</summary>
        [DllImport("advapi32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool CryptReleaseContext(IntPtr hProv, Int32 dwFlags);

        /// <summary>Function for Crypto API.</summary>
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool CryptAcquireContext(ref IntPtr hProv, string pszContainer, string pszProvider, CRYPT_PROVIDER_TYPE dwProvType, CRYPT_ACQUIRE_CONTEXT_FLAGS dwFlags);

        /// <summary>Function from Crypto API.</summary>
        [DllImport("crypt32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool CryptStringToBinary(string sPEM, UInt32 sPEMLength, CRYPT_STRING_FLAGS dwFlags, [Out] byte[] pbBinary, ref UInt32 pcbBinary, out UInt32 pdwSkip, out UInt32 pdwFlags);

        /// <summary>Function from Crypto API.</summary>
        [DllImport("crypt32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool CryptDecodeObjectEx(CRYPT_ENCODING_FLAGS dwCertEncodingType, IntPtr lpszStructType, byte[] pbEncoded, UInt32 cbEncoded, CRYPT_DECODE_FLAGS dwFlags, IntPtr pDecodePara, ref byte[] pvStructInfo, ref UInt32 pcbStructInfo);

        /// <summary>Function from Crypto API.</summary>
        [DllImport("crypt32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool CryptDecodeObject(CRYPT_ENCODING_FLAGS dwCertEncodingType, IntPtr lpszStructType, byte[] pbEncoded, UInt32 cbEncoded, CRYPT_DECODE_FLAGS flags, [In, Out] byte[] pvStructInfo, ref UInt32 cbStructInfo);

        #endregion P/Invoke Functions
    }
}

然後是加密、解密封裝類

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Org.BouncyCastle;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.Utilities.Collections;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Crypto.Encodings;

namespace TAPI.Common
{

    /// <summary>
    /// RSA簽名工具類。
    /// </summary>
    public class RSAUtil
    {

        /// <summary>
        /// java公鑰轉C#所需公鑰
        /// </summary>
        /// <param name="publicKey"></param>
        /// <returns></returns>
        public static string RSAPublicKeyJava2DotNet(string publicKey)
        {
            RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey));
            return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
                Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),
                Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));
        }

        public static string RSAEncryptMore(string xmlPublicKey, string m_strEncryptString)
        {
            if (string.IsNullOrEmpty(m_strEncryptString))
            {
                return string.Empty;
            }

            if (string.IsNullOrEmpty(xmlPublicKey))
            {
                throw new ArgumentException("Invalid Public Key");
            }

            using (var rsaProvider = new RSACryptoServiceProvider())
            {
                var inputBytes = Encoding.UTF8.GetBytes(m_strEncryptString);//有含義的字串轉化為位元組流
                rsaProvider.FromXmlString(xmlPublicKey);//載入公鑰
                int bufferSize = (rsaProvider.KeySize / 8) - 11;//單塊最大長度
                var buffer = new byte[bufferSize];
                using (MemoryStream inputStream = new MemoryStream(inputBytes),
                     outputStream = new MemoryStream())
                {
                    while (true)
                    { //分段加密
                        int readSize = inputStream.Read(buffer, 0, bufferSize);
                        if (readSize <= 0)
                        {
                            break;
                        }

                        var temp = new byte[readSize];
                        Array.Copy(buffer, 0, temp, 0, readSize);
                        var encryptedBytes = rsaProvider.Encrypt(temp, false);
                        outputStream.Write(encryptedBytes, 0, encryptedBytes.Length);
                    }
                    return Convert.ToBase64String(outputStream.ToArray());//轉化為位元組流方便傳輸
                }
            }
        }





        #region  加密  
        /// <summary>  
        /// RSA加密  
        /// </summary>  
        /// <param name="publicKeyJava"></param>  
        /// <param name="data"></param>  
        /// <returns></returns>  
        public static string EncryptJava(string publicKeyJava, string data, string encoding = "UTF-8")
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            //byte[] cipherbytes;
            rsa.FromPublicKeyJavaString(publicKeyJava);

            //☆☆☆☆.NET 4.6以後特有☆☆☆☆  
            //HashAlgorithmName hashName = new System.Security.Cryptography.HashAlgorithmName(hashAlgorithm);  
            //RSAEncryptionPadding padding = RSAEncryptionPadding.OaepSHA512;//RSAEncryptionPadding.CreateOaep(hashName);//.NET 4.6以後特有                 
            //cipherbytes = rsa.Encrypt(Encoding.GetEncoding(encoding).GetBytes(data), padding);  
            //☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆  

            //☆☆☆☆.NET 4.6以前請用此段程式碼☆☆☆☆  
            //cipherbytes = rsa.Encrypt(Encoding.GetEncoding(encoding).GetBytes(data), false);

            using (var rsaProvider = new RSACryptoServiceProvider())
            {
                var inputBytes = Encoding.UTF8.GetBytes(data);//有含義的字串轉化為位元組流                              
                int bufferSize = (rsa.KeySize / 8) - 11;//單塊最大長度
                var buffer = new byte[bufferSize];
                using (MemoryStream inputStream = new MemoryStream(inputBytes),
                     outputStream = new MemoryStream())
                {
                    while (true)
                    { //分段加密
                        int readSize = inputStream.Read(buffer, 0, bufferSize);
                        if (readSize <= 0)
                        {
                            break;
                        }

                        var temp = new byte[readSize];
                        Array.Copy(buffer, 0, temp, 0, readSize);
                        var encryptedBytes = rsaProvider.Encrypt(temp, false);
                        outputStream.Write(encryptedBytes, 0, encryptedBytes.Length);
                    }
                    return Convert.ToBase64String(outputStream.ToArray());//轉化為位元組流方便傳輸
                }
            }         
        }
        /// <summary>  
        /// RSA加密  
        /// </summary>  
        /// <param name="publicKeyCSharp"></param>  
        /// <param name="data"></param>  
        /// <returns></returns>  
        public static string EncryptCSharp(string publicKeyCSharp, string data, string encoding = "UTF-8")
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            byte[] cipherbytes;
            rsa.FromXmlString(publicKeyCSharp);

            //☆☆☆☆.NET 4.6以後特有☆☆☆☆  
            //HashAlgorithmName hashName = new System.Security.Cryptography.HashAlgorithmName(hashAlgorithm);  
            //RSAEncryptionPadding padding = RSAEncryptionPadding.OaepSHA512;//RSAEncryptionPadding.CreateOaep(hashName);//.NET 4.6以後特有                 
            //cipherbytes = rsa.Encrypt(Encoding.GetEncoding(encoding).GetBytes(data), padding);  
            //☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆  

            //☆☆☆☆.NET 4.6以前請用此段程式碼☆☆☆☆  
            cipherbytes = rsa.Encrypt(Encoding.GetEncoding(encoding).GetBytes(data), false);

            return Convert.ToBase64String(cipherbytes);
        }

        /// <summary>  
        /// RSA加密PEM祕鑰  
        /// </summary>  
        /// <param name="publicKeyPEM"></param>  
        /// <param name="data"></param>  
        /// <returns></returns>  
        public static string EncryptPEM(string publicKeyPEM, string data, string encoding = "UTF-8")
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            byte[] cipherbytes;
            rsa.LoadPublicKeyPEM(publicKeyPEM);

            //☆☆☆☆.NET 4.6以後特有☆☆☆☆  
            //HashAlgorithmName hashName = new System.Security.Cryptography.HashAlgorithmName(hashAlgorithm);  
            //RSAEncryptionPadding padding = RSAEncryptionPadding.OaepSHA512;//RSAEncryptionPadding.CreateOaep(hashName);//.NET 4.6以後特有                 
            //cipherbytes = rsa.Encrypt(Encoding.GetEncoding(encoding).GetBytes(data), padding);  
            //☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆  

            //☆☆☆☆.NET 4.6以前請用此段程式碼☆☆☆☆  
            cipherbytes = rsa.Encrypt(Encoding.GetEncoding(encoding).GetBytes(data), false);

            return Convert.ToBase64String(cipherbytes);
        }
        #endregion

        /// <summary>
        /// 解密公鑰
        /// </summary>
        /// <param name="s"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        /// <summary>
        /// 解密公鑰
        /// </summary>
        /// <param name="s"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string DecryptByPublicKey(string s, string key)
        {
            s = s.Replace("\r", "").Replace("\n", "").Replace(" ", "");
            //非對稱加密演算法,加解密用  
            IAsymmetricBlockCipher engine = new Pkcs1Encoding(new RsaEngine());
            //解密  
            try
            {
                engine.Init(false, GetPublicKeyParameter(key));
                byte[] byteData = Convert.FromBase64String(s);
                var ResultData = engine.ProcessBlock(byteData, 0, byteData.Length);
                return System.Text.Encoding.UTF8.GetString(ResultData);
            }
            catch (Exception ex)
            {
                return ex.Message;

            }
        }

        //#region 私有屬性
        ////private RSAParameters RSAKeyInfo;
        //private static RSACryptoServiceProvider RSA = null;
        ////私鑰
        //private const string NET_PRIVATE_KEY = @"<RSAKeyValue><Modulus>ndSLc+4nW6DJbZKjs+UrQynUjxca1IPOIyfcZxPB7lpEQFUJWwpN+hDabWdVeFldNhaNSFg1UlQz4N2wPR030ui62ayyD66yEm0KCvAUOfw0fVhiEf/5CmoLSz+co6fAYvCf5GymwB0fjziiIorNvmZiAJyBNrm4JLbbvsoNDIU=</Modulus><Exponent>AQAB</Exponent><P>zS4nps270U327EPDQjcCQVQXSnOQILtJyiH8V0QoImQpT6a1dhFwLfe/bl/3L7nBr3PLk9nkPMtUdwXnZ6lrcQ==</P><Q>xOwSJfUODzVETrMc2D2947krqcR+XYubvPIsiDyeYqqMFQMYA+ONZKoExn3o1tb1ORvunTApH2d/f5qq6aJgVQ==</Q><DP>vwHio+QOnrDn19bVZUT0coCoFgUy/WWdMfElis/GVQ3Nb3sQntNpDUIAEe6AnQtehclUkVVcpkPbY9o5LEWJ4Q==</DP><DQ>JB0zOtjVSj63l0NL7/Bqyb+k3U6W6ir3VdCIEDglx+yFIjleByCNRr/Tfl+K+xOTB3Uy7ortj7/YZxuDarOHvQ==</DQ><InverseQ>Ueugp68z1cKJXLXSFz/LRJNd+uh4vVOBt6ndBtmJ+H4gI0JgBoL8QmR5X1iiD7v9LD+5cJng5k4uriil6cAeFw==</InverseQ><D>InIDqV59inrR2y8YuSc3xOW5NS1mtqC5eWS2rmxac8mRgbTNYOgj0oKhGSVnOufN9wL+/J37rSchV18qmnvo9bABSEMYNlTkViTgmAWdU3sIXa8EmFVS6sf6Ba+SBTYQLv8PyzxWXU3aXFdLGvU/WIY2QRYtIIL/mHsLrw3/p0E=</D></RSAKeyValue>";
        ////公鑰引數
        //private const string PUB_KEY_MODULES = @"1lpnLvumD8/NedJ7s4WS8UO9OORbXVTgJXmfa72bI4A1L1l6Np91BETQ+yB8Fq6iGWw5OR8OB2UbRBcopb2etepDqWd7kmCtbVT36kTW+E8dWdaVjbI2BCXEGaXuzPPdGOlp52OaawYR5zyG0MiCvJ4jE7RDJax4Cl24ZqPUs4U=";
        ////公鑰引數
        //private const string PUB_KEY_EXP = @"AQAB";
        //public RSAUtil()
        //{
        //}
        //#endregion
        //#region 私有方法
        ////取大頭的資料
        //private static ushort readBEUInt16(BinaryReader br)
        //{
        //    byte[] b = br.ReadBytes(2);
        //    byte[] rb = new byte[2];
        //    rb[0] = b[1];
        //    rb[1] = b[0];
        //    return BitConverter.ToUInt16(rb, 0);
        //}
        //private static bool equalBytes(byte[] first, byte[] second)
        //{
        //    try
        //    {
        //        if (first.Length != second.Length)
        //        {
        //            return false;
        //        }
        //        for (int i = 0; i < first.Length; i++)
        //        {
        //            if (first[i] != second[i])
        //            {
        //                return false;
        //            }
        //        }
        //        return true;
        //    }
        //    catch (Exception e)
        //    {
        //        Console.WriteLine(e.Message);
        //        return false;
        //    }
        //}
        //private static int getHead(BinaryReader br, byte elementFlag)
        //{
        //    try
        //    {
        //        int count = 0;
        //        byte bt = 0;
        //        bt = br.ReadByte();
        //        if (elementFlag != 0x00 && bt != elementFlag)
        //        {
        //            throw (new Exception("pem format err,element head : " + bt + " != " + elementFlag));
        //        }
        //        count = getElementLen(br);
        //        return count;
        //    }
        //    catch (Exception e)
        //    {
        //        Console.WriteLine(e.Message);
        //        return -1;
        //    }
        //}
        //private static int getElementLen(BinaryReader br)
        //{
        //    try
        //    {
        //        ushort count = 0;
        //        byte bt = 0;
        //        bt = br.ReadByte();
        //        if (bt == 0x81)
        //        {
        //            count = br.ReadByte();
        //        }
        //        else if (bt == 0x82)
        //        {
        //            count = readBEUInt16(br); ;
        //        }
        //        else
        //        {
        //            count = bt;
        //        }
        //        return (int)count;
        //    }
        //    catch (Exception e)
        //    {
        //        Console.WriteLine(e.Message);
        //        return -1;
        //    }
        //}
        //private static byte[] loadBytesFromPemFile(String fileName)
        //{
        //    StringBuilder sb = new StringBuilder();
        //    using (StreamReader sr = new StreamReader(fileName))
        //    {
        //        String line;
        //        do
        //        {
        //            line = sr.ReadLine();
        //        } while (line != null && (line.Length == 0 || line.Substring(0, 1) != "-"));
        //        do
        //        {
        //            line = sr.ReadLine();
        //        } while (line != null && (line.Length == 0 || line.Substring(0, 1) == "-"));
        //        while (line != null && (line.Length == 0 || line.Substring(0, 1) != "-"))
        //        {
        //            sb.Append(line);
        //            line = sr.ReadLine();
        //        }
        //    }
        //    //Response.Write("base64:" + sb.ToString() + "<br>\n");
        //    return Convert.FromBase64String(sb.ToString());
        //}
        //private static byte[] stripLeftZeros(byte[] a)
        //{
        //    int lastZero = -1;
        //    for (int i = 0; i < a.Length; i++)
        //    {
        //        if (a[i] == 0)
        //        {
        //            lastZero = i;
        //        }
        //        else
        //        {
        //            break;
        //        }
        //    }
        //    lastZero++;
        //    byte[] result = new byte[a.Length - lastZero];
        //    Array.Copy(a, lastZero, result, 0, result.Length);
        //    return result;
        //}
        //private static byte[] getElement(BinaryReader br, byte elementFlag)
        //{
        //    try
        //    {
        //        int count = 0;
        //        byte bt = 0;
        //        bt = br.ReadByte();
        //        if (elementFlag != 0x00 && bt != elementFlag)
        //        {
        //            throw (new Exception("pem format err,element head : " + bt + " != " + elementFlag));
        //        }
        //        count = getElementLen(br);
        //        byte[] value = stripLeftZeros(br.ReadBytes(count));
        //        return value;
        //    }
        //    catch (Exception e)
        //    {
        //        Console.WriteLine(e.Message);
        //        return null;
        //    }
        //}
        //#endregion
        //#region 公有方法
        ///// <summary>
        ///// 通過私key檔案 獲取RSAParameters
        ///// </summary>
        ///// <param name="fileName"></param>
        ///// <returns></returns>
        //public static RSAParameters getPrivateKeyFromPem(String fileName)
        //{
        //    byte[] keyBytes = loadBytesFromPemFile(fileName);
        //    RSAParameters para = new RSAParameters();
        //    BinaryReader br = new BinaryReader(new MemoryStream(keyBytes));
        //    byte bt = 0;
        //    ushort twoBytes = 0;
        //    twoBytes = readBEUInt16(br);
        //    if (twoBytes == 0x3081)
        //    {
        //        br.ReadByte();
        //    }
        //    else if (twoBytes == 0x3082)
        //    {
        //        br.ReadInt16();
        //    }
        //    else
        //    {
        //        throw (new Exception("pem format err,head 1: " + twoBytes + " != 0x3081 or 0x3082," + 0x3082));
        //    }
        //    twoBytes = readBEUInt16(br);
        //    bt = br.ReadByte();
        //    if (twoBytes != 0x0201 || bt != 0x00)
        //    {
        //        throw (new Exception("pem format err,head 2: " + twoBytes + " != 0x0201 or " + bt + " != 0x00"));
        //    }
        //    para.Modulus = getElement(br, 0x02);
        //    para.Exponent = getElement(br, 0x02);
        //    para.D = getElement(br, 0x02);
        //    para.P = getElement(br, 0x02);
        //    para.Q = getElement(br, 0x02);
        //    para.DP = getElement(br, 0x02);
        //    para.DQ = getElement(br, 0x02);
        //    para.InverseQ = getElement(br, 0x02);
        //    if (para.Equals(""))
        //    {
        //        throw (new Exception("pem format err,para=null!"));
        //    }
        //    return para;
        //}
        ///// <summary>
        ///// 通過公key檔案 獲取RSAParameters
        ///// </summary>
        ///// <param name="fileName"></param>
        ///// <returns></returns>
        //public static RSAParameters getPublicKeyFromPem(String fileName)
        //{
        //    byte[] keyBytes = loadBytesFromPemFile(fileName);
        //    RSAParameters para = new RSAParameters();
        //    BinaryReader br = new BinaryReader(new MemoryStream(keyBytes));
        //    byte bt = 0;
        //    ushort twoBytes = 0;
        //    //兩個30開頭的Sequence
        //    getHead(br, 0x30);
        //    getHead(br, 0x30);
        //    //{ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 }
        //    byte[] correctOid = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
        //    byte[] oid = getElement(br, 0x06);
        //    if (!equalBytes(correctOid, oid))
        //    {
        //        throw (new Exception("pem format err,oid err"));
        //    }
        //    bt = br.ReadByte();
        //    //05 00
        //    if (bt == 0x05)
        //    {
        //        br.ReadByte();
        //    }
        //    else
        //    {
        //        //已經獲取了一個位元組,只能呼叫兩個函式組合,不能用getElement
        //        int len = getElementLen(br);
        //        br.ReadBytes(len);
        //    }
        //    //03開頭的BitString,03+len+00
        //    getHead(br, 0x03);
        //    br.ReadByte();
        //    //30開頭的Sequence
        //    getHead(br, 0x30);
        //    para.Modulus = getElement(br, 0x02);
        //    para.Exponent = getElement(br, 0x02);
        //    if (para.Equals(""))
        //    {
        //        throw (new Exception("pem format err,para=null!"));
        //    }
        //    return para;
        //}
        //public static bool verifySignature(byte[] signature, string signedData, RSAParameters pubPara)
        //{
        //    try
        //    {
        //        RSA = new RSACryptoServiceProvider();
        //        RSAParameters RSAParams = RSA.ExportParameters(false);
        //        RSACryptoServiceProvider RSA2 = new RSACryptoServiceProvider();
        //        //RSA2.ImportParameters(priPara)
        //        RSA2.ImportParameters(pubPara);
        //        byte[] hash = Encoding.UTF8.GetBytes(signedData);
        //        if (RSA2.VerifyData(hash, "SHA1", signature))
        //        {
        //            return true;
        //        }
        //        else
        //        {
        //            return false;
        //        }
        //    }
        //    catch (Exception e)
        //    {
        //        Console.WriteLine(e.Message);
        //        return false;
        //    }
        //}
        ///// <summary>
        ///// 驗證簽名資料
        ///// </summary>
        ///// <param name="signature">祕鑰</param>
        ///// <param name="signedData">明文</param>
        ///// <param name="pubFileName">公鑰檔案</param>
        ///// <returns></returns>
        //public static bool verifySignature(string signature, string signedData, string pubFileName)
        //{
        //    RSAParameters pubPara;
        //    pubPara = getPublicKeyFromPem(pubFileName);
        //    byte[] sign = Convert.FromBase64String(signature);
        //    //Convert.FromBase64String(signature);
        //    return verifySignature(sign, signedData, pubPara);
        //}
        ///// <summary>
        ///// 資料簽名
        ///// </summary>
        ///// <param name="dataToBeSigned">需要加密的字串</param>
        ///// <param name="priFileName">私鑰檔案</param>
        ///// <returns></returns>
        //public static string signData(string dataToBeSigned, string priFileName)
        //{
        //    RSAParameters priPara;
        //    priPara = getPrivateKeyFromPem(priFileName);
        //    RSA = new RSACryptoServiceProvider();
        //    //RSA.FromXmlString(NET_PRIVATE_KEY);
        //    RSAParameters RSAParams = RSA.ExportParameters(false);
        //    RSACryptoServiceProvider RSA2 = new RSACryptoServiceProvider();
        //    RSA2.ImportParameters(priPara);
        //    byte[] data = Encoding.UTF8.GetBytes(dataToBeSigned);
        //    byte[] endata = RSA2.SignData(data, "SHA1");
        //    return Convert.ToBase64String(endata);
        //}
        ///// <summary>
        ///// 資料加密
        ///// </summary>
        ///// <param name="dataSigned"></param>
        ///// <param name="pubFileName"></param>
        ///// <returns></returns>
        //public static string RSAEncrypt(string dataSign, string publicFileName)
        //{
        //    RSAParameters priPara;
        //    string hyxfmes = "";
        //    priPara = getPublicKeyFromPem(publicFileName);
        //    try
        //    {
        //        RSA = new RSACryptoServiceProvider();
        //        RSAParameters RSAParams = RSA.ExportParameters(false);
        //        RSACryptoServiceProvider RSA2 = new RSACryptoServiceProvider();
        //        RSA2.ImportParameters(priPara);
        //        byte[] hash = Encoding.UTF8.GetBytes(dataSign);
        //        byte[] de = RSA2.Encrypt(hash, false);
        //        hyxfmes = Convert.ToBase64String(de, Base64FormattingOptions.None);
        //        return hyxfmes;
        //    }
        //    catch (Exception e)
        //    {
        //        return "資料加密失敗!";
        //    }
        //}
        ///// <summary>
        ///// 資料解密
        ///// </summary>
        ///// <param name="dataSigned"></param>
        ///// <param name="pubFileName"></param>
        ///// <returns></returns>
        //public static string RSADecrypt(string dataSigned, string privateFileName)
        //{
        //    RSAParameters pubPara;
        //    pubPara = getPrivateKeyFromPem(privateFileName);
        //    try
        //    {
        //        RSA = new RSACryptoServiceProvider();
        //        RSAParameters RSAParams = RSA.ExportParameters(false);
        //        RSACryptoServiceProvider RSA2 = new RSACryptoServiceProvider();
        //        RSA2.ImportParameters(pubPara);
        //        byte[] hash = Convert.FromBase64String(dataSigned);
        //        byte[] de = RSA2.Decrypt(hash, false);
        //        return Encoding.UTF8.GetString(de);
        //    }
        //    catch (Exception e)
        //    {
        //        return e.ToString();
        //    }
        //}
        //#endregion
        /// <summary>
        /// 獲取公鑰
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        private static AsymmetricKeyParameter GetPublicKeyParameter(string s)
        {
            s = s.Replace("\r", "").Replace("\n", "").Replace(" ", "");
            byte[] publicInfoByte = Convert.FromBase64String(s);
            Asn1Object pubKeyObj = Asn1Object.FromByteArray(publicInfoByte);//這裡也可以從流中讀取,從本地匯入
            AsymmetricKeyParameter pubKey = PublicKeyFactory.CreateKey(publicInfoByte);
            return pubKey;
        }


    }
}

使用方式:

/***加密**/

publickey = RSAUtil.RSAPublicKeyJava2DotNet(publickey);
log.Trace("加密前的值" + m_SignDataStr);
string sign = RSAUtil.RSAEncryptMore(publickey, m_SignDataStr);
log.Trace("加密後的值:" + sign);

/****解密****/

RSAForJava rsa = new RSAForJava();
string data = RSAUtil.DecryptByPublicKey(response.pl_sign, publickey);

相關文章