nodejs加密与c#解密 rsa非对称加密互通,包含分段加密

2 篇文章 0 订阅

nodejs加密与c#解密 rsa非对称加密互通,包含分段加密

目的

将license信息在nodejs服务端加密,将license导入c#开发的window桌面应用程序进行license信息解密提取其中的激活信息,进行软件激活。

代码分享

c# 密钥生成和加密代码参考了 C# javascript js RSA非对称加解密的实现
我是使用的pem格式的公钥和密钥,使用在c#里生成,pkcs1和pkcs8都是可以的,nodejs生成的公钥密钥我还没有测试过。

nodejs端需要使用 node-jsencrypt 模块

npm i node-jsencrypt -s

C#代码

RSACryptoHelper.cs

public static class RSACryptoHelper
    {

        /// <summary>
        /// 取得私钥和公钥 XML 格式,返回数组第一个是私钥,第二个是公钥.
        /// </summary>
        /// <param name="size">密钥长度,默认1024,可以为2048</param>
        /// <returns></returns>
        public static string[] CreateXmlKey(int size = 1024)
        {
            //密钥格式要生成pkcs#1格式的  而不是pkcs#8格式的
            RSACryptoServiceProvider sp = new RSACryptoServiceProvider(size);
            string privateKey = sp.ToXmlString(true);//private key
            string publicKey = sp.ToXmlString(false);//public  key
            return new string[] { privateKey, publicKey };
        }


        /// <summary>
        /// 取得私钥和公钥 CspBlob 格式,返回数组第一个是私钥,第二个是公钥.
        /// </summary>
        /// <param name="size"></param>
        /// <returns></returns>
        public static string[] CreateCspBlobKey(int size = 1024)
        {
            //密钥格式要生成pkcs#1格式的  而不是pkcs#8格式的
            RSACryptoServiceProvider sp = new RSACryptoServiceProvider(size);
            string privateKey = Convert.ToBase64String(sp.ExportCspBlob(true));//private key
            string publicKey = Convert.ToBase64String(sp.ExportCspBlob(false));//public  key 

            return new string[] { privateKey, publicKey };
        }
        /// <summary>
		/// 导出PEM PKCS#1格式密钥对,返回数组第一个是私钥,第二个是公钥.
		/// </summary>
		public static string[] CreateKey_PEM_PKCS1(int size = 1024)
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(size);
            string privateKey = RSA_PEM.ToPEM(rsa, false, false);
            string publicKey = RSA_PEM.ToPEM(rsa, true, false);
            return new string[] { privateKey, publicKey };
        }

        /// <summary>
        /// 导出PEM PKCS#8格式密钥对,返回数组第一个是私钥,第二个是公钥.
        /// </summary>
        public static string[] CreateKey_PEM_PKCS8(int size = 1024)
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(size);
            string privateKey = RSA_PEM.ToPEM(rsa, false, true);
            string publicKey = RSA_PEM.ToPEM(rsa, true, true);
            return new string[] { privateKey, publicKey };

        }

        /// <summary>
        /// 加密 用的是PEM格式的密钥
        /// </summary>
        /// <param name="str_Plain_Text">要加密的数据</param>
        /// <param name="str_Public_PEMKey"></param>
        /// <returns></returns>
        public static string Encrypt_PEMKey(string str_Plain_Text, string str_Public_PEMKey)
        {
            using (RSACryptoServiceProvider RSA = RSA_PEM.FromPEM(str_Public_PEMKey))
            {
                return Encrypt(str_Plain_Text, RSA);
            }
        }

        /// <summary>
        /// 加密 用的是Xml格式的密钥
        /// </summary>
        /// <param name="str_Plain_Text">要加密的数据</param>
        /// <param name="str_Public_XmlKey">Xml格式的公钥</param>
        /// <returns></returns>
        public static string Encrypt_XmlKey(string str_Plain_Text, string str_Public_XmlKey)
        {
            using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
            {

                RSA.FromXmlString(str_Public_XmlKey);//载入公钥

                return Encrypt(str_Plain_Text, RSA);
            }
        }

        private static string Encrypt(string str_Plain_Text, RSACryptoServiceProvider RSA)
        {
            var data = Encoding.UTF8.GetBytes(str_Plain_Text);
            int buffersize = (RSA.KeySize / 8) - 11;
            var buffer = new byte[buffersize];
            using (MemoryStream input = new MemoryStream(data), output = new MemoryStream())
            {
                while (true)
                {
                    int readsize = input.Read(buffer, 0, buffersize);
                    if (readsize <= 0)
                    {
                        break;
                    }
                    var temp = new byte[readsize];
                    Array.Copy(buffer, 0, temp, 0, readsize);
                    var EncBytes = RSA.Encrypt(temp, false);
                    output.Write(EncBytes, 0, EncBytes.Length);
                }
                return Convert.ToBase64String(output.ToArray());
            }
        }


        /// <summary>
        /// 解密 用的是Xml格式的密钥
        /// </summary>
        /// <param name="str_Cypher_Text">密文</param>
        /// <param name="str_Private_Key">密钥</param>
        /// <returns></returns>

        public static string Decrypt_XmlKey(string str_Cypher_Text, string str_Private_XmlKey)
        {
            using (var RSA = new RSACryptoServiceProvider())
            {
                RSA.FromXmlString(str_Private_XmlKey);
                return Decrypt(str_Cypher_Text, RSA);
            }
        }


        /// <summary>
        /// 解密 用的是PEM格式的密钥
        /// </summary>
        /// <param name="str_Cypher_Text">密文</param>
        /// <param name="str_Private_Key">密钥</param>
        /// <returns></returns>

        public static string Decrypt_PEMKey(string str_Cypher_Text, string str_Private_PEMKey)
        {
            //using (var RSA = new RSACryptoServiceProvider())
            using (var RSA = RSA_PEM.FromPEM(str_Private_PEMKey))
            {
                return Decrypt(str_Cypher_Text, RSA);
            }
        }

        private static string Decrypt(string str_Cypher_Text, RSACryptoServiceProvider RSA)
        {
            var data = Convert.FromBase64String(str_Cypher_Text);

            //RSA.FromXmlString(str_Private_Key);
            int buffersize = RSA.KeySize / 8;
            var buffer = new byte[buffersize];
            using (MemoryStream input = new MemoryStream(data),
                 output = new MemoryStream())
            {
                while (true)
                {
                    int readsize = input.Read(buffer, 0, buffersize);
                    if (readsize <= 0)
                    {
                        break;
                    }

                    var temp = new byte[readsize];
                    Array.Copy(buffer, 0, temp, 0, readsize);
                    var DecBytes = RSA.Decrypt(temp, false);
                    output.Write(DecBytes, 0, DecBytes.Length);
                }
                return Encoding.UTF8.GetString(output.ToArray());
            }
        }
    }

RSA_Unit.cs

/// <summary>
    /// 封装的一些通用方法
    /// </summary>
    public class RSA_Unit
    {
        static public string Base64EncodeBytes(byte[] byts)
        {
            return Convert.ToBase64String(byts);
        }
        static public byte[] Base64DecodeBytes(string str)
        {
            try
            {
                return Convert.FromBase64String(str);
            }
            catch
            {
                return null;
            }
        }
        /// <summary>
        /// 把字符串按每行多少个字断行
        /// </summary>
        static public string TextBreak(string text, int line)
        {
            var idx = 0;
            var len = text.Length;
            var str = new StringBuilder();
            while (idx < len)
            {
                if (idx > 0)
                {
                    str.Append('\n');
                }
                if (idx + line >= len)
                {
                    str.Append(text.Substring(idx));
                }
                else
                {
                    str.Append(text.Substring(idx, line));
                }
                idx += line;
            }
            return str.ToString();
        }
    }

    static public class Extensions
    {
        /// <summary>
        /// 从数组start开始到指定长度复制一份
        /// </summary>
        static public T[] sub<T>(this T[] arr, int start, int count)
        {
            T[] val = new T[count];
            for (var i = 0; i < count; i++)
            {
                val[i] = arr[start + i];
            }
            return val;
        }
        static public void writeAll(this Stream stream, byte[] byts)
        {
            stream.Write(byts, 0, byts.Length);
        }
    }

RSA_PEM.cs

/// <summary>
    /// RSA PEM格式秘钥对的解析和导出
    /// </summary>
    public class RSA_PEM
    {
        /// <summary>
        /// 用PEM格式密钥对创建RSA,支持PKCS#1、PKCS#8格式的PEM
        /// </summary>
        public static RSACryptoServiceProvider FromPEM(string pem)
        {
            var rsaParams = new CspParameters();
            rsaParams.Flags = CspProviderFlags.UseMachineKeyStore;
            var rsa = new RSACryptoServiceProvider(rsaParams);

            var param = new RSAParameters();

            var base64 = _PEMCode.Replace(pem, "");
            var data = RSA_Unit.Base64DecodeBytes(base64);
            if (data == null)
            {
                throw new Exception("PEM内容无效");
            }
            var idx = 0;

            //读取长度
            Func<byte, int> readLen = (first) =>
            {
                if (data[idx] == first)
                {
                    idx++;
                    if (data[idx] == 0x81)
                    {
                        idx++;
                        return data[idx++];
                    }
                    else if (data[idx] == 0x82)
                    {
                        idx++;
                        return (((int)data[idx++]) << 8) + data[idx++];
                    }
                    else if (data[idx] < 0x80)
                    {
                        return data[idx++];
                    }
                }
                throw new Exception("PEM未能提取到数据");
            };
            //读取块数据
            Func<byte[]> readBlock = () =>
            {
                var len = readLen(0x02);
                if (data[idx] == 0x00)
                {
                    idx++;
                    len--;
                }
                var val = data.sub(idx, len);
                idx += len;
                return val;
            };
            //比较data从idx位置开始是否是byts内容
            Func<byte[], bool> eq = (byts) =>
            {
                for (var i = 0; i < byts.Length; i++, idx++)
                {
                    if (idx >= data.Length)
                    {
                        return false;
                    }
                    if (byts[i] != data[idx])
                    {
                        return false;
                    }
                }
                return true;
            };




            if (pem.Contains("PUBLIC KEY"))
            {
                /****使用公钥****/
                //读取数据总长度
                readLen(0x30);
                if (!eq(_SeqOID))
                {
                    throw new Exception("PEM未知格式");
                }
                //读取1长度
                readLen(0x03);
                idx++;//跳过0x00
                      //读取2长度
                readLen(0x30);

                //Modulus
                param.Modulus = readBlock();

                //Exponent
                param.Exponent = readBlock();
            }
            else if (pem.Contains("PRIVATE KEY"))
            {
                /****使用私钥****/
                //读取数据总长度
                readLen(0x30);

                //读取版本号
                if (!eq(_Ver))
                {
                    throw new Exception("PEM未知版本");
                }

                //检测PKCS8
                var idx2 = idx;
                if (eq(_SeqOID))
                {
                    //读取1长度
                    readLen(0x04);
                    //读取2长度
                    readLen(0x30);

                    //读取版本号
                    if (!eq(_Ver))
                    {
                        throw new Exception("PEM版本无效");
                    }
                }
                else
                {
                    idx = idx2;
                }

                //读取数据
                param.Modulus = readBlock();
                param.Exponent = readBlock();
                param.D = readBlock();
                param.P = readBlock();
                param.Q = readBlock();
                param.DP = readBlock();
                param.DQ = readBlock();
                param.InverseQ = readBlock();
            }
            else
            {
                throw new Exception("pem需要BEGIN END标头");
            }

            rsa.ImportParameters(param);
            return rsa;
        }
        static private Regex _PEMCode = new Regex(@"--+.+?--+|\s+");
        static private byte[] _SeqOID = new byte[] { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
        static private byte[] _Ver = new byte[] { 0x02, 0x01, 0x00 };

        /// <summary>
        /// 将RSA中的密钥对转换成PEM格式,usePKCS8=false时返回PKCS#1格式,否则返回PKCS#8格式,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响
        /// </summary>
        public static string ToPEM(RSACryptoServiceProvider rsa, bool convertToPublic, bool usePKCS8)
        {
            //https://www.jianshu.com/p/25803dd9527d
            //https://www.cnblogs.com/ylz8401/p/8443819.html
            //https://blog.csdn.net/jiayanhui2877/article/details/47187077
            //https://blog.csdn.net/xuanshao_/article/details/51679824
            //https://blog.csdn.net/xuanshao_/article/details/51672547

            var ms = new MemoryStream();
            //写入一个长度字节码
            Action<int> writeLenByte = (len) =>
            {
                if (len < 0x80)
                {
                    ms.WriteByte((byte)len);
                }
                else if (len <= 0xff)
                {
                    ms.WriteByte(0x81);
                    ms.WriteByte((byte)len);
                }
                else
                {
                    ms.WriteByte(0x82);
                    ms.WriteByte((byte)(len >> 8 & 0xff));
                    ms.WriteByte((byte)(len & 0xff));
                }
            };
            //写入一块数据
            Action<byte[]> writeBlock = (byts) =>
            {
                var addZero = (byts[0] >> 4) >= 0x8;
                ms.WriteByte(0x02);
                var len = byts.Length + (addZero ? 1 : 0);
                writeLenByte(len);

                if (addZero)
                {
                    ms.WriteByte(0x00);
                }
                ms.Write(byts, 0, byts.Length);
            };
            //根据后续内容长度写入长度数据
            Func<int, byte[], byte[]> writeLen = (index, byts) =>
            {
                var len = byts.Length - index;

                ms.SetLength(0);
                ms.Write(byts, 0, index);
                writeLenByte(len);
                ms.Write(byts, index, len);

                return ms.ToArray();
            };


            if (rsa.PublicOnly || convertToPublic)
            {
                /****生成公钥****/
                var param = rsa.ExportParameters(false);


                //写入总字节数,不含本段长度,额外需要24字节的头,后续计算好填入
                ms.WriteByte(0x30);
                var index1 = (int)ms.Length;

                //固定内容
                // encoded OID sequence for PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"
                ms.writeAll(_SeqOID);

                //从0x00开始的后续长度
                ms.WriteByte(0x03);
                var index2 = (int)ms.Length;
                ms.WriteByte(0x00);

                //后续内容长度
                ms.WriteByte(0x30);
                var index3 = (int)ms.Length;

                //写入Modulus
                writeBlock(param.Modulus);

                //写入Exponent
                writeBlock(param.Exponent);


                //计算空缺的长度
                var byts = ms.ToArray();

                byts = writeLen(index3, byts);
                byts = writeLen(index2, byts);
                byts = writeLen(index1, byts);


                return "-----BEGIN PUBLIC KEY-----\n" + RSA_Unit.TextBreak(RSA_Unit.Base64EncodeBytes(byts), 64) + "\n-----END PUBLIC KEY-----";
            }
            else
            {
                /****生成私钥****/
                var param = rsa.ExportParameters(true);

                //写入总字节数,后续写入
                ms.WriteByte(0x30);
                int index1 = (int)ms.Length;

                //写入版本号
                ms.writeAll(_Ver);

                //PKCS8 多一段数据
                int index2 = -1, index3 = -1;
                if (usePKCS8)
                {
                    //固定内容
                    ms.writeAll(_SeqOID);

                    //后续内容长度
                    ms.WriteByte(0x04);
                    index2 = (int)ms.Length;

                    //后续内容长度
                    ms.WriteByte(0x30);
                    index3 = (int)ms.Length;

                    //写入版本号
                    ms.writeAll(_Ver);
                }

                //写入数据
                writeBlock(param.Modulus);
                writeBlock(param.Exponent);
                writeBlock(param.D);
                writeBlock(param.P);
                writeBlock(param.Q);
                writeBlock(param.DP);
                writeBlock(param.DQ);
                writeBlock(param.InverseQ);


                //计算空缺的长度
                var byts = ms.ToArray();

                if (index2 != -1)
                {
                    byts = writeLen(index3, byts);
                    byts = writeLen(index2, byts);
                }
                byts = writeLen(index1, byts);


                var flag = " PRIVATE KEY";
                if (!usePKCS8)
                {
                    flag = " RSA" + flag;
                }
                return "-----BEGIN" + flag + "-----\n" + RSA_Unit.TextBreak(RSA_Unit.Base64EncodeBytes(byts), 64) + "\n-----END" + flag + "-----";
            }
        }
    }

解密

string pkcs1_private = "-----BEGIN RSA PRIVATE KEY-----\n" +
    "MIIEowIBAAKCAQEA9zhzkpG+YFDtm+MpNR17dHW2k+r8gzEJmU5IMUeiVOBAYGr+\n" +
    "p6+bvRIGnNOdb4nZpdl/zgeuO1v/f5H0eTIW4E/xvDb2k81ucAcuJbX81p2sFtaP\n" +
    "vH1NdVmXPLDsOrgQnF9W63WU25JZNp7F+47lX2wJLPcShJ8TIvmW5PA0JARMafpW\n" +
    "wDL2zyraUAvJvIOdFWdhy+ejWLMckpyh2LuCnF41CAjPmg68PN4+McavQoTCXAZf\n" +
    "IpmZuWrfK8Xfe1RWE6f3G7QQvlTN67NNR8NVjOrJEoL/MntMR4pfnRoCGIqzirTO\n" +
    "vhpJes5/sntNM3zuqXF3POlgCEwI1/HxmQ7Y+QIDAQABAoIBAA1dcOoQlQEx/tZ5\n" +
    "nmWvtVfjcT5n6sTQ5trx33dCjyUVhoVv41p/ZOUAz3i0/ALmqeyMaJtj0OiGnbZw\n" +
    "1o2ixpfT2pa5RfVRmtHVoYoKX6PenEoTyWuAPqrEcCeozOyTvNonUVSjY6vHKqmI\n" +
    "Rd3GqOHSvmA+7zJaQzeV1LGFxtvXgHKGSlStJaO+BE3wiJT6izfrYBt3+CHZeH4P\n" +
    "drAxu8fjHOXrF7YaBFORS5neoB72hkQsRLyfYvaxPr1LNcfy0ks50ErHsZIySTg5\n" +
    "v+lV20XDoHTqpcBe0GQACZ+7NXY6/6JfeY+44SKM+n74Z1gn2CqLDdRze6WG7ujq\n" +
    "yvNUUb0CgYEA/Oja01UExw60GVRyMjzcRQcBKWZNEjxaAgMmSg+Vi1lpzm9I2R6z\n" +
    "uHTmu9SZfEA3z46mIRFrkdnaUh8NdovPIxB0kuqC4e+KQFFs+dRn3k1MmwDd8us0\n" +
    "XLGs/gmUbgdbOlRAI//JCTDnvL6Wfngv4bIPXqnBXSPRcW1ujLGHyUMCgYEA+j3M\n" +
    "3Sl3STGRaaEl8iRQaCK7er0G5/l6PoFNrnHC5+YK0Ly7zHzR/PJobo3cM7BjjDjH\n" +
    "3ORM6eG3nByxQFEX7pVdeoxhEAj3ibx0IDcvfaJl4JJ31xjrseSXiZ9Pu/4Tqj9D\n" +
    "Ukn0aeBmk9iWrU8xkghGZTN3xiAMJ25vwBTiYxMCgYEA7BKXICj9+qj456PxrH8u\n" +
    "xKgTJ4e8bUc0ZSh3dy4w0xA1OWKbRz/nVkiYj7+VPWvcLLvkyn0uQchuh7VApeU/\n" +
    "BmX3yqNoZGlqTTs0U8c25USWOyGGC5gNGnEnH0Hl8Qag20OFU5URHKkvxvjIFWku\n" +
    "mKfSvPQL8Frcx9n0FRQpwW0CgYAhJ4z8BGFsjiew8gvgABWzJl7mjSLcGz6qB2Gu\n" +
    "ah4jsWPfchIDrsn3lHpno134bzdRPbilOI5EMoasJVUKq3PbRWjkMrMtd7KsSg6s\n" +
    "sgMVxy1uSpmcIw4fPKUjM7tRsgES/lzCC1BZssSEdB7KiYKM0ZHaGK6Wzmot00D1\n" +
    "Fw9DhwKBgDLss7dqk9tUfM3sjQbIVxLi+D0Vmi7jD4AIQQZoVQn390hZ75C/j02m\n" +
    "4w/Lm065PASYxAN551AmpILzJSF3YdxzrAoAAP21itCLT0HVEU54UdqQwHsmsSEk\n" +
    "0y+RbOs702xclseYd3hVG8mIaC3wIX31iDMAqz/qSsYUe4BCIb+5\n" +
    "-----END RSA PRIVATE KEY-----";
            string pkcs1_public = "-----BEGIN PUBLIC KEY-----\n" +
    "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9zhzkpG+YFDtm+MpNR17\n" +
    "dHW2k+r8gzEJmU5IMUeiVOBAYGr+p6+bvRIGnNOdb4nZpdl/zgeuO1v/f5H0eTIW\n" +
    "4E/xvDb2k81ucAcuJbX81p2sFtaPvH1NdVmXPLDsOrgQnF9W63WU25JZNp7F+47l\n" +
    "X2wJLPcShJ8TIvmW5PA0JARMafpWwDL2zyraUAvJvIOdFWdhy+ejWLMckpyh2LuC\n" +
    "nF41CAjPmg68PN4+McavQoTCXAZfIpmZuWrfK8Xfe1RWE6f3G7QQvlTN67NNR8NV\n" +
    "jOrJEoL/MntMR4pfnRoCGIqzirTOvhpJes5/sntNM3zuqXF3POlgCEwI1/HxmQ7Y\n" +
    "+QIDAQAB\n" +
    "-----END PUBLIC KEY-----";
            string pkcs8_private = "-----BEGIN PRIVATE KEY-----\n" +
    "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCvB5m7LDu1+u2X\n" +
    "xqHMF20tqAseN0qwqbMPlw43GCh42uHFC2AXKqWvZCAJ8LaI5Ludk8IPwYVWz5Sz\n" +
    "UDJxgvSGTXs2vFpSKnvM8dP2nUwTDKUt6gKRayBZnMVZcShz7aVk5VD7Uco/0224\n" +
    "kqyQRaC675vLROIgLv0Bu87NqZ83uau2YcuGSbTtmn+JOBt52SuLfd9uFGCA+mRu\n" +
    "/R0lYDLjFNjUUwCqKtqPWMDk1uPs8wIPfvBd4tz3TiwUgK1tCTjqvWrP36Wp2aeO\n" +
    "wcyrTZJOol1uG8ZXtOJ/wWb3CUkeFT36m0Zs9+YKbXasee2CYrMeas5ywLVVjq6l\n" +
    "KMCYeW05AgMBAAECggEANcDQzrHr+JyCoU0oXYSITDBCkdoLPywuyMfsXrE1pMAb\n" +
    "/CbdMOAxGCdYy5S4ilws3l0FiU82gw2nLlaf10qPjDt5brrzxi4z7SILpb5zIZqN\n" +
    "lAc9GKncuoix9yEQemHunIjskPJyeZ2WIcwx4PDxRtfVcdzK0XV80C58eZ7xPexu\n" +
    "TSaj7W+JXr7gdhEC0+BeRTT62nOx/ElBZGtywAKj0AZmWO7phx44EcUGuTki6COV\n" +
    "trY/HlkOLTHgu2uu6NufAVp6GYdNojj20ZvEyljuOTlWZjd/HizhxoiyHZD2rf9X\n" +
    "wTEdINpEEIT5VNfAtvbBzWaztPvzbID1/Jt6iQg8jQKBgQDD0umeFL5SqZzAdpIR\n" +
    "pTDzy4BYuOMiudYn0OD5B9m/4u5g5JPG2AL+94SOzsUexR6zgeBPo/WobiVBd3ZV\n" +
    "BMG8+OrIQdaBEaAd4911fldX/rhn+tAXBmv+pbcC3LXNfYYNVR4CzcGEAHbXATL8\n" +
    "HipBWsCeT0bXXOBjiDKZypKhbwKBgQDk0Nlm/0GaH/eZsRYIWA6Xz558wX9h+iFA\n" +
    "ecXqTPNDtvlMOp8uJO+I3gmvvICal/FvjktU7MAb3riu0QgGt7D9730xsm7bSXju\n" +
    "DZx1hbHayewgN9WlZpOkQBF657PaeZmcOAq/ss7JLpGfRu8cCuzrqdadbRyuR/46\n" +
    "QL9eNys31wKBgCOcYVucDhheO+FMLrgCwGo1YbvAs52HCgjnlWH0KYcZr5vzNWR9\n" +
    "t93CCVsnAvXbhv/B6JbTDEN69E95eA1x9gF1isysHGQQXnvRCl7pgNzBt6tBE0J8\n" +
    "qnr+i897b5xU7WHTTsfXvw9QPkxPLYRnv+tuo4Smig10GGJBTGJnUk8FAoGBAKgB\n" +
    "kR9HHOwFvM9kb0EBJvXgxAXmLZnLBs9ImkFG7vcxSirmgCpphFeCcKpQRj08g1Hd\n" +
    "sQJSM1xDVGdHpBUKmzJYvhvXX/4zHE/uPosr90MmL/IYDQ69Gnrnb+5GYpBv6JID\n" +
    "tCC9MYgWYWYJt1dnzj3bHnHIw95Tjh9HmzuaVmlRAoGBALFTaeGbhf8k6x/amSvV\n" +
    "lowpsYgTAuR02GUIn80fG5blcAjIMCs8/J3E7p0qvZgW7+dMpHFWPUJzvQBD/iLF\n" +
    "VqVdhjQAvoJT5dpTuHCaQObt7LwMpjdPB3W0vMNQx/z5RppKrIbA4ZH8KNNByvHI\n" +
    "5PyXdToSZCKBULOYal41l5Va\n" +
    "-----END PRIVATE KEY-----";
            string pkcs8_public = "-----BEGIN PUBLIC KEY-----\n" +
    "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArweZuyw7tfrtl8ahzBdt\n" +
    "LagLHjdKsKmzD5cONxgoeNrhxQtgFyqlr2QgCfC2iOS7nZPCD8GFVs+Us1AycYL0\n" +
    "hk17NrxaUip7zPHT9p1MEwylLeoCkWsgWZzFWXEoc+2lZOVQ+1HKP9NtuJKskEWg\n" +
    "uu+by0TiIC79AbvOzamfN7mrtmHLhkm07Zp/iTgbedkri33fbhRggPpkbv0dJWAy\n" +
    "4xTY1FMAqiraj1jA5Nbj7PMCD37wXeLc904sFICtbQk46r1qz9+lqdmnjsHMq02S\n" +
    "TqJdbhvGV7Tif8Fm9wlJHhU9+ptGbPfmCm12rHntgmKzHmrOcsC1VY6upSjAmHlt\n" +
    "OQIDAQAB\n" +
    "-----END PUBLIC KEY-----";
string data = "nodejs端使用公钥加密的密文";
string[] splitKey = { "-SPLIT-" };
string[] result = data.Split(splitKey, StringSplitOptions.RemoveEmptyEntries);
            Console.WriteLine(result.Length);
            string[] decryptArr = new string[result.Length];
            //使用了-SPLIT-分割多份密文
            for (var i = 0; i < result.Length; i++)
            {
                string encryptData = result[i];
                string decryptData = RSACryptoHelper.Decrypt_PEMKey(encryptData, pkcs1_private);
                decryptArr[i] = decryptData;
            }

            string decryptStr = string.Join("", decryptArr);
            //原始字符串使用了base64编码了一次,解密是使用base64转码回去
            string original = Encoding.UTF8.GetString(Convert.FromBase64String(decryptStr));
            Console.WriteLine(original);

Nodejs代码

nodejs写的是测试代码,但实际逻辑代码基本就这样处理。

test.js

let util = require('./common/util');
const fs = require('fs');
let JSEncrypt = require('node-jsencrypt');
async function main() {
    let splitKey = '-SPLIT-';
    let publicKey = await fs.readFileSync('../key/pkcs1_public.pem');
    let privateKey = await fs.readFileSync('../key/pkcs1_private.pem');

    let aa = "需要加密的明文";

    let start = 0, size = 100;
    let encyptoArr = [];
    let a = util.base64Encode(aa);
    console.log(a);
    if (a.length > 100) {
        while (start < a.length) {
            encyptoArr.push(a.slice(start, start + size));
            start += size;
        }
    } else {
        encyptoArr.push(a);
    }
    console.log(encyptoArr.join('') === a);

    let result = [];
    let encrypted = new JSEncrypt();
    encrypted.setPublicKey(publicKey.toString());
    console.log(encrypted);
    encyptoArr.forEach(item => {
        // let bf = Buffer.from(item, 'utf8');
        // let encryptData = crypto.publicEncrypt(publicKey, bf).toString('base64');
        let encryptData = encrypted.encrypt(item);
        result.push(encryptData);
    })
    console.log(result.join(splitKey));  //result.join(splitKey)就是license信息
	//这里是测试在nodejs使用密钥将密文解密
    let decrypto = [];
    let decrypted = new JSEncrypt();
    decrypted.setPrivateKey(privateKey.toString());
    result.forEach(item => {
        // let bf = Buffer.from(item, 'base64');
        // let decryptData = crypto.privateDecrypt(privateKey, bf).toString();
        let decryptData = decrypted.decrypt(item);
        decrypto.push(decryptData);
    })
    let oldstr = util.base64Decode(decrypto.join(''));
    console.log(oldstr);

}

main().then(() => {
})

util.js

module.exports = {
base64Encode(str) {
        if (this.isEmpty(str)) return '';
        let data = Buffer.from(str, 'utf8');
        return data.toString('base64');
    },
    base64Decode(str) {
        if (this.isEmpty(str)) return '';
        let data = Buffer.from(str, 'base64');
        return data.toString('utf8');
    },
    }

前两天使用nodejs内置模块node-rsa和crypto加密后,将密文在c#代码里都不行,什么密文太长啊,这些问题,烦,不过总算是解决了,又可以进行下一个bug的编写了

网上轮子比较多,但是要找到适合自己轮毂的还是要花点心思,我也感谢找到的这个轮子。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赵东19970820

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值