Files
juipnet/Infrastructure/ServiceClient/Alipay.AopSdk.Core/Util/AlipaySignature.cs
“wanyongkang” 40a40b6d36 忽略
2020-12-28 14:55:48 +08:00

808 lines
25 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace Alipay.AopSdk.Core.Util
{
public class AlipaySignature
{
/** 默认编码字符集 */
private static readonly string DEFAULT_CHARSET = "utf-8";
public static string GetSignContent(IDictionary<string, string> parameters)
{
// 第一步把字典按Key的字母顺序排序
IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters);
var dem = sortedParams.GetEnumerator();
// 第二步:把所有参数名和参数值串在一起
var query = new StringBuilder("");
while (dem.MoveNext())
{
var key = dem.Current.Key;
var value = dem.Current.Value;
if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value))
query.Append(key).Append("=").Append(value).Append("&");
}
var content = query.ToString().Substring(0, query.Length - 1);
return content;
}
public static string RSASign(IDictionary<string, string> parameters, string privateKeyPem, string charset,
string signType)
{
var signContent = GetSignContent(parameters);
return RSASignCharSet(signContent, privateKeyPem, charset, signType);
}
public static string RSASign(string data, string privateKeyPem, string charset, string signType)
{
return RSASignCharSet(data, privateKeyPem, charset, signType);
}
///*
public static string RSASign(IDictionary<string, string> parameters, string privateKeyPem, string charset,
bool keyFromFile, string signType)
{
var signContent = GetSignContent(parameters);
return RSASignCharSet(signContent, privateKeyPem, charset, keyFromFile, signType);
}
public static string RSASign(string data, string privateKeyPem, string charset, string signType, bool keyFromFile)
{
return RSASignCharSet(data, privateKeyPem, charset, keyFromFile, signType);
}
//*/
public static string RSASignCharSet(string data, string privateKeyPem, string charset, string signType)
{
RSA rsaCsp = LoadCertificateFile(privateKeyPem, signType);
byte[] dataBytes = null;
if (string.IsNullOrEmpty(charset))
dataBytes = Encoding.UTF8.GetBytes(data);
else
dataBytes = Encoding.GetEncoding(charset).GetBytes(data);
var signatureBytes = rsaCsp.SignData(dataBytes, "RSA2".Equals(signType) ? HashAlgorithmName.SHA256 : HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
return Convert.ToBase64String(signatureBytes);
}
public static string RSASignCharSet(string data, string privateKeyPem, string charset, bool keyFromFile,
string signType)
{
byte[] signatureBytes = null;
try
{
RSA rsaCsp = null;
rsaCsp = keyFromFile ? LoadCertificateFile(privateKeyPem, signType) : LoadCertificateString(privateKeyPem, signType);
byte[] dataBytes = null;
if (string.IsNullOrEmpty(charset))
dataBytes = Encoding.UTF8.GetBytes(data);
else
dataBytes = Encoding.GetEncoding(charset).GetBytes(data);
if (null == rsaCsp)
throw new AopException("您使用的私钥格式错误请检查RSA私钥配置" + ",charset = " + charset);
signatureBytes = rsaCsp.SignData(dataBytes, "RSA2".Equals(signType) ? HashAlgorithmName.SHA256 : HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
}
catch (Exception ex)
{
throw new AopException($"您使用的私钥格式错误请检查RSA私钥配置,charset = {charset},异常信息:{ex.Message}", ex);
}
return Convert.ToBase64String(signatureBytes);
}
public static bool RSACheckV1(IDictionary<string, string> parameters, string publicKeyPem, string charset)
{
var sign = parameters["sign"];
parameters.Remove("sign");
parameters.Remove("sign_type");
var signContent = GetSignContent(parameters);
return RSACheckContent(signContent, sign, publicKeyPem, charset, "RSA");
}
public static bool RSACheckV1(IDictionary<string, string> parameters, string publicKeyPem)
{
var sign = parameters["sign"];
parameters.Remove("sign");
parameters.Remove("sign_type");
var signContent = GetSignContent(parameters);
return RSACheckContent(signContent, sign, publicKeyPem, DEFAULT_CHARSET, "RSA");
}
public static bool RSA2Check(IDictionary<string, string> parameters, string publicKeyPem)
{
var sign = parameters["sign"];
parameters.Remove("sign");
parameters.Remove("sign_type");
var signContent = GetSignContent(parameters);
return RSACheckContent(signContent, sign, publicKeyPem, DEFAULT_CHARSET, "RSA2");
}
public static bool RSACheckV1(IDictionary<string, string> parameters, string publicKeyPem, string charset,
string signType, bool keyFromFile)
{
var sign = parameters["sign"];
parameters.Remove("sign");
parameters.Remove("sign_type");
var signContent = GetSignContent(parameters);
return RSACheckContent(signContent, sign, publicKeyPem, charset, signType, keyFromFile);
}
public static bool RSACheckV2(IDictionary<string, string> parameters, string publicKeyPem, string charset)
{
var sign = parameters["sign"];
parameters.Remove("sign");
parameters.Remove("sign_type");
var signContent = GetSignContent(parameters);
return RSACheckContent(signContent, sign, publicKeyPem, charset, "RSA");
}
public static bool RSACheckV2(IDictionary<string, string> parameters, string publicKeyPem, string charset,
string signType, bool keyFromFile)
{
var sign = parameters["sign"];
parameters.Remove("sign");
parameters.Remove("sign_type");
var signContent = GetSignContent(parameters);
return RSACheckContent(signContent, sign, publicKeyPem, charset, signType, keyFromFile);
}
public static RSA CreateRsaProviderFromPublicKey(string publicKeyString,string signType)
{
// encoded OID sequence for PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"
byte[] seqOid = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
byte[] seq = new byte[15];
var x509Key = Convert.FromBase64String(publicKeyString);
// --------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ------
using (MemoryStream mem = new MemoryStream(x509Key))
{
using (BinaryReader binr = new BinaryReader(mem)) //wrap Memory Stream with BinaryReader for easy reading
{
byte bt = 0;
ushort twobytes = 0;
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;
seq = binr.ReadBytes(15); //read the Sequence OID
if (!CompareBytearrays(seq, seqOid)) //make sure Sequence for OID is correct
return null;
twobytes = binr.ReadUInt16();
if (twobytes == 0x8103) //data read as little endian order (actual data order for Bit String is 03 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8203)
binr.ReadInt16(); //advance 2 bytes
else
return null;
bt = binr.ReadByte();
if (bt != 0x00) //expect null byte next
return null;
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();
byte lowbyte = 0x00;
byte highbyte = 0x00;
if (twobytes == 0x8102) //data read as little endian order (actual data order for Integer is 02 81)
lowbyte = binr.ReadByte(); // read next bytes which is bytes in modulus
else if (twobytes == 0x8202)
{
highbyte = binr.ReadByte(); //advance 2 bytes
lowbyte = binr.ReadByte();
}
else
return null;
byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; //reverse byte order since asn.1 key uses big endian order
int modsize = BitConverter.ToInt32(modint, 0);
int firstbyte = binr.PeekChar();
if (firstbyte == 0x00)
{ //if first byte (highest order) of modulus is zero, don't include it
binr.ReadByte(); //skip this null byte
modsize -= 1; //reduce modulus buffer size by 1
}
byte[] modulus = binr.ReadBytes(modsize); //read the modulus bytes
if (binr.ReadByte() != 0x02) //expect an Integer for the exponent data
return null;
int expbytes = (int)binr.ReadByte(); // should only need one byte for actual exponent data (for all useful values)
byte[] exponent = binr.ReadBytes(expbytes);
// ------- create RSACryptoServiceProvider instance and initialize with public key -----
var rsa = RSA.Create();
rsa.KeySize = signType == "RSA" ? 1024 : 2048;
RSAParameters rsaKeyInfo = new RSAParameters();
rsaKeyInfo.Modulus = modulus;
rsaKeyInfo.Exponent = exponent;
rsa.ImportParameters(rsaKeyInfo);
return rsa;
}
}
}
private static bool CompareBytearrays(byte[] a, byte[] b)
{
if (a.Length != b.Length)
return false;
int i = 0;
foreach (byte c in a)
{
if (c != b[i])
return false;
i++;
}
return true;
}
public static bool RSACheckContent(string signContent, string sign, string publicKeyPem, string charset,
string signType)
{
try
{
if (string.IsNullOrEmpty(charset))
charset = DEFAULT_CHARSET;
var sPublicKeyPem = File.ReadAllText(publicKeyPem);
var rsa = CreateRsaProviderFromPublicKey(sPublicKeyPem, signType);
if ("RSA2".Equals(signType))
{
var bVerifyResultOriginal = rsa.VerifyData(Encoding.GetEncoding(charset).GetBytes(signContent),
Convert.FromBase64String(sign),HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
return bVerifyResultOriginal;
}
else
{
var bVerifyResultOriginal = rsa.VerifyData(Encoding.GetEncoding(charset).GetBytes(signContent),
Convert.FromBase64String(sign), HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
return bVerifyResultOriginal;
}
}
catch
{
return false;
}
}
public static bool RSACheckContent(string signContent, string sign, string publicKeyPem, string charset,
string signType, bool keyFromFile)
{
try
{
if (string.IsNullOrEmpty(charset))
charset = DEFAULT_CHARSET;
string sPublicKeyPem= publicKeyPem;
if (keyFromFile)
{
sPublicKeyPem = File.ReadAllText(publicKeyPem);
}
var rsa = CreateRsaProviderFromPublicKey(sPublicKeyPem, signType);
if ("RSA2".Equals(signType))
{
var bVerifyResultOriginal = rsa.VerifyData(Encoding.GetEncoding(charset).GetBytes(signContent),
Convert.FromBase64String(sign), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
return bVerifyResultOriginal;
}
else
{
var bVerifyResultOriginal = rsa.VerifyData(Encoding.GetEncoding(charset).GetBytes(signContent),
Convert.FromBase64String(sign), HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
return bVerifyResultOriginal;
}
}
catch
{
return false;
}
}
public static bool RSACheckContent(string signContent, string sign, string publicKeyPem, string charset,
bool keyFromFile)
{
try
{
string sPublicKeyPem= publicKeyPem;
if (keyFromFile)
{
sPublicKeyPem = File.ReadAllText(publicKeyPem);
}
var rsa = CreateRsaProviderFromPublicKey(sPublicKeyPem, "RSA");
var sha1 = new SHA1CryptoServiceProvider();
if (string.IsNullOrEmpty(charset))
charset = DEFAULT_CHARSET;
var bVerifyResultOriginal = rsa.VerifyData(Encoding.GetEncoding(charset).GetBytes(signContent),
Convert.FromBase64String(sign),HashAlgorithmName.SHA1,RSASignaturePadding.Pkcs1);
return bVerifyResultOriginal;
}
catch (Exception ex)
{
var s = ex.Message;
return false;
}
}
public static string CheckSignAndDecrypt(IDictionary<string, string> parameters, string alipayPublicKey,
string cusPrivateKey, bool isCheckSign,
bool isDecrypt)
{
var charset = parameters["charset"];
var bizContent = parameters["biz_content"];
if (isCheckSign)
if (!RSACheckV2(parameters, alipayPublicKey, charset))
throw new AopException("rsaCheck failure:rsaParams=" + parameters);
if (isDecrypt)
return RSADecrypt(bizContent, cusPrivateKey, charset, "RSA");
return bizContent;
}
public static string CheckSignAndDecrypt(IDictionary<string, string> parameters, string alipayPublicKey,
string cusPrivateKey, bool isCheckSign,
bool isDecrypt, string signType, bool keyFromFile)
{
var charset = parameters["charset"];
var bizContent = parameters["biz_content"];
if (isCheckSign)
if (!RSACheckV2(parameters, alipayPublicKey, charset, signType, keyFromFile))
throw new AopException("rsaCheck failure:rsaParams=" + parameters);
if (isDecrypt)
return RSADecrypt(bizContent, cusPrivateKey, charset, signType, keyFromFile);
return bizContent;
}
public static string encryptAndSign(string bizContent, string alipayPublicKey,
string cusPrivateKey, string charset, bool isEncrypt,
bool isSign, string signType, bool keyFromFile)
{
var sb = new StringBuilder();
if (string.IsNullOrEmpty(charset))
charset = DEFAULT_CHARSET;
sb.Append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>");
if (isEncrypt)
{
// 加密
sb.Append("<alipay>");
var encrypted = RSAEncrypt(bizContent, alipayPublicKey, charset, keyFromFile);
sb.Append("<response>" + encrypted + "</response>");
sb.Append("<encryption_type>" + signType + "</encryption_type>");
if (isSign)
{
var sign = RSASign(encrypted, cusPrivateKey, charset, signType, keyFromFile);
sb.Append("<sign>" + sign + "</sign>");
sb.Append("<sign_type>" + signType + "</sign_type>");
}
sb.Append("</alipay>");
}
else if (isSign)
{
// 不加密,但需要签名
sb.Append("<alipay>");
sb.Append("<response>" + bizContent + "</response>");
var sign = RSASign(bizContent, cusPrivateKey, charset, signType, keyFromFile);
sb.Append("<sign>" + sign + "</sign>");
sb.Append("<sign_type>" + signType + "</sign_type>");
sb.Append("</alipay>");
}
else
{
// 不加密,不加签
sb.Append(bizContent);
}
return sb.ToString();
}
public static string encryptAndSign(string bizContent, string alipayPublicKey,
string cusPrivateKey, string charset, bool isEncrypt,
bool isSign)
{
var sb = new StringBuilder();
if (string.IsNullOrEmpty(charset))
charset = DEFAULT_CHARSET;
sb.Append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>");
if (isEncrypt)
{
// 加密
sb.Append("<alipay>");
var encrypted = RSAEncrypt(bizContent, alipayPublicKey, charset);
sb.Append("<response>" + encrypted + "</response>");
sb.Append("<encryption_type>RSA</encryption_type>");
if (isSign)
{
var sign = RSASign(encrypted, cusPrivateKey, charset, "RSA");
sb.Append("<sign>" + sign + "</sign>");
sb.Append("<sign_type>RSA</sign_type>");
}
sb.Append("</alipay>");
}
else if (isSign)
{
// 不加密,但需要签名
sb.Append("<alipay>");
sb.Append("<response>" + bizContent + "</response>");
var sign = RSASign(bizContent, cusPrivateKey, charset, "RSA");
sb.Append("<sign>" + sign + "</sign>");
sb.Append("<sign_type>RSA</sign_type>");
sb.Append("</alipay>");
}
else
{
// 不加密,不加签
sb.Append(bizContent);
}
return sb.ToString();
}
public static string RSAEncrypt(string content, string publicKeyPem, string charset)
{
try
{
var sPublicKeyPEM = File.ReadAllText(publicKeyPem);
var rsa = CreateRsaProviderFromPublicKey(sPublicKeyPEM, "RSA");
if (string.IsNullOrEmpty(charset))
charset = DEFAULT_CHARSET;
var data = Encoding.GetEncoding(charset).GetBytes(content);
var maxBlockSize = rsa.KeySize / 8 - 11; //加密块最大长度限制
if (data.Length <= maxBlockSize)
{
var cipherbytes = rsa.Encrypt(data, RSAEncryptionPadding.Pkcs1);
return Convert.ToBase64String(cipherbytes);
}
var plaiStream = new MemoryStream(data);
var crypStream = new MemoryStream();
var buffer = new byte[maxBlockSize];
var blockSize = plaiStream.Read(buffer, 0, maxBlockSize);
while (blockSize > 0)
{
var toEncrypt = new byte[blockSize];
Array.Copy(buffer, 0, toEncrypt, 0, blockSize);
var cryptograph = rsa.Encrypt(toEncrypt, RSAEncryptionPadding.Pkcs1);
crypStream.Write(cryptograph, 0, cryptograph.Length);
blockSize = plaiStream.Read(buffer, 0, maxBlockSize);
}
return Convert.ToBase64String(crypStream.ToArray(), Base64FormattingOptions.None);
}
catch (Exception ex)
{
throw new AopException("EncryptContent = " + content + ",charset = " + charset, ex);
}
}
public static string RSAEncrypt(string content, string publicKeyPem, string charset, bool keyFromFile)
{
try
{
string sPublicKeyPEM= publicKeyPem;
if (keyFromFile)
{
sPublicKeyPEM = File.ReadAllText(publicKeyPem);
}
var rsa = CreateRsaProviderFromPublicKey(publicKeyPem, "RSA");
if (string.IsNullOrEmpty(charset))
charset = DEFAULT_CHARSET;
var data = Encoding.GetEncoding(charset).GetBytes(content);
var maxBlockSize = rsa.KeySize / 8 - 11; //加密块最大长度限制
if (data.Length <= maxBlockSize)
{
var cipherbytes = rsa.Encrypt(data, RSAEncryptionPadding.Pkcs1);
return Convert.ToBase64String(cipherbytes);
}
var plaiStream = new MemoryStream(data);
var crypStream = new MemoryStream();
var buffer = new byte[maxBlockSize];
var blockSize = plaiStream.Read(buffer, 0, maxBlockSize);
while (blockSize > 0)
{
var toEncrypt = new byte[blockSize];
Array.Copy(buffer, 0, toEncrypt, 0, blockSize);
var cryptograph = rsa.Encrypt(toEncrypt, RSAEncryptionPadding.Pkcs1);
crypStream.Write(cryptograph, 0, cryptograph.Length);
blockSize = plaiStream.Read(buffer, 0, maxBlockSize);
}
return Convert.ToBase64String(crypStream.ToArray(), Base64FormattingOptions.None);
}
catch (Exception ex)
{
throw new AopException("EncryptContent = " + content + ",charset = " + charset, ex);
}
}
public static string RSADecrypt(string content, string privateKeyPem, string charset, string signType)
{
try
{
var rsaCsp = LoadCertificateFile(privateKeyPem, signType);
if (string.IsNullOrEmpty(charset))
charset = DEFAULT_CHARSET;
var data = Convert.FromBase64String(content);
var maxBlockSize = rsaCsp.KeySize / 8; //解密块最大长度限制
if (data.Length <= maxBlockSize)
{
var cipherbytes = rsaCsp.Decrypt(data, RSAEncryptionPadding.Pkcs1);
return Encoding.GetEncoding(charset).GetString(cipherbytes);
}
var crypStream = new MemoryStream(data);
var plaiStream = new MemoryStream();
var buffer = new byte[maxBlockSize];
var blockSize = crypStream.Read(buffer, 0, maxBlockSize);
while (blockSize > 0)
{
var toDecrypt = new byte[blockSize];
Array.Copy(buffer, 0, toDecrypt, 0, blockSize);
var cryptograph = rsaCsp.Decrypt(toDecrypt, RSAEncryptionPadding.Pkcs1);
plaiStream.Write(cryptograph, 0, cryptograph.Length);
blockSize = crypStream.Read(buffer, 0, maxBlockSize);
}
return Encoding.GetEncoding(charset).GetString(plaiStream.ToArray());
}
catch (Exception ex)
{
throw new AopException("DecryptContent = " + content + ",charset = " + charset, ex);
}
}
public static string RSADecrypt(string content, string privateKeyPem, string charset, string signType,
bool keyFromFile)
{
try
{
RSA rsaCsp = null;
if (keyFromFile)
rsaCsp = LoadCertificateFile(privateKeyPem, signType);
else
rsaCsp = LoadCertificateString(privateKeyPem, signType);
if (string.IsNullOrEmpty(charset))
charset = DEFAULT_CHARSET;
var data = Convert.FromBase64String(content);
var maxBlockSize = rsaCsp.KeySize / 8; //解密块最大长度限制
if (data.Length <= maxBlockSize)
{
var cipherbytes = rsaCsp.Decrypt(data, RSAEncryptionPadding.Pkcs1);
return Encoding.GetEncoding(charset).GetString(cipherbytes);
}
var crypStream = new MemoryStream(data);
var plaiStream = new MemoryStream();
var buffer = new byte[maxBlockSize];
var blockSize = crypStream.Read(buffer, 0, maxBlockSize);
while (blockSize > 0)
{
var toDecrypt = new byte[blockSize];
Array.Copy(buffer, 0, toDecrypt, 0, blockSize);
var cryptograph = rsaCsp.Decrypt(toDecrypt, RSAEncryptionPadding.Pkcs1);
plaiStream.Write(cryptograph, 0, cryptograph.Length);
blockSize = crypStream.Read(buffer, 0, maxBlockSize);
}
return Encoding.GetEncoding(charset).GetString(plaiStream.ToArray());
}
catch (Exception ex)
{
throw new AopException("DecryptContent = " + content + ",charset = " + charset, ex);
}
}
private static byte[] GetPem(string type, byte[] data)
{
var pem = Encoding.UTF8.GetString(data);
var header = string.Format("-----BEGIN {0}-----\\n", type);
var footer = string.Format("-----END {0}-----", type);
var start = pem.IndexOf(header) + header.Length;
var end = pem.IndexOf(footer, start);
var base64 = pem.Substring(start, end - start);
return Convert.FromBase64String(base64);
}
private static RSA LoadCertificateFile(string filename, string signType)
{
using (var fs = File.OpenRead(filename))
{
var data = new byte[fs.Length];
byte[] res = null;
fs.Read(data, 0, data.Length);
if (data[0] != 0x30)
res = GetPem("RSA PRIVATE KEY", data);
try
{
var rsa = DecodeRSAPrivateKey(res, signType);
return rsa;
}
catch (Exception ex)
{
}
return null;
}
}
public static RSA LoadCertificateString(string strKey, string signType)
{
byte[] data = null;
//读取带
//ata = Encoding.Default.GetBytes(strKey);
data = Convert.FromBase64String(strKey);
//data = GetPem("RSA PRIVATE KEY", data);
try
{
var rsa = DecodeRSAPrivateKey(data, signType);
return rsa;
}
catch (Exception ex)
{
throw new AopException("Alipay.AopSdk.Core.Util.AlipaySignature LoadCertificateString DecodeRSAPrivateKey Error", ex);
}
return null;
}
private static RSA DecodeRSAPrivateKey(byte[] privkey, string signType)
{
byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
// --------- Set up stream to decode the asn.1 encoded RSA private key ------
var mem = new MemoryStream(privkey);
var binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
byte bt = 0;
ushort twobytes = 0;
var 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 -----
var CspParameters = new CspParameters();
CspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
var bitLen = 1024;
if ("RSA2".Equals(signType))
bitLen = 2048;
var rsa = RSA.Create();
rsa.KeySize = bitLen;
var 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 (Exception ex)
{
return null;
}
finally
{
binr.Close();
}
}
private static int GetIntegerSize(BinaryReader binr)
{
byte bt = 0;
byte lowbyte = 0x00;
byte highbyte = 0x00;
var 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;
}
}
}