美文网首页
.net core linux下的RSA解密

.net core linux下的RSA解密

作者: a9b854aded01 | 来源:发表于2019-06-20 09:26 被阅读0次

    基础部分参考https://blog.csdn.net/sD7O95O/article/details/78412745?locationNum=8&fps=1

    但是由于这里的RSA加密/解密主要是针对于由OpenSSL生成的公钥/私钥字符串。ssh-keygen -t rsa 命令生成的公钥私钥是不行的。

    如果使用带签名的加密方式字符串就会出现

    rsa.ImportParameters(rsaParameters);
    

    无法解析到相应byte的问题

    如果使用

     rsa = new RSACryptoServiceProvider(keySize, rsaParams);
    

    可以解析带签名的RSA加密字符串,但是在linux下会出现错误

    解析出错:System.PlatformNotSupportedException: 'CspParameters' requires Windows Cryptographic API (CAPI), which is not available on this platform.
    

    有依赖包依赖于windows环境下的dll,linux下无法解析。

    解决方案:
    将参考部分的RSAHelper中rsa.ImportParameters(rsaParameters);获取公钥私钥byte的解析方案用下面解析方式替换掉

       /// <summary>
            /// 用PEM格式密钥对创建RSA,支持PKCS#1、PKCS#8格式的PEM
            /// </summary>
            public static System.Security.Cryptography.RSA FromPEM(string pem)
            {
                var rsa = System.Security.Cryptography.RSA.Create();
    
                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;
            }
    

    依赖方法

     /// <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);
            }
        }
    

    这样经过测试上线可以在linux下解析出带签名的RSA加密字符串

           var rsa = new RSAHelper(RSAType.RSA, Encoding.UTF8, rsaprivate);
                    Console.WriteLine("原始字符串:" + connection);
                    //加密
                    // string enStr = rsa.Encrypt(str);
    
                    // Console.WriteLine("加密字符串:" + enStr);
    
                    //解密
                    // string deStr = rsa.DecodeOrNull(connection);
                    var deStr = rsa.Decrypt(connection);
    
                    Console.WriteLine("解密字符串:" + deStr);
                    string finalconnection = MySqlHelper(deStr);
    

    被坑了一下午,在同事的帮助下解决这个问题,希望能帮助到那些还再坑里的同学吧O(∩_∩)O哈哈~

    相关文章

      网友评论

          本文标题:.net core linux下的RSA解密

          本文链接:https://www.haomeiwen.com/subject/zfgrqctx.html