private static RSACryptoServiceProvider DecodeRsaPrivateKey(byte[] privkey)
{
byte[] E, D, P, Q, DP, DQ, IQ;
// ------ Set up stream to decode the asn.1 encoded RSA private key ------
MemoryStream mem = new MemoryStream(privkey);
//wrap Memory Stream with BinaryReader for easy reading
BinaryReader binr = new BinaryReader(mem);
try
{
ushort 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;
byte bt = binr.ReadByte();
if (bt != 0x00)
return null;
//------ all private key components are Integer sequences ----
int elems = GetIntegerSize(binr);
byte[] 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 cparams = new CspParameters(1,
"Microsoft Base Cryptographic Provider v1.0")
{
KeyNumber = 1,
KeyContainerName = Guid.NewGuid().ToString()
};
var rsa = new RSACryptoServiceProvider(cparams);
var rsAparams = new RSAParameters
{
Modulus = modulus,
Exponent = E,
D = D,
P = P,
Q = Q,
DP = DP,
DQ = DQ,
InverseQ = IQ
};
rsa.ImportParameters(rsAparams);
return rsa;
}
catch (Exception)
{
return null;
}
finally { binr.Close(); }
}