209 lines
7.5 KiB
C#
209 lines
7.5 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Security.Cryptography;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace ResTool
|
||
{
|
||
public class SHA1withRSA
|
||
{
|
||
|
||
/// <summary>
|
||
/// SHA1withRSA签名
|
||
/// </summary>
|
||
/// <param name="content">待签名字符串</param>
|
||
/// <param name="privateKey">私钥</param>
|
||
/// <param name="input_charset">编码格式</param>
|
||
/// <returns>签名后字符串</returns>
|
||
public static string Sign(string content, string privateKey, string input_charset)
|
||
{
|
||
byte[] Data = Encoding.GetEncoding(input_charset).GetBytes(content);
|
||
RSACryptoServiceProvider rsa = DecodePemPrivateKey(privateKey);
|
||
using (var sh = SHA1.Create())
|
||
{
|
||
byte[] signData = rsa.SignData(Data, sh);
|
||
return Convert.ToBase64String(signData);
|
||
}
|
||
|
||
}
|
||
/// <summary>
|
||
/// pem格式公钥验签
|
||
/// </summary>
|
||
/// <param name="content">待验签字符串</param>
|
||
/// <param name="signedString">签名</param>
|
||
/// <param name="publicKey">公钥</param>
|
||
/// <param name="input_charset">编码格式</param>
|
||
/// <returns>true(通过),false(不通过)</returns>
|
||
public static bool Verify(string content, string signedString, string publicKey, string input_charset)
|
||
{
|
||
bool result = false;
|
||
byte[] Data = Encoding.GetEncoding(input_charset).GetBytes(content);
|
||
byte[] data = Convert.FromBase64String(signedString);
|
||
RSAParameters paraPub = ConvertFromPublicKey(publicKey);
|
||
RSACryptoServiceProvider rsaPub = new RSACryptoServiceProvider();
|
||
rsaPub.ImportParameters(paraPub);
|
||
using (var sh = SHA1.Create())
|
||
{
|
||
result = rsaPub.VerifyData(Data, sh, data);
|
||
return result;
|
||
}
|
||
|
||
}
|
||
|
||
#region 内部方法
|
||
|
||
private static RSACryptoServiceProvider DecodePemPrivateKey(String pemstr)
|
||
{
|
||
RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(Convert.FromBase64String(pemstr));
|
||
return rsa;
|
||
}
|
||
|
||
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
|
||
{
|
||
return null;
|
||
}
|
||
finally
|
||
{
|
||
binr.Dispose();
|
||
}
|
||
}
|
||
|
||
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
|
||
|
||
#region 生成的Pem
|
||
private static RSAParameters ConvertFromPublicKey(string pemFileConent)
|
||
{
|
||
|
||
if (string.IsNullOrEmpty(pemFileConent))
|
||
{
|
||
throw new ArgumentNullException("pemFileConent", "This arg cann't be empty.");
|
||
}
|
||
pemFileConent = pemFileConent.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("\n", "").Replace("\r", "");
|
||
byte[] keyData = Convert.FromBase64String(pemFileConent);
|
||
bool keySize1024 = (keyData.Length == 162);
|
||
bool keySize2048 = (keyData.Length == 294);
|
||
if (!(keySize1024 || keySize2048))
|
||
{
|
||
throw new ArgumentException("pem file content is incorrect, Only support the key size is 1024 or 2048");
|
||
}
|
||
byte[] pemModulus = (keySize1024 ? new byte[128] : new byte[256]);
|
||
byte[] pemPublicExponent = new byte[3];
|
||
Array.Copy(keyData, (keySize1024 ? 29 : 33), pemModulus, 0, (keySize1024 ? 128 : 256));
|
||
Array.Copy(keyData, (keySize1024 ? 159 : 291), pemPublicExponent, 0, 3);
|
||
RSAParameters para = new RSAParameters();
|
||
para.Modulus = pemModulus;
|
||
para.Exponent = pemPublicExponent;
|
||
return para;
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
}
|