linux rsa加密算法,.net core linux下的RSA解密

本文介绍了如何在Linux环境下使用.NET Core进行RSA解密,特别是针对OpenSSL生成的PEM格式公钥/私钥。文章讨论了遇到的`System.PlatformNotSupportedException`问题,并提供了一个解决方案,通过修改RSAHelper类来正确解析PKCS#1和PKCS#8格式的PEM密钥。

但是由于这里的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的解析方案用下面解析方式替换掉

///

/// 用PEM格式密钥对创建RSA,支持PKCS#1、PKCS#8格式的PEM

///

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 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 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 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;

}

依赖方法

///

/// 封装的一些通用方法

///

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;

}

}

///

/// 把字符串按每行多少个字断行

///

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

{

///

/// 从数组start开始到指定长度复制一份

///

static public T[] sub(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哈哈~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值