diff --git a/DearFTP/Utils/OpenSslKey.cs b/DearFTP/Utils/OpenSslKey.cs index 40d108c..ac9a86a 100644 --- a/DearFTP/Utils/OpenSslKey.cs +++ b/DearFTP/Utils/OpenSslKey.cs @@ -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(); - } - } } } \ No newline at end of file