php openssl_sign 对应 C#版 RSA签名

时间:2021-07-15
本文章向大家介绍php openssl_sign 对应 C#版 RSA签名,主要包括php openssl_sign 对应 C#版 RSA签名使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

 

RSA Key Converter 在线转换工具:https://superdry.apphb.com/tools/online-rsa-key-converter

PHP 代码:

/ rsa 私钥复制到这里

$private_key = <<<EOD

PASTE YOUR RSA PRIVATE KEY IN HERE

EOD;

 // 空着即可,不需要赋值

$binary_signature = "";

 $algo = "SHA256";

openssl_sign($data, $binary_signature, $private_key, $algo);

 // 最终生成的 signature

$signature = base64_encode($binary_signature)

C# 代码实现:

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


namespace User2MeiCan
{
   public class RSA
    {

        #region RSAWithSHA256

        /// <summary>
        /// RSAWithSHA256 签名
        /// </summary>
        /// <param name="data">数据</param>
        /// <returns>密文</returns>
        public static string Sign(string data)
        {
            //转换成适用于.Net的秘钥
            var netKey = "<RSAKeyValue><Modulus>7XdZSrF+spbABFhYuxP7rfJKycvT0O7BmCoSJvU7yHWYqucc8msPDTi8ymdZOPOjHj2BuLUrqGsUm8Ljy8FVM2Bb51GaO2lgiBip9elFkzOJ8XP/ncHHvm4XCq5S201ovJefNC0xOxsXJU4fM+4B6ufYr4WqBmyuxTcZVHweE0k=</Modulus><Exponent>AQAB</Exponent><P>9ryI0kxJL9PupO9NEeWuCUo4xcl9x/M9+mtkfY3VoDDDV1E/eUjmoTfANYwrjcddiQrO0MLyEdootiLpN77qOw==</P><Q>9mG2//6moxVOsvFadUotnhlVM8+AlBCQV2FbBiXPugrMHdVtBG3+MsVdTII3Z4I/uuCWtedrPsBgF+0XRqMcSw==</Q><DP>wzX5HkFC6jdIKXA3TsCkSC9T6ZB4FplpYNZUxE1SRhIuisf6ay/1YHomdXc4Ak1IwKMva9XBBcTPzwKh9/vxfw==</DP><DQ>zsTCp6Q2hLblDRewKq7OCdiIwKpr5dbgy/RQR6CD7EYTdxYeH5GPu1wXKJY/mQaeJV9GG/LS9h7MhkfbONS6cQ==</DQ><InverseQ>dBEb5vloBDLcSQFDQO/VZ9SKFHCmHLXluhhIizYKGzgf3OXEGNDSAC3qy+ZTnLd3N5iYrVbK52UoiLOLhhNMqA==</InverseQ><D>iBOTTHUn6EjwoczKk/GgkI4+gyLVL24R7BN3sXFoH7gbkxu6/8OPrYDs1oOgoj0jJSoT0vemm+04swVcKh+QpTSniPswQl1n4KNW+B7G2RZrzSeP9RmIzWg4vpgfAfhm0+1j6kUJMrWt2ff7TvSoEH22dWe1s3+OrQt3t/S3tQ0=</D></RSAKeyValue>"; //RSAPrivateKeyJava2DotNet(privateKey);
            var rsa = new RSACryptoServiceProvider();
            rsa.FromXmlString(netKey);
            //创建一个空对象
            var rsaClear = new RSACryptoServiceProvider();
            var paras = rsa.ExportParameters(true);
            rsaClear.ImportParameters(paras);
            //签名返回
            using (var sha256 = new SHA256CryptoServiceProvider())
            {
                var signData = rsa.SignData(Encoding.UTF8.GetBytes(data), sha256);
                return Convert.ToBase64String(signData);
            }
        }

        #endregion


        #region RSAWithSHA256
        /// <summary>
        /// RSAWithSHA256 签名
        /// </summary>
        /// <param name="data">数据</param>
        /// <param name="privateKeyPath">私钥文件路径</param>
        /// <returns>密文</returns>
        public static string Sign(string data, string privateKeyPath)
        {
            // using (RSACryptoServiceProvider rsa = opensslkey.DecodePrivateKeyInfo(merchantPrivateKey))
            RSACryptoServiceProvider rsaCsp = LoadCertificateFile(privateKeyPath);
            byte[] dataBytes = Encoding.Default.GetBytes(data);
            byte[] signatureBytes = rsaCsp.SignData(dataBytes, "SHA256");
            return Convert.ToBase64String(signatureBytes);
        }

        /// <summary>
        /// RSAWithSHA256 签名
        /// </summary>
        /// <param name="data">数据</param>
        /// <param name="privateKey">私钥字符串(参数privateKey是Pem私钥文件中去除头(-----BEGIN RSA PRIVATE KEY-----)和尾(-----END RSA PRIVATE KEY-----)以及换行符后的字符串)</param>
        /// <returns>密文</returns>
        public static string SignByKey(string data, string privateKey)
        {
            using (RSACryptoServiceProvider rsaCsp = DecodeRSAPrivateKey(Convert.FromBase64String(privateKey)))
            {
                byte[] dataBytes = Encoding.Default.GetBytes(data);
                byte[] signatureBytes = rsaCsp.SignData(dataBytes, "SHA256");
                return Convert.ToBase64String(signatureBytes);
            }
        }

        private static byte[] GetPem(string type, byte[] data)
        {

            string pem = Encoding.UTF8.GetString(data);
            string header = String.Format("-----BEGIN {0}-----\\n", type);
            string footer = String.Format("-----END {0}-----", type);
            int start = pem.IndexOf(header) + header.Length;
            int end = pem.IndexOf(footer, start);
            string base64 = pem.Substring(start, (end - start));
            return Convert.FromBase64String(base64);
        }
        private static RSACryptoServiceProvider LoadCertificateFile(string filename)
        {
            using (FileStream fs = File.OpenRead(filename))
            {
                byte[] data = new byte[fs.Length];
                byte[] res = null;
                fs.Read(data, 0, data.Length);
                if (data[0] != 0x30)
                {
                    res = GetPem("RSA PRIVATE KEY", data);
                }
                try
                {
                    RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(res);

                    return rsa;
                }
                catch (Exception ex)
                {
                }
                return null;
            }
        }

        private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
        {
            byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;

            // --------- Set up stream to decode the asn.1 encoded RSA private key ------
            MemoryStream mem = new MemoryStream(privkey);
            BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
            byte bt = 0;
            ushort twobytes = 0;
            int elems = 0;
            try
            {
                twobytes = binr.ReadUInt16();
                if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
                    binr.ReadByte(); //advance 1 byte
                else if (twobytes == 0x8230)
                    binr.ReadInt16(); //advance 2 bytes
                else
                    return null;

                twobytes = binr.ReadUInt16();
                if (twobytes != 0x0102) //version number
                    return null;
                bt = binr.ReadByte();
                if (bt != 0x00)
                    return null;


                //------ all private key components are Integer sequences ----
                elems = GetIntegerSize(binr);
                MODULUS = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                E = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                D = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                P = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                Q = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                DP = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                DQ = binr.ReadBytes(elems);

                elems = GetIntegerSize(binr);
                IQ = binr.ReadBytes(elems);


                // ------- create RSACryptoServiceProvider instance and initialize with public key -----
                CspParameters CspParameters = new CspParameters();
                CspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
                RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(1024, CspParameters);
                RSAParameters RSAparams = new RSAParameters();
                RSAparams.Modulus = MODULUS;
                RSAparams.Exponent = E;
                RSAparams.D = D;
                RSAparams.P = P;
                RSAparams.Q = Q;
                RSAparams.DP = DP;
                RSAparams.DQ = DQ;
                RSAparams.InverseQ = IQ;
                RSA.ImportParameters(RSAparams);
                return RSA;
            }
            catch (Exception ex)
            {

                return null;
            }
            finally
            {
                binr.Close();
            }
        }



        private static int GetIntegerSize(BinaryReader binr)
        {
            byte bt = 0;
            byte lowbyte = 0x00;
            byte highbyte = 0x00;
            int count = 0;
            bt = binr.ReadByte();
            if (bt != 0x02) //expect integer
                return 0;
            bt = binr.ReadByte();

            if (bt == 0x81)
                count = binr.ReadByte(); // data size in next byte
            else
            if (bt == 0x82)
            {
                highbyte = binr.ReadByte(); // data size in next 2 bytes
                lowbyte = binr.ReadByte();
                byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
                count = BitConverter.ToInt32(modint, 0);
            }
            else
            {
                count = bt; // we already have the data size
            }

            while (binr.ReadByte() == 0x00)
            { //remove high order zeros in data
                count -= 1;
            }
            binr.BaseStream.Seek(-1, SeekOrigin.Current); //last ReadByte wasn't a removed zero, so back up a byte
            return count;
        }


        #endregion
    }
}
View Code

原文地址:https://www.cnblogs.com/Xingsoft-555/p/15014961.html