基礎(chǔ)部分參考https://blog.csdn.net/sD7O95O/article/details/78412745?locationNum=8&fps=1
但是由于這里的RSA加密/解密主要是針對(duì)于由OpenSSL生成的公鑰/私鑰字符串。ssh-keygen -t rsa 命令生成的公鑰私鑰是不行的。
如果使用帶簽名的加密方式字符串就會(huì)出現(xiàn)
rsa.ImportParameters(rsaParameters);
無(wú)法解析到相應(yīng)byte的問(wèn)題
如果使用
rsa = new RSACryptoServiceProvider(keySize, rsaParams);
可以解析帶簽名的RSA加密字符串,但是在linux下會(huì)出現(xiàn)錯(cuò)誤
解析出錯(cuò):System.PlatformNotSupportedException: 'CspParameters' requires Windows Cryptographic API (CAPI), which is not available on this platform.
有依賴(lài)包依賴(lài)于windows環(huán)境下的dll,linux下無(wú)法解析。
解決方案:
將參考部分的RSAHelper中rsa.ImportParameters(rsaParameters);獲取公鑰私鑰byte的解析方案用下面解析方式替換掉
/// <summary>
/// 用PEM格式密鑰對(duì)創(chuàng)建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內(nèi)容無(wú)效");
}
var idx = 0;
//讀取長(zhǎng)度
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未能提取到數(shù)據(jù)");
};
//讀取塊數(shù)據(jù)
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位置開(kāi)始是否是byts內(nèi)容
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"))
{
/****使用公鑰****/
//讀取數(shù)據(jù)總長(zhǎng)度
readLen(0x30);
if (!eq(_SeqOID))
{
throw new Exception("PEM未知格式");
}
//讀取1長(zhǎng)度
readLen(0x03);
idx++;//跳過(guò)0x00
//讀取2長(zhǎng)度
readLen(0x30);
//Modulus
param.Modulus = readBlock();
//Exponent
param.Exponent = readBlock();
}
else if (pem.Contains("PRIVATE KEY"))
{
/****使用私鑰****/
//讀取數(shù)據(jù)總長(zhǎng)度
readLen(0x30);
//讀取版本號(hào)
if (!eq(_Ver))
{
throw new Exception("PEM未知版本");
}
//檢測(cè)PKCS8
var idx2 = idx;
if (eq(_SeqOID))
{
//讀取1長(zhǎng)度
readLen(0x04);
//讀取2長(zhǎng)度
readLen(0x30);
//讀取版本號(hào)
if (!eq(_Ver))
{
throw new Exception("PEM版本無(wú)效");
}
}
else
{
idx = idx2;
}
//讀取數(shù)據(jù)
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標(biāo)頭");
}
rsa.ImportParameters(param);
return rsa;
}
依賴(lài)方法
/// <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>
/// 把字符串按每行多少個(gè)字?jǐn)嘈? /// </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>
/// 從數(shù)組start開(kāi)始到指定長(zhǎng)度復(fù)制一份
/// </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);
}
}
這樣經(jīng)過(guò)測(cè)試上線可以在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);
被坑了一下午,在同事的幫助下解決這個(gè)問(wèn)題,希望能幫助到那些還再坑里的同學(xué)吧O(∩_∩)O哈哈~