C# RSA加密、解密、加签、验签、支持JAVA格式公钥私钥、PEM格式公钥私钥、.NET格式公钥私钥、一般模式【支持公钥加密,私钥解密】(一)

2019-02-26日更新:源码更新至github上。

2017-12-04日更新:增加支持微信支付。代码注释中//☆☆☆☆.NET 4.6以后特有☆☆☆☆的别用,那个不对。

RSA非对称加密。简明扼要吧,直说干货。(在此特别感谢下貳进制,提供JAVA版的公钥私钥)

C#RSA加签解签加密比较常见,一般遇到的问题是非.NET代码的加签验签、加密解密。以下就是解决此类问题的。

一般情况下是【公钥加密,私钥解密。】

有些变态喜欢乱搞,【私钥加密,公钥解密。】,详见这里:http://blog.csdn.net/gzy11/article/details/58609719

1、RSA 具体是什么请点击这里

     * 重要的事情说三遍,不懂的自己恶补去。
     * RSA加密解密:私钥解密,公钥加密。
     * RSA数字签名-俗称加签验签:私钥加签,公钥验签。 
     * RSA加密解密:私钥解密,公钥加密。
     * RSA数字签名-俗称加签验签:私钥加签,公钥验签。 
     * RSA加密解密:私钥解密,公钥加密。
     * RSA数字签名-俗称加签验签:私钥加签,公钥验签。 

 

关于hashAlgorithm参数值有:MD5、SHA1、SHA256、SHA384、SHA512。其它的自己试吧,可能这个不全。

具体java与C#对应的参见这里(仅供参考,详见测试代码部分):http://blog.csdn.net/gzy11/article/details/58609719

在这里提醒下各位对接其他它非.NET对接时注意事项吧。下面是自己总结的一些方法。

【注意简单的地方,越是简单的地方越容易阴沟里翻船】。

1、首先测试的时候,先给对方提供一整套公私钥,或者问对方要一套,以便方便自己和对方测试使用。因为跟你对接的兄弟多半跟你不在一个频道上,你说的他不明白。他也不明白你说的。

2、对方是否使用safeurl,请问清楚。如没有请忽略以下代码。

 

        public static string ConvertEncodeBase64URLSafe(string data)
        {
            return data.Replace("=", String.Empty).Replace('+', '-').Replace('/', '_');
        }
        public static string ConvertDecodeBase64URLSafe(string data)
        {
            data = data.Replace('-', '+').Replace('_', '/');
            int len = data.Length % 4;
            if (len > 0)
            {
                data += "====".Substring(0, 4 - len);
            }
            return data;
        }

 

 

 

 

3、对方是否使用MD5withRas。请看加签、验签。

C# RSA加密、解密、加签、验签、支持JAVA格式公钥私钥、PEM格式公钥私钥、.NET格式公钥私钥、一般模式【支持公钥加密,私钥解密】(一)_第1张图片

4、一些单元测试及使用方法,都在

C# RSA加密、解密、加签、验签、支持JAVA格式公钥私钥、PEM格式公钥私钥、.NET格式公钥私钥、一般模式【支持公钥加密,私钥解密】(一)_第2张图片

5、rsa.KeySize / 8-11是可加密的长度,RSA是本意是加密部分及其重要的数据,如果超过,多半是你自己的设计有问题。请改进,网上有分段加密解密超长数据的方法。不建议采用,改进自己的设计去。

6、【注意双方的编码格式。】

      【注意双方的编码格式。】

      【注意双方的编码格式。】

7、【注意本文的加密、加签结果都是Base64的。】

      【注意本文的加密、加签结果都是Base64的。】

      【注意本文的加密、加签结果都是Base64的。】

 

byte[] dataBytes = Convert.FromBase64String(data);
string base64Str = Convert.ToBase64String(signer.GenerateSignature());

 

 

 

8、对方是个变态,使用【私钥加密、公钥解密】。详见这里:http://blog.csdn.net/gzy11/article/details/58609719

9、注意加签验签Algorithm参数。详见这里:http://blog.csdn.net/gzy11/article/details/58609719 C#与JAVA对应的关系,暂无。

10、JAVA 使用PEM的为PKCS8,转换命令如下

PKCS8转换为普通的PKCS1,本示列使用普通PEM私钥

openssl pkcs8 -in private_key_pkcs8.pem -nocrypt -out private_key.pem

11、微信RSA支付。必须使用.NET4.6以上版本 。

使用如下代码。

https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_7&index=4

 

public static string DecryptPEMByWeiXin(string privateKeyPEM, string data, string encoding = "UTF-8")
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            byte[] cipherbytes;
            rsa.LoadPrivateKeyPEM(privateKeyPEM);
            var padding = System.Security.Cryptography.RSAEncryptionPadding.Pkcs1;
            cipherbytes = rsa.Decrypt(Convert.FromBase64String(data), padding);
          
            return Encoding.GetEncoding(encoding).GetString(cipherbytes);
        }
 

 

以下是RSA的帮助类:

加签:

 

        #region 加签

        /// 
        /// RSA签名
        /// 
        /// 私钥
        /// 待签名的内容
        /// 
        public static string RSASignJava(string data, string privateKeyJava, string hashAlgorithm = "MD5", string encoding = "UTF-8")
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.FromPrivateKeyJavaString(privateKeyJava);//加载私钥
            //RSAPKCS1SignatureFormatter RSAFormatter = new RSAPKCS1SignatureFormatter(rsa);
            ////设置签名的算法为MD5 MD5withRSA 签名
            //RSAFormatter.SetHashAlgorithm(hashAlgorithm);


            var dataBytes = Encoding.GetEncoding(encoding).GetBytes(data);
            var HashbyteSignature = rsa.SignData(dataBytes, hashAlgorithm);
            return Convert.ToBase64String(HashbyteSignature);

            //byte[] HashbyteSignature = ConvertToRgbHash(data, encoding);

            //byte[] dataBytes =Encoding.GetEncoding(encoding).GetBytes(data);
            //HashbyteSignature = rsa.SignData(dataBytes, hashAlgorithm);
            //return Convert.ToBase64String(HashbyteSignature);
            //执行签名 
            //EncryptedSignatureData = RSAFormatter.CreateSignature(HashbyteSignature);
            //return Convert.ToBase64String(RSAFormatter.CreateSignature(HashbyteSignature));
            //return result.Replace("=", String.Empty).Replace('+', '-').Replace('/', '_');
        }
        /// 
        /// RSA签名
        /// 
        /// 私钥
        /// 待签名的内容
        /// 
        public static string RSASignPEM(string data, string privateKeyPEM, string hashAlgorithm = "MD5", string encoding = "UTF-8")
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.LoadPrivateKeyPEM(privateKeyPEM);//加载私钥   
            var dataBytes = Encoding.GetEncoding(encoding).GetBytes(data);
            var HashbyteSignature = rsa.SignData(dataBytes, hashAlgorithm);
            return Convert.ToBase64String(HashbyteSignature);
        }
        /// 
        /// RSA签名CSharp
        /// 
        /// 私钥
        /// 待签名的内容
        /// 
        public static string RSASignCSharp(string data, string privateKeyCSharp, string hashAlgorithm = "MD5", string encoding = "UTF-8")
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.FromXmlString(privateKeyCSharp);//加载私钥   
            var dataBytes = Encoding.GetEncoding(encoding).GetBytes(data);
            var HashbyteSignature = rsa.SignData(dataBytes, hashAlgorithm);
            return Convert.ToBase64String(HashbyteSignature);
        }

        #endregion

 

 

 

验签:

 

       #region 验签

        ///  
        /// 验证签名-方法一
        /// 
        /// 
        /// 
        /// 
        /// 
        public static bool VerifyJava(string data, string publicKeyJava, string signature, string hashAlgorithm = "MD5", string encoding = "UTF-8")
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            //导入公钥,准备验证签名
            rsa.FromPublicKeyJavaString(publicKeyJava);
            //返回数据验证结果
            byte[] Data = Encoding.GetEncoding(encoding).GetBytes(data);
            byte[] rgbSignature = Convert.FromBase64String(signature);

            return rsa.VerifyData(Data, hashAlgorithm, rgbSignature);

            //return SignatureDeformatter(publicKeyJava, data, signature);

            //return CheckSign(publicKeyJava, data, signature);

            //return rsa.VerifyData(Encoding.GetEncoding(encoding).GetBytes(data), "MD5", Encoding.GetEncoding(encoding).GetBytes(signature));
        }
        ///  
        /// 验证签名PEM
        /// 
        /// 
        /// 
        /// 
        /// 
        public static bool VerifyPEM(string data, string publicKeyPEM, string signature, string hashAlgorithm = "MD5", string encoding = "UTF-8")
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            //导入公钥,准备验证签名
            rsa.LoadPublicKeyPEM(publicKeyPEM);
            //返回数据验证结果
            byte[] Data = Encoding.GetEncoding(encoding).GetBytes(data);
            byte[] rgbSignature = Convert.FromBase64String(signature);

            return rsa.VerifyData(Data, hashAlgorithm, rgbSignature);
        }

        ///  
        /// 验证签名CSharp
        /// 
        /// 
        /// 
        /// 
        /// 
        public static bool VerifyCSharp(string data, string publicKeyCSharp, string signature, string hashAlgorithm = "MD5", string encoding = "UTF-8")
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            //导入公钥,准备验证签名
            rsa.LoadPublicKeyPEM(publicKeyCSharp);
            //返回数据验证结果
            byte[] Data = Encoding.GetEncoding(encoding).GetBytes(data);
            byte[] rgbSignature = Convert.FromBase64String(signature);

            return rsa.VerifyData(Data, hashAlgorithm, rgbSignature);
        }

        #region 签名验证-方法二
        /// 
        /// 签名验证
        /// 
        /// 公钥
        /// 待验证的用户名
        /// 注册码
        /// 签名是否符合
        public static bool SignatureDeformatter(string publicKey, string data, string signature, string hashAlgorithm = "MD5")
        {
            try
            {
                byte[] rgbHash = ConvertToRgbHash(data);
                RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
                //导入公钥,准备验证签名
                rsa.FromPublicKeyJavaString(publicKey);

                RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(rsa);
                deformatter.SetHashAlgorithm("MD5");
                byte[] rgbSignature = Convert.FromBase64String(signature);
                if (deformatter.VerifySignature(rgbHash, rgbSignature))
                {
                    return true;
                }
                return false;
            }
            catch
            {
                return false;
            }
        }

        /// 
        /// 签名数据转化为RgbHash
        /// 
        /// 
        /// 
        /// 
        public static byte[] ConvertToRgbHash(string data, string encoding = "UTF-8")
        {
            using (MD5 md5 = new MD5CryptoServiceProvider())
            {
                byte[] bytes_md5_in = Encoding.GetEncoding(encoding).GetBytes(data);
                return md5.ComputeHash(bytes_md5_in);
            }
        }
        #endregion

        #region 签名验证-方法三
        /// 
        /// 验证签名
        /// 
        /// 原始数据
        /// 签名
        /// 
        public static bool CheckSign(string publicKey, string data, string sign, string encoding = "UTF-8")
        {

            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.FromPublicKeyJavaString(publicKey);
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();

            byte[] Data = Encoding.GetEncoding(encoding).GetBytes(data);
            byte[] rgbSignature = Convert.FromBase64String(sign);
            if (rsa.VerifyData(Data, md5, rgbSignature))
            {
                return true;
            }
            return false;
        }
        #endregion
        #endregion

 

 

 

加密:

 

      #region  加密


        /// 
        /// RSA加密
        /// 
        /// 
        /// 
        /// 
        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);
           
            return Convert.ToBase64String(cipherbytes);
        }
        /// 
        /// RSA加密
        /// 
        /// 
        /// 
        /// 
        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);
        }

        /// 
        /// RSA加密PEM秘钥
        /// 
        /// 
        /// 
        /// 
        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

 

 

 

解密:

 

        #region 解密


        /// 
        /// RSA解密
        /// 
        /// 
        /// 
        /// 
        public static string DecryptJava(string privateKeyJava, string data, string encoding = "UTF-8")
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            byte[] cipherbytes;
            rsa.FromPrivateKeyJavaString(privateKeyJava);
            //☆☆☆☆.NET 4.6以后特有☆☆☆☆
            //RSAEncryptionPadding padding = RSAEncryptionPadding.CreateOaep(new System.Security.Cryptography.HashAlgorithmName(hashAlgorithm));//.NET 4.6以后特有        
            //cipherbytes = rsa.Decrypt(Encoding.GetEncoding(encoding).GetBytes(data), padding);
            //☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆

            //☆☆☆☆.NET 4.6以前请用此段代码☆☆☆☆
            cipherbytes = rsa.Decrypt(Convert.FromBase64String(data), false);

            return Encoding.GetEncoding(encoding).GetString(cipherbytes);
        }
        /// 
        /// RSA解密
        /// 
        /// 
        /// 
        /// 
        public static string DecryptCSharp(string privateKeyCSharp, string data, string encoding = "UTF-8")
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            byte[] cipherbytes;
            rsa.FromXmlString(privateKeyCSharp);
            //☆☆☆☆.NET 4.6以后特有☆☆☆☆
            //RSAEncryptionPadding padding = RSAEncryptionPadding.CreateOaep(new System.Security.Cryptography.HashAlgorithmName(hashAlgorithm));//.NET 4.6以后特有        
            //cipherbytes = rsa.Decrypt(Encoding.GetEncoding(encoding).GetBytes(data), padding);
            //☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆

            //☆☆☆☆.NET 4.6以前请用此段代码☆☆☆☆
            cipherbytes = rsa.Decrypt(Convert.FromBase64String(data), false);

            return Encoding.GetEncoding(encoding).GetString(cipherbytes);
        }
        /// 
        /// RSA解密
        /// 
        /// 
        /// 
        /// 
        public static string DecryptPEM(string privateKeyPEM, string data,  string encoding = "UTF-8")
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            byte[] cipherbytes;
            rsa.LoadPrivateKeyPEM(privateKeyPEM);
            //☆☆☆☆.NET 4.6以后特有☆☆☆☆
            //RSAEncryptionPadding padding = RSAEncryptionPadding.CreateOaep(new System.Security.Cryptography.HashAlgorithmName(hashAlgorithm));//.NET 4.6以后特有        
            //cipherbytes = rsa.Decrypt(Encoding.GetEncoding(encoding).GetBytes(data), padding);
            //☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆

            //☆☆☆☆.NET 4.6以前请用此段代码☆☆☆☆
            cipherbytes = rsa.Decrypt(Convert.FromBase64String(data), false);

            return Encoding.GetEncoding(encoding).GetString(cipherbytes);
        }
        #endregion

 

 

 

RSA扩展方法:

 

  public static class RSAExtensions
    {
        /// 
        ///  把java的私钥转换成.net的xml格式
        /// 
        /// 
        /// 
        /// 
        public static string ConvertToXmlPrivateKey(this RSA rsa, string privateJavaKey)
        {
            RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateJavaKey));
            string xmlPrivateKey = string.Format("{0}{1}

{2}

{3}{4}{5}{6}{7}
", 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; } /// /// RSA加载JAVA PrivateKey /// /// java提供的第三方私钥 /// public static void FromPrivateKeyJavaString(this RSA rsa, string privateJavaKey) { string xmlPrivateKey = rsa.ConvertToXmlPrivateKey(privateJavaKey); rsa.FromXmlString(xmlPrivateKey); } /// /// 把java的公钥转换成.net的xml格式 /// /// java提供的第三方公钥 /// public static string ConvertToXmlPublicJavaKey(this RSA rsa, string publicJavaKey) { RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicJavaKey)); string xmlpublicKey = string.Format("{0}{1}", Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()), Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned())); return xmlpublicKey; } /// /// 把java的私钥转换成.net的xml格式 /// /// java提供的第三方公钥 /// public static void FromPublicKeyJavaString(this RSA rsa, string publicJavaKey) { string xmlpublicKey = rsa.ConvertToXmlPublicJavaKey(publicJavaKey); rsa.FromXmlString(xmlpublicKey); } ///// ///// RSA公钥格式转换,java->.net ///// ///// java生成的公钥 ///// //private static string ConvertJavaPublicKeyToDotNet(this RSA rsa,string publicKey) //{ // RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey)); // return string.Format("{0}{1}", // Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()), // Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned())); //} /// Extension method for initializing a RSACryptoServiceProvider from PEM data string. #region Methods /// Extension method which initializes an RSACryptoServiceProvider from a DER public key blob. public static void LoadPublicKeyDER(this RSACryptoServiceProvider provider, byte[] DERData) { byte[] RSAData = GetRSAFromDER(DERData); byte[] publicKeyBlob = GetPublicKeyBlobFromRSA(RSAData); provider.ImportCspBlob(publicKeyBlob); } /// Extension method which initializes an RSACryptoServiceProvider from a DER private key blob. public static void LoadPrivateKeyDER(this RSACryptoServiceProvider provider, byte[] DERData) { byte[] privateKeyBlob = GetPrivateKeyDER(DERData); provider.ImportCspBlob(privateKeyBlob); } /// Extension method which initializes an RSACryptoServiceProvider from a PEM public key string. public static void LoadPublicKeyPEM(this RSACryptoServiceProvider provider, string sPEM) { byte[] DERData = GetDERFromPEM(sPEM); LoadPublicKeyDER(provider, DERData); } /// Extension method which initializes an RSACryptoServiceProvider from a PEM private key string. public static void LoadPrivateKeyPEM(this RSACryptoServiceProvider provider, string sPEM) { byte[] DERData = GetDERFromPEM(sPEM); LoadPrivateKeyDER(provider, DERData); } /// Returns a public key blob from an RSA public key. 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; } /// Converts DER binary format to a CAPI CRYPT_PRIVATE_KEY_INFO structure. 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; } /// Converts DER binary format to a CAPI CERT_PUBLIC_KEY_INFO structure containing an RSA key. 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; } /// Extracts the binary data from a PEM file. 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 /// Enumeration derived from Crypto API. 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 } /// Enumeration derived from Crypto API. internal enum CRYPT_PROVIDER_TYPE : uint { PROV_RSA_FULL = 1 } /// Enumeration derived from Crypto API. internal enum CRYPT_DECODE_FLAGS : uint { NONE = 0, CRYPT_DECODE_ALLOC_FLAG = 0x8000 } /// Enumeration derived from Crypto API. internal enum CRYPT_ENCODING_FLAGS : uint { PKCS_7_ASN_ENCODING = 0x00010000, X509_ASN_ENCODING = 0x00000001, } /// Enumeration derived from Crypto API. 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 } /// Enumeration derived from Crypto API. 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 /// Structure from Crypto API. [StructLayout(LayoutKind.Sequential)] internal struct CRYPT_OBJID_BLOB { internal UInt32 cbData; internal IntPtr pbData; } /// Structure from Crypto API. [StructLayout(LayoutKind.Sequential)] internal struct CRYPT_ALGORITHM_IDENTIFIER { internal IntPtr pszObjId; internal CRYPT_OBJID_BLOB Parameters; } /// Structure from Crypto API. [StructLayout(LayoutKind.Sequential)] struct CRYPT_BIT_BLOB { internal UInt32 cbData; internal IntPtr pbData; internal UInt32 cUnusedBits; } /// Structure from Crypto API. [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 /// Function for Crypto API. [DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool CryptDestroyKey(IntPtr hKey); /// Function for Crypto API. [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); /// Function for Crypto API. [DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool CryptReleaseContext(IntPtr hProv, Int32 dwFlags); /// Function for Crypto API. [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); /// Function from Crypto API. [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); /// Function from Crypto API. [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); /// Function from Crypto API. [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 }

 

 

 

单元测试:

   [TestClass]
    public class RSAHelperTest
    {
        string publicKeyJava = @"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkixtIe0MzCFDW3eCDSq/6SFFN+eK+zg1q62SX
TbJprt7zOD6D9A8zU1fTEzY9+0gVUYmOMPOF8jI8EMZOnl2jDUtn3KdD2Uuee3/cmEfMpAN++KMG
6Tfm3p3Iz4kw/dLmM1EAkADIp4zFmkvxd/BN+dmT/1Tp87mMUQBS8mvdRwIDAQAB";
        string privateKeyJava = @"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKSLG0h7QzMIUNbd4INKr/pIUU35
4r7ODWrrZJdNsmmu3vM4PoP0DzNTV9MTNj37SBVRiY4w84XyMjwQxk6eXaMNS2fcp0PZS557f9yY
R8ykA374owbpN+bencjPiTD90uYzUQCQAMinjMWaS/F38E352ZP/VOnzuYxRAFLya91HAgMBAAEC
gYBXJCSq2jzYhgrqAE+quJ9CGZKVjUV8b3vDqC55wvg96BLDFIJnN5XlRLo6Wu5bHP0r7SbAW0Rd
J8ta7DdZ450Kow+k2Z69gYO818cptQXYrs4ky6M48NXeSSoYeGESxW7LGJs++o2nGmVRkhj4DMYY
8lur1oYsyDAy/d3B0ucnwQJBAP0Kc2KCOl8xnbXUuoFhJHaVoKPWqdhody5sNHK+11Bgc3/ZhqNM
T1uIiiZnB3CTyfKeJAgX0fwde7fmtZHaUO8CQQCmd7a3qXvUbnQao03ITrthGRvGAJSAfTAG/VEx
2g1knxUmiq+bek+FGi7UYXYRZ/rVqX934ztTAOnBqVtnK4kpAkEAs6KAqVUkFUJG4LfFM2YAGcM9
SDJzXvNCcI1WaoM6nY/rTr7hCvp4d9WlpX+M04nHWtqTX79xTdasZrB9A68FtwJAHXWmIk6eGXQK
nAQ2abJ1OrPE1H+ZyDtfWn1N9zKNmDcG+TEl7q/wjq+ZhgBRcrciDtnWMxNFlmTc+WbNRC7SMQJB
AIBSE1kfhy3V63db91Gnr789G2QKy3TI46QEY3dirLiXWF3/tt+9K8itjeB22S5S7cWbzJ+2FIFW
mFB/DP3ER8Q=";

        string publicKeyPEM = @"-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDe8W+2jrrWY55W8nZcWCBXQSJJ
uJxkannRsZbwiwJBftXCzN0wSaujwmT0S0Aqttnqg/sO+jDHVnpph8omZdSvnySt
/PiGEqmsk+6AsgZ7eczeokVkrFvVbjq13s6NVF8tgMds/w5VG8+uEECmiHCKM8/V
3oXhq7aLPLINFYggcQIDAQAB
-----END PUBLIC KEY-----
";
        string privateKeyPEM = @"-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQDe8W+2jrrWY55W8nZcWCBXQSJJuJxkannRsZbwiwJBftXCzN0w
SaujwmT0S0Aqttnqg/sO+jDHVnpph8omZdSvnySt/PiGEqmsk+6AsgZ7eczeokVk
rFvVbjq13s6NVF8tgMds/w5VG8+uEECmiHCKM8/V3oXhq7aLPLINFYggcQIDAQAB
AoGAN9OnkMRe/u6FKOqgPvGGb7MMvf8vkmmjRaI91NBKaVI0fwpD3SKli2VTWGU7
lTaijPottQtriY8bKi/prAHV5wiSetsiPB9DQq8bN3rLtJPG6NCmwiOUhamBg9kD
VbqOb/1dg0vGL1zEKxtscaK5yDCBnyX+4LfAR5Upg0Q4t70CQQD8n5XxSdQpHNAf
sl26cTxf6YHCzHoqUfDo4SE74jWy8ooNF3qk0jaYy6+N1EOLwpMfm2MeWdxCYFmC
9NdbowIDAkEA4exKy9FGTPVkkVhAwva0fm7/mJSHsl7btPTJvmgEfO9eHbozYacQ
2PmbZd46uPzaI0LaDh8ICbaLvf8IPiVjewJAXIMUpggjaerjTLhFGsHdGkKpAm1f
T6AyWRYY1ZVBlQa9B45Rm4pf9BSjdY0GL2hR+IEvCy5dOvGN1idTtns7gQJAfiqO
TqptPxcfdYe6iuZpP95PAO+ZpEQTIEg/zgSa1QZ8Ic/VV+iLoRAr90SWuK4ESALS
cWZk/7+g5JbjDImmtwJAfBpGw+TVeMw+2Oo9GJnIM9Ga/hiYQDCkZ9A/4fYrNxxr
znkMqFQ28dhYQbKK9/WcPTjHGakpY/2hY/9dki6CJw==
-----END RSA PRIVATE KEY-----
";
        [TestMethod]
        public void RSA_Java_MD5Verify()
        {
            string data = "hello word!";
            string hashAlgorithm = "MD5";
            string signResult = RSAHelper.RSASignJava(data,privateKeyJava, hashAlgorithm);
            string sign1 = "bI/x8LHsuvCVgO7YEBA0hvQWdpLzqdThfYKYEeo4YFTclhFV+R4QCN2FgYshZqjDTBzHAvRHxoRk4kbYWeOuVNG+W3exdtqfUuUp29EgxEPFfqECUqucgN/bFxrtKtNGOCAqOBSx6SBkRpByKEAH7FHsRmPS4Bd4MUT4xr9gGg8=";
            if (sign1 == signResult)
            {

            }
            bool result = RSAHelper.VerifyJava(data, publicKeyJava, signResult, hashAlgorithm);
            if (!result)
            {
                int a = 0;
                int b = 0 / a;
            }
            Console.WriteLine(hashAlgorithm + ":" + result);
        }
        [TestMethod]
        public void RSA_Java_SHA1Verify()
        {
            //通过测试
            string data = "hello word!";
            string hashAlgorithm = "SHA1";
            string signResult = RSAHelper.RSASignJava(data,privateKeyJava, hashAlgorithm);
            bool result = RSAHelper.VerifyJava(data,publicKeyJava, signResult, hashAlgorithm);
            if (!result)
            {
                int a = 0;
                int b = 0 / a;
            }
            Console.WriteLine(hashAlgorithm + ":" + result);
        }

        [TestMethod]
        public void RSA_Java_SHA256Verify()
        {
            //未通过
            string data = "hello word!";
            string hashAlgorithm = "SHA256";
            string signResult = RSAHelper.RSASignJava(data,privateKeyJava, hashAlgorithm);
            bool result = RSAHelper.VerifyJava(data,publicKeyJava, signResult, hashAlgorithm);
            if (!result)
            {
                int a = 0;
                int b = 0 / a;
            }
            Console.WriteLine(hashAlgorithm + ":" + result);
        }
        [TestMethod]
        public void RSASign_JAVA_WithVerify()
        {
            string data = "hello word!";
            //"RIPEMD160",
            List hashAlgorithmList = new List() { "MD5", "SHA1", "SHA256", "SHA384", "SHA512" };//{MD5、RIPEMD160、SHA1、SHA256、SHA384、SHA512}
            foreach (var hashAlgorithm in hashAlgorithmList)
            {
                string signResult = RSAHelper.RSASignJava(data,privateKeyJava, hashAlgorithm);
                bool result = RSAHelper.VerifyJava(data,publicKeyJava, signResult, hashAlgorithm);
                if (!result)
                {
                    int a = 0;
                    int b = 0 / a;
                }
                Console.WriteLine(hashAlgorithm + ":" + result);
            }


        }
        [TestMethod]
        public void RSASign_PEM_WithVerify()
        {
            string data = "hello word!";
            //"RIPEMD160",
            List hashAlgorithmList = new List() { "MD5", "SHA1", "SHA256", "SHA384", "SHA512" };//{MD5、RIPEMD160、SHA1、SHA256、SHA384、SHA512}
            foreach (var hashAlgorithm in hashAlgorithmList)
            {
                string signResult = RSAHelper.RSASignPEM(data, privateKeyPEM, hashAlgorithm);
                bool result = RSAHelper.VerifyPEM(data, publicKeyPEM, signResult, hashAlgorithm);
                if (!result)
                {
                    int a = 0;
                    int b = 0 / a;
                }
                Console.WriteLine(hashAlgorithm + ":" + result);
            }


        }

        [TestMethod]
        public void RSA_Java_EncryptWithDecrypt()
        {

            string data = "hello word!";//"MD5",

            string encryptResult = RSAHelper.EncryptJava(publicKeyJava,data);
            string decryptResult = RSAHelper.DecryptJava(privateKeyJava,encryptResult);
            if (data != decryptResult)
            {
                int a = 0;
                int b = 0 / a;
            }


        }
        [TestMethod]
        public void RSA_PEM_EncryptWithDecrypt()
        {
            string data = "hello word!";//"MD5",

            string encryptResult = RSAHelper.EncryptPEM(publicKeyPEM,data);
            string decryptResult = RSAHelper.DecryptPEM(privateKeyPEM,encryptResult);
            if (data != decryptResult)
            {
                int a = 0;
                int b = 0 / a;
            }
        }
    }

测试结果:

C# RSA加密、解密、加签、验签、支持JAVA格式公钥私钥、PEM格式公钥私钥、.NET格式公钥私钥、一般模式【支持公钥加密,私钥解密】(一)_第3张图片

下载地址:

http://download.csdn.net/detail/gzy11/9738814

已上传 github 有需要的可自行下载

github下载地址:

https://github.com/winphone3721/WNSLP.Toolkits.RSA

CSDN下载不靠谱,不要积分的现在下的人多了积分要那么多,谁没事老去整积分啊。要源码的可以直接留言,留下邮箱,邮箱回复不及时,急需请自行GitHub下载。

你可能感兴趣的:(C#,ASP.NET)