Remove unused code
This commit is contained in:
@@ -36,7 +36,6 @@ using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
|
||||
|
||||
namespace DearFTP.Utils
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
@@ -60,167 +59,6 @@ namespace DearFTP.Utils
|
||||
|
||||
public class OpenSslKey
|
||||
{
|
||||
|
||||
public const string Pemprivheader = "-----BEGIN RSA PRIVATE KEY-----";
|
||||
public const string Pemprivfooter = "-----END RSA PRIVATE KEY-----";
|
||||
public const string Pempubheader = "-----BEGIN PUBLIC KEY-----";
|
||||
public const string Pempubfooter = "-----END PUBLIC KEY-----";
|
||||
public const string Pemp8header = "-----BEGIN PRIVATE KEY-----\n";
|
||||
public const string Pemp8footer = "-----END PRIVATE KEY-----\n";
|
||||
public const string Pemp8encheader = "-----BEGIN ENCRYPTED PRIVATE KEY-----";
|
||||
public const string Pemp8encfooter = "-----END ENCRYPTED PRIVATE KEY-----";
|
||||
|
||||
private static bool _verbose = false;
|
||||
|
||||
// ------- Decode PEM pubic, private or pkcs8 key ----------------
|
||||
public static void DecodePEMKey(string pemstr)
|
||||
{
|
||||
byte[] pempublickey;
|
||||
byte[] pemprivatekey;
|
||||
byte[] pkcs8privatekey;
|
||||
byte[] pkcs8encprivatekey;
|
||||
|
||||
if (pemstr.StartsWith(Pempubheader) && pemstr.EndsWith(Pempubfooter))
|
||||
{
|
||||
Console.WriteLine("Trying to decode and parse a PEM public key ..");
|
||||
pempublickey = DecodeOpenSSLPublicKey(pemstr);
|
||||
if (pempublickey != null)
|
||||
{
|
||||
if (_verbose)
|
||||
ShowBytes("\nRSA public key", pempublickey);
|
||||
//PutFileBytes("rsapubkey.pem", pempublickey, pempublickey.Length) ;
|
||||
RSACryptoServiceProvider rsa = DecodeX509PublicKey(pempublickey);
|
||||
Console.WriteLine("\nCreated an RSACryptoServiceProvider instance\n");
|
||||
string xmlpublickey = rsa.ToXmlString(false);
|
||||
Console.WriteLine("\nXML RSA public key: {0} bits\n{1}\n", rsa.KeySize, xmlpublickey);
|
||||
}
|
||||
}
|
||||
else if (pemstr.StartsWith(Pemprivheader) && pemstr.EndsWith(Pemprivfooter))
|
||||
{
|
||||
Console.WriteLine("Trying to decrypt and parse a PEM private key ..");
|
||||
pemprivatekey = DecodeOpenSSLPrivateKey(pemstr);
|
||||
if (pemprivatekey != null)
|
||||
{
|
||||
if (_verbose)
|
||||
ShowBytes("\nRSA private key", pemprivatekey);
|
||||
//PutFileBytes("rsaprivkey.pem", pemprivatekey, pemprivatekey.Length) ;
|
||||
RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(pemprivatekey);
|
||||
Console.WriteLine("\nCreated an RSACryptoServiceProvider instance\n");
|
||||
string xmlprivatekey = rsa.ToXmlString(true);
|
||||
Console.WriteLine("\nXML RSA private key: {0} bits\n{1}\n", rsa.KeySize, xmlprivatekey);
|
||||
ProcessRSA(rsa);
|
||||
}
|
||||
}
|
||||
else if (pemstr.StartsWith(Pemp8header) && pemstr.EndsWith(Pemp8footer))
|
||||
{
|
||||
Console.WriteLine("Trying to decode and parse as PEM PKCS #8 PrivateKeyInfo ..");
|
||||
pkcs8privatekey = DecodePkcs8PrivateKey(pemstr);
|
||||
if (pkcs8privatekey != null)
|
||||
{
|
||||
if (_verbose)
|
||||
ShowBytes("\nPKCS #8 PrivateKeyInfo", pkcs8privatekey);
|
||||
//PutFileBytes("PrivateKeyInfo", pkcs8privatekey, pkcs8privatekey.Length) ;
|
||||
RSACryptoServiceProvider rsa = DecodePrivateKeyInfo(pkcs8privatekey);
|
||||
if (rsa != null)
|
||||
{
|
||||
Console.WriteLine("\nCreated an RSACryptoServiceProvider instance\n");
|
||||
string xmlprivatekey = rsa.ToXmlString(true);
|
||||
Console.WriteLine("\nXML RSA private key: {0} bits\n{1}\n", rsa.KeySize, xmlprivatekey);
|
||||
ProcessRSA(rsa);
|
||||
}
|
||||
else
|
||||
Console.WriteLine("\nFailed to create an RSACryptoServiceProvider");
|
||||
}
|
||||
}
|
||||
else if (pemstr.StartsWith(Pemp8encheader) && pemstr.EndsWith(Pemp8encfooter))
|
||||
{
|
||||
Console.WriteLine("Trying to decode and parse as PEM PKCS #8 EncryptedPrivateKeyInfo ..");
|
||||
pkcs8encprivatekey = DecodePkcs8EncPrivateKey(pemstr);
|
||||
if (pkcs8encprivatekey != null)
|
||||
{
|
||||
if (_verbose)
|
||||
ShowBytes("\nPKCS #8 EncryptedPrivateKeyInfo", pkcs8encprivatekey);
|
||||
//PutFileBytes("EncryptedPrivateKeyInfo", pkcs8encprivatekey, pkcs8encprivatekey.Length) ;
|
||||
RSACryptoServiceProvider rsa = DecodeEncryptedPrivateKeyInfo(pkcs8encprivatekey);
|
||||
if (rsa != null)
|
||||
{
|
||||
Console.WriteLine("\nCreated an RSACryptoServiceProvider instance\n");
|
||||
string xmlprivatekey = rsa.ToXmlString(true);
|
||||
Console.WriteLine("\nXML RSA private key: {0} bits\n{1}\n", rsa.KeySize, xmlprivatekey);
|
||||
ProcessRSA(rsa);
|
||||
}
|
||||
else
|
||||
Console.WriteLine("\nFailed to create an RSACryptoServiceProvider");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Not a PEM public, private key or a PKCS #8");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// ------- Decode PEM pubic, private or pkcs8 key ----------------
|
||||
public static void DecodeDERKey(string filename)
|
||||
{
|
||||
RSACryptoServiceProvider rsa;
|
||||
byte[] keyblob = GetFileBytes(filename);
|
||||
|
||||
if (keyblob == null)
|
||||
return;
|
||||
|
||||
rsa = DecodeX509PublicKey(keyblob);
|
||||
if (rsa != null)
|
||||
{
|
||||
Console.WriteLine("\nA valid SubjectPublicKeyInfo\n");
|
||||
Console.WriteLine("\nCreated an RSACryptoServiceProvider instance\n");
|
||||
string xmlpublickey = rsa.ToXmlString(false);
|
||||
Console.WriteLine("\nXML RSA public key: {0} bits\n{1}\n", rsa.KeySize, xmlpublickey);
|
||||
return;
|
||||
}
|
||||
|
||||
rsa = DecodeRSAPrivateKey(keyblob);
|
||||
if (rsa != null)
|
||||
{
|
||||
Console.WriteLine("\nA valid RSAPrivateKey\n");
|
||||
Console.WriteLine("\nCreated an RSACryptoServiceProvider instance\n");
|
||||
string xmlprivatekey = rsa.ToXmlString(true);
|
||||
Console.WriteLine("\nXML RSA private key: {0} bits\n{1}\n", rsa.KeySize, xmlprivatekey);
|
||||
ProcessRSA(rsa);
|
||||
return;
|
||||
}
|
||||
|
||||
rsa = DecodePrivateKeyInfo(keyblob); //PKCS #8 unencrypted
|
||||
if (rsa != null)
|
||||
{
|
||||
Console.WriteLine("\nA valid PKCS #8 PrivateKeyInfo\n");
|
||||
Console.WriteLine("\nCreated an RSACryptoServiceProvider instance\n");
|
||||
string xmlprivatekey = rsa.ToXmlString(true);
|
||||
Console.WriteLine("\nXML RSA private key: {0} bits\n{1}\n", rsa.KeySize, xmlprivatekey);
|
||||
ProcessRSA(rsa);
|
||||
return;
|
||||
}
|
||||
|
||||
rsa = DecodeEncryptedPrivateKeyInfo(keyblob); //PKCS #8 encrypted
|
||||
if (rsa != null)
|
||||
{
|
||||
Console.WriteLine("\nA valid PKCS #8 EncryptedPrivateKeyInfo\n");
|
||||
Console.WriteLine("\nCreated an RSACryptoServiceProvider instance\n");
|
||||
string xmlprivatekey = rsa.ToXmlString(true);
|
||||
Console.WriteLine("\nXML RSA private key: {0} bits\n{1}\n", rsa.KeySize, xmlprivatekey);
|
||||
ProcessRSA(rsa);
|
||||
return;
|
||||
}
|
||||
Console.WriteLine("Not a binary DER public, private or PKCS #8 key");
|
||||
return;
|
||||
}
|
||||
|
||||
public static void ProcessRSA(RSACryptoServiceProvider rsa)
|
||||
{
|
||||
if (_verbose)
|
||||
ShowRSAProps(rsa);
|
||||
}
|
||||
|
||||
//-------- Get the binary PKCS #8 PRIVATE key --------
|
||||
public static byte[] DecodePkcs8PrivateKey(string instr)
|
||||
{
|
||||
@@ -253,13 +91,14 @@ namespace DearFTP.Utils
|
||||
// encoded OID sequence for PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"
|
||||
// this byte[] includes the sequence byte and terminal encoded null
|
||||
byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
|
||||
byte[] seq = new byte[15];
|
||||
byte[] seq;
|
||||
|
||||
// --------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ------
|
||||
MemoryStream mem = new MemoryStream(pkcs8);
|
||||
int lenstream = (int)mem.Length;
|
||||
BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
|
||||
byte bt = 0;
|
||||
ushort twobytes = 0;
|
||||
byte bt;
|
||||
ushort twobytes;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -302,14 +141,14 @@ namespace DearFTP.Utils
|
||||
RSACryptoServiceProvider rsacsp = DecodeRSAPrivateKey(rsaprivkey);
|
||||
return rsacsp;
|
||||
}
|
||||
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
finally { binr.Close(); }
|
||||
|
||||
finally
|
||||
{
|
||||
binr.Close();
|
||||
}
|
||||
}
|
||||
|
||||
//-------- Get the binary PKCS #8 Encrypted PRIVATE key --------
|
||||
@@ -346,8 +185,8 @@ namespace DearFTP.Utils
|
||||
byte[] OIDpkcs5PBES2 = { 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x0D };
|
||||
byte[] OIDpkcs5PBKDF2 = { 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x0C };
|
||||
byte[] OIDdesEDE3CBC = { 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x03, 0x07 };
|
||||
byte[] seqdes = new byte[10];
|
||||
byte[] seq = new byte[11];
|
||||
byte[] seqdes;
|
||||
byte[] seq;
|
||||
byte[] salt;
|
||||
byte[] IV;
|
||||
byte[] encryptedpkcs8;
|
||||
@@ -358,10 +197,9 @@ namespace DearFTP.Utils
|
||||
|
||||
// --------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ------
|
||||
MemoryStream mem = new MemoryStream(encpkcs8);
|
||||
int lenstream = (int)mem.Length;
|
||||
BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
|
||||
byte bt = 0;
|
||||
ushort twobytes = 0;
|
||||
byte bt;
|
||||
ushort twobytes;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -413,8 +251,6 @@ namespace DearFTP.Utils
|
||||
saltsize = binr.ReadByte();
|
||||
salt = binr.ReadBytes(saltsize);
|
||||
|
||||
if (_verbose)
|
||||
ShowBytes("Salt for pbkd", salt);
|
||||
bt = binr.ReadByte();
|
||||
if (bt != 0x02) //expect an integer for PBKF2 interation count
|
||||
return null;
|
||||
@@ -426,8 +262,6 @@ namespace DearFTP.Utils
|
||||
iterations = 256 * binr.ReadByte() + binr.ReadByte();
|
||||
else
|
||||
return null;
|
||||
if (_verbose)
|
||||
Console.WriteLine("PBKD2 iterations {0}", iterations);
|
||||
|
||||
twobytes = binr.ReadUInt16();
|
||||
if (twobytes == 0x8130)
|
||||
@@ -435,7 +269,6 @@ namespace DearFTP.Utils
|
||||
else if (twobytes == 0x8230)
|
||||
binr.ReadInt16();
|
||||
|
||||
|
||||
seqdes = binr.ReadBytes(10); //read the Sequence OID
|
||||
if (!CompareBytearrays(seqdes, OIDdesEDE3CBC)) //is it a OIDdes-EDE3-CBC ?
|
||||
return null;
|
||||
@@ -443,16 +276,14 @@ namespace DearFTP.Utils
|
||||
bt = binr.ReadByte();
|
||||
if (bt != 0x04) //expect octet string for IV
|
||||
return null;
|
||||
|
||||
ivsize = binr.ReadByte(); // IV byte size should fit in one byte (24 expected for 3DES)
|
||||
IV = binr.ReadBytes(ivsize);
|
||||
if (_verbose)
|
||||
ShowBytes("IV for des-EDE3-CBC", IV);
|
||||
|
||||
bt = binr.ReadByte();
|
||||
if (bt != 0x04) // expect octet string for encrypted PKCS8 data
|
||||
return null;
|
||||
|
||||
|
||||
bt = binr.ReadByte();
|
||||
|
||||
if (bt == 0x81)
|
||||
@@ -462,21 +293,17 @@ namespace DearFTP.Utils
|
||||
else
|
||||
encblobsize = bt; // we already have the data size
|
||||
|
||||
|
||||
encryptedpkcs8 = binr.ReadBytes(encblobsize);
|
||||
//if(verbose)
|
||||
// showBytes("Encrypted PKCS8 blob", encryptedpkcs8) ;
|
||||
|
||||
|
||||
SecureString secpswd = GetSecPswd("Enter password for Encrypted PKCS #8 ==>");
|
||||
pkcs8 = DecryptPBDK2(encryptedpkcs8, salt, IV, secpswd, iterations);
|
||||
|
||||
if (pkcs8 == null) // probably a bad pswd entered.
|
||||
return null;
|
||||
|
||||
//if(verbose)
|
||||
// showBytes("Decrypted PKCS #8", pkcs8) ;
|
||||
//----- With a decrypted pkcs #8 PrivateKeyInfo blob, decode it to an RSA ---
|
||||
RSACryptoServiceProvider rsa = DecodePrivateKeyInfo(pkcs8);
|
||||
|
||||
return rsa;
|
||||
}
|
||||
catch (Exception)
|
||||
@@ -492,11 +319,8 @@ namespace DearFTP.Utils
|
||||
// ------ Uses PBKD2 to derive a 3DES key and decrypts data --------
|
||||
public static byte[] DecryptPBDK2(byte[] edata, byte[] salt, byte[] IV, SecureString secpswd, int iterations)
|
||||
{
|
||||
CryptoStream decrypt = null;
|
||||
|
||||
IntPtr unmanagedPswd = IntPtr.Zero;
|
||||
byte[] psbytes = new byte[secpswd.Length];
|
||||
unmanagedPswd = Marshal.SecureStringToGlobalAllocAnsi(secpswd);
|
||||
IntPtr unmanagedPswd = Marshal.SecureStringToGlobalAllocAnsi(secpswd);
|
||||
Marshal.Copy(unmanagedPswd, psbytes, 0, psbytes.Length);
|
||||
Marshal.ZeroFreeGlobalAllocAnsi(unmanagedPswd);
|
||||
|
||||
@@ -507,7 +331,7 @@ namespace DearFTP.Utils
|
||||
decAlg.Key = kd.GetBytes(24);
|
||||
decAlg.IV = IV;
|
||||
MemoryStream memstr = new MemoryStream();
|
||||
decrypt = new CryptoStream(memstr, decAlg.CreateDecryptor(), CryptoStreamMode.Write);
|
||||
CryptoStream decrypt = new CryptoStream(memstr, decAlg.CreateDecryptor(), CryptoStreamMode.Write);
|
||||
decrypt.Write(edata, 0, edata.Length);
|
||||
decrypt.Flush();
|
||||
decrypt.Close(); // this is REQUIRED.
|
||||
@@ -521,133 +345,6 @@ namespace DearFTP.Utils
|
||||
}
|
||||
}
|
||||
|
||||
//-------- Get the binary RSA PUBLIC key --------
|
||||
public static byte[] DecodeOpenSSLPublicKey(string instr)
|
||||
{
|
||||
const string pempubheader = "-----BEGIN PUBLIC KEY-----";
|
||||
const string pempubfooter = "-----END PUBLIC KEY-----";
|
||||
string pemstr = instr.Trim();
|
||||
byte[] binkey;
|
||||
if (!pemstr.StartsWith(pempubheader) || !pemstr.EndsWith(pempubfooter))
|
||||
return null;
|
||||
StringBuilder sb = new StringBuilder(pemstr);
|
||||
sb.Replace(pempubheader, ""); //remove headers/footers, if present
|
||||
sb.Replace(pempubfooter, "");
|
||||
|
||||
string pubstr = sb.ToString().Trim(); //get string after removing leading/trailing whitespace
|
||||
|
||||
try
|
||||
{
|
||||
binkey = Convert.FromBase64String(pubstr);
|
||||
}
|
||||
catch (System.FormatException)
|
||||
{ //if can't b64 decode, data is not valid
|
||||
return null;
|
||||
}
|
||||
return binkey;
|
||||
}
|
||||
|
||||
//------- Parses binary asn.1 X509 SubjectPublicKeyInfo; returns RSACryptoServiceProvider ---
|
||||
public static RSACryptoServiceProvider DecodeX509PublicKey(byte[] x509key)
|
||||
{
|
||||
// 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];
|
||||
// --------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ------
|
||||
MemoryStream mem = new MemoryStream(x509key);
|
||||
BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
|
||||
byte bt = 0;
|
||||
ushort twobytes = 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;
|
||||
|
||||
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);
|
||||
|
||||
byte firstbyte = binr.ReadByte();
|
||||
binr.BaseStream.Seek(-1, SeekOrigin.Current);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
ShowBytes("\nExponent", exponent);
|
||||
ShowBytes("\nModulus", modulus);
|
||||
|
||||
// ------- create RSACryptoServiceProvider instance and initialize with public key -----
|
||||
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
|
||||
RSAParameters RSAKeyInfo = new RSAParameters();
|
||||
RSAKeyInfo.Modulus = modulus;
|
||||
RSAKeyInfo.Exponent = exponent;
|
||||
RSA.ImportParameters(RSAKeyInfo);
|
||||
return RSA;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
binr.Close();
|
||||
}
|
||||
}
|
||||
|
||||
//------- Parses binary ans.1 RSA private key; returns RSACryptoServiceProvider ---
|
||||
public static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
|
||||
{
|
||||
@@ -656,9 +353,10 @@ namespace DearFTP.Utils
|
||||
// --------- 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;
|
||||
byte bt;
|
||||
ushort twobytes;
|
||||
int elems;
|
||||
|
||||
try
|
||||
{
|
||||
twobytes = binr.ReadUInt16();
|
||||
@@ -702,20 +400,6 @@ namespace DearFTP.Utils
|
||||
elems = GetIntegerSize(binr);
|
||||
IQ = binr.ReadBytes(elems);
|
||||
|
||||
if (_verbose)
|
||||
{
|
||||
Console.WriteLine("showing components ..");
|
||||
|
||||
ShowBytes("\nModulus", MODULUS);
|
||||
ShowBytes("\nExponent", E);
|
||||
ShowBytes("\nD", D);
|
||||
ShowBytes("\nP", P);
|
||||
ShowBytes("\nQ", Q);
|
||||
ShowBytes("\nDP", DP);
|
||||
ShowBytes("\nDQ", DQ);
|
||||
ShowBytes("\nIQ", IQ);
|
||||
}
|
||||
|
||||
// ------- create RSACryptoServiceProvider instance and initialize with public key -----
|
||||
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
|
||||
RSAParameters RSAparams = new RSAParameters
|
||||
@@ -743,25 +427,21 @@ namespace DearFTP.Utils
|
||||
|
||||
private static int GetIntegerSize(BinaryReader binr)
|
||||
{
|
||||
byte bt = 0;
|
||||
byte lowbyte = 0x00;
|
||||
byte highbyte = 0x00;
|
||||
int count = 0;
|
||||
|
||||
bt = binr.ReadByte();
|
||||
byte bt = binr.ReadByte();
|
||||
|
||||
if (bt != 0x02) //expect integer
|
||||
|
||||
return 0;
|
||||
bt = binr.ReadByte();
|
||||
|
||||
int count;
|
||||
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 highbyte = binr.ReadByte();
|
||||
byte lowbyte = binr.ReadByte();
|
||||
byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
|
||||
count = BitConverter.ToInt32(modint, 0);
|
||||
}
|
||||
@@ -779,160 +459,6 @@ namespace DearFTP.Utils
|
||||
return count;
|
||||
}
|
||||
|
||||
//----- Get the binary RSA PRIVATE key, decrypting if necessary ----
|
||||
public static byte[] DecodeOpenSSLPrivateKey(string instr)
|
||||
{
|
||||
const string pemprivheader = "-----BEGIN RSA PRIVATE KEY-----";
|
||||
const string pemprivfooter = "-----END RSA PRIVATE KEY-----";
|
||||
string pemstr = instr.Trim();
|
||||
byte[] binkey;
|
||||
|
||||
if (!pemstr.StartsWith(pemprivheader) || !pemstr.EndsWith(pemprivfooter))
|
||||
return null;
|
||||
|
||||
StringBuilder sb = new StringBuilder(pemstr);
|
||||
sb.Replace(pemprivheader, ""); //remove headers/footers, if present
|
||||
sb.Replace(pemprivfooter, "");
|
||||
|
||||
string pvkstr = sb.ToString().Trim(); //get string after removing leading/trailing whitespace
|
||||
|
||||
try
|
||||
{ // if there are no PEM encryption info lines, this is an UNencrypted PEM private key
|
||||
binkey = Convert.FromBase64String(pvkstr);
|
||||
return binkey;
|
||||
}
|
||||
catch (System.FormatException)
|
||||
{ //if can't b64 decode, it must be an encrypted private key
|
||||
//Console.WriteLine("Not an unencrypted OpenSSL PEM private key");
|
||||
}
|
||||
|
||||
StringReader str = new StringReader(pvkstr);
|
||||
|
||||
//-------- read PEM encryption info. lines and extract salt -----
|
||||
if (!str.ReadLine().StartsWith("Proc-Type: 4,ENCRYPTED"))
|
||||
return null;
|
||||
string saltline = str.ReadLine();
|
||||
if (!saltline.StartsWith("DEK-Info: DES-EDE3-CBC,"))
|
||||
return null;
|
||||
string saltstr = saltline.Substring(saltline.IndexOf(",") + 1).Trim();
|
||||
byte[] salt = new byte[saltstr.Length / 2];
|
||||
for (int i = 0; i < salt.Length; i++)
|
||||
salt[i] = Convert.ToByte(saltstr.Substring(i * 2, 2), 16);
|
||||
if (!(str.ReadLine() == ""))
|
||||
return null;
|
||||
|
||||
//------ remaining b64 data is encrypted RSA key ----
|
||||
string encryptedstr = str.ReadToEnd();
|
||||
|
||||
try
|
||||
{ //should have b64 encrypted RSA key now
|
||||
binkey = Convert.FromBase64String(encryptedstr);
|
||||
}
|
||||
catch (System.FormatException)
|
||||
{ // bad b64 data.
|
||||
return null;
|
||||
}
|
||||
|
||||
//------ Get the 3DES 24 byte key using PDK used by OpenSSL ----
|
||||
|
||||
SecureString despswd = GetSecPswd("Enter password to derive 3DES key==>");
|
||||
//Console.Write("\nEnter password to derive 3DES key: ");
|
||||
//String pswd = Console.ReadLine();
|
||||
byte[] deskey = GetOpenSSL3deskey(salt, despswd, 1, 2); // count=1 (for OpenSSL implementation); 2 iterations to get at least 24 bytes
|
||||
if (deskey == null)
|
||||
return null;
|
||||
//showBytes("3DES key", deskey) ;
|
||||
|
||||
//------ Decrypt the encrypted 3des-encrypted RSA private key ------
|
||||
byte[] rsakey = DecryptKey(binkey, deskey, salt); //OpenSSL uses salt value in PEM header also as 3DES IV
|
||||
if (rsakey != null)
|
||||
return rsakey; //we have a decrypted RSA private key
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Failed to decrypt RSA private key; probably wrong password.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ----- Decrypt the 3DES encrypted RSA private key ----------
|
||||
public static byte[] DecryptKey(byte[] cipherData, byte[] desKey, byte[] IV)
|
||||
{
|
||||
MemoryStream memst = new MemoryStream();
|
||||
TripleDES alg = TripleDES.Create();
|
||||
alg.Key = desKey;
|
||||
alg.IV = IV;
|
||||
try
|
||||
{
|
||||
CryptoStream cs = new CryptoStream(memst, alg.CreateDecryptor(), CryptoStreamMode.Write);
|
||||
cs.Write(cipherData, 0, cipherData.Length);
|
||||
cs.Close();
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Console.WriteLine(exc.Message);
|
||||
return null;
|
||||
}
|
||||
byte[] decryptedData = memst.ToArray();
|
||||
return decryptedData;
|
||||
}
|
||||
|
||||
//----- OpenSSL PBKD uses only one hash cycle (count); miter is number of iterations required to build sufficient bytes ---
|
||||
private static byte[] GetOpenSSL3deskey(byte[] salt, SecureString secpswd, int count, int miter)
|
||||
{
|
||||
IntPtr unmanagedPswd = IntPtr.Zero;
|
||||
int HASHLENGTH = 16; //MD5 bytes
|
||||
byte[] keymaterial = new byte[HASHLENGTH * miter]; //to store contatenated Mi hashed results
|
||||
|
||||
|
||||
byte[] psbytes = new byte[secpswd.Length];
|
||||
unmanagedPswd = Marshal.SecureStringToGlobalAllocAnsi(secpswd);
|
||||
Marshal.Copy(unmanagedPswd, psbytes, 0, psbytes.Length);
|
||||
Marshal.ZeroFreeGlobalAllocAnsi(unmanagedPswd);
|
||||
|
||||
//UTF8Encoding utf8 = new UTF8Encoding();
|
||||
//byte[] psbytes = utf8.GetBytes(pswd);
|
||||
|
||||
// --- contatenate salt and pswd bytes into fixed data array ---
|
||||
byte[] data00 = new byte[psbytes.Length + salt.Length];
|
||||
Array.Copy(psbytes, data00, psbytes.Length); //copy the pswd bytes
|
||||
Array.Copy(salt, 0, data00, psbytes.Length, salt.Length); //concatenate the salt bytes
|
||||
|
||||
// ---- do multi-hashing and contatenate results D1, D2 ... into keymaterial bytes ----
|
||||
MD5 md5 = new MD5CryptoServiceProvider();
|
||||
byte[] result = null;
|
||||
byte[] hashtarget = new byte[HASHLENGTH + data00.Length]; //fixed length initial hashtarget
|
||||
|
||||
for (int j = 0; j < miter; j++)
|
||||
{
|
||||
// ---- Now hash consecutively for count times ------
|
||||
if (j == 0)
|
||||
result = data00; //initialize
|
||||
else
|
||||
{
|
||||
Array.Copy(result, hashtarget, result.Length);
|
||||
Array.Copy(data00, 0, hashtarget, result.Length, data00.Length);
|
||||
result = hashtarget;
|
||||
//Console.WriteLine("Updated new initial hash target:") ;
|
||||
//showBytes(result) ;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
result = md5.ComputeHash(result);
|
||||
Array.Copy(result, 0, keymaterial, j * HASHLENGTH, result.Length); //contatenate to keymaterial
|
||||
}
|
||||
//showBytes("Final key material", keymaterial);
|
||||
byte[] deskey = new byte[24];
|
||||
Array.Copy(keymaterial, deskey, deskey.Length);
|
||||
|
||||
Array.Clear(psbytes, 0, psbytes.Length);
|
||||
Array.Clear(data00, 0, data00.Length);
|
||||
Array.Clear(result, 0, result.Length);
|
||||
Array.Clear(hashtarget, 0, hashtarget.Length);
|
||||
Array.Clear(keymaterial, 0, keymaterial.Length);
|
||||
|
||||
return deskey;
|
||||
}
|
||||
|
||||
private static SecureString GetSecPswd(string prompt)
|
||||
{
|
||||
SecureString password = new SecureString();
|
||||
@@ -990,7 +516,9 @@ namespace DearFTP.Utils
|
||||
{
|
||||
if (a.Length != b.Length)
|
||||
return false;
|
||||
|
||||
int i = 0;
|
||||
|
||||
foreach (byte c in a)
|
||||
{
|
||||
if (c != b[i])
|
||||
@@ -999,72 +527,5 @@ namespace DearFTP.Utils
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void ShowRSAProps(RSACryptoServiceProvider rsa)
|
||||
{
|
||||
Console.WriteLine("RSA CSP key information:");
|
||||
CspKeyContainerInfo keyInfo = rsa.CspKeyContainerInfo;
|
||||
Console.WriteLine("Accessible property: " + keyInfo.Accessible);
|
||||
Console.WriteLine("Exportable property: " + keyInfo.Exportable);
|
||||
Console.WriteLine("HardwareDevice property: " + keyInfo.HardwareDevice);
|
||||
Console.WriteLine("KeyContainerName property: " + keyInfo.KeyContainerName);
|
||||
Console.WriteLine("KeyNumber property: " + keyInfo.KeyNumber.ToString());
|
||||
Console.WriteLine("MachineKeyStore property: " + keyInfo.MachineKeyStore);
|
||||
Console.WriteLine("Protected property: " + keyInfo.Protected);
|
||||
Console.WriteLine("ProviderName property: " + keyInfo.ProviderName);
|
||||
Console.WriteLine("ProviderType property: " + keyInfo.ProviderType);
|
||||
Console.WriteLine("RandomlyGenerated property: " + keyInfo.RandomlyGenerated);
|
||||
Console.WriteLine("Removable property: " + keyInfo.Removable);
|
||||
Console.WriteLine("UniqueKeyContainerName property: " + keyInfo.UniqueKeyContainerName);
|
||||
}
|
||||
|
||||
private static void ShowBytes(string info, byte[] data)
|
||||
{
|
||||
Console.WriteLine("{0} [{1} bytes]", info, data.Length);
|
||||
for (int i = 1; i <= data.Length; i++)
|
||||
{
|
||||
Console.Write("{0:X2} ", data[i - 1]);
|
||||
if (i % 16 == 0)
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine("\n\n");
|
||||
}
|
||||
|
||||
private static byte[] GetFileBytes(string filename)
|
||||
{
|
||||
if (!File.Exists(filename))
|
||||
return null;
|
||||
|
||||
Stream stream = new FileStream(filename, FileMode.Open);
|
||||
int datalen = (int)stream.Length;
|
||||
byte[] filebytes = new byte[datalen];
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
stream.Read(filebytes, 0, datalen);
|
||||
stream.Close();
|
||||
return filebytes;
|
||||
}
|
||||
|
||||
private static void PutFileBytes(string outfile, byte[] data, int bytes)
|
||||
{
|
||||
FileStream fs = null;
|
||||
if (bytes > data.Length)
|
||||
{
|
||||
Console.WriteLine("Too many bytes");
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
fs = new FileStream(outfile, FileMode.Create);
|
||||
fs.Write(data, 0, bytes);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
fs.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user