Отправка пароля через TCP в C # - PullRequest
0 голосов
/ 13 октября 2011

Я и не практикующий программист, так что, в принципе, снова новичок в этом.

Что я делаю, так это подключаюсь к устройству через Telnet или TCP. Вместо того, чтобы управлять устройством с помощью команды типа, я использую приложение пользовательских форм для отправки команд типа строки с помощью предварительно запрограммированной кнопки. Устройство старого кодека. Цель моего программного обеспечения - создать кнопочный контроллер для ПК.

У меня проблема в том, что некоторые из моих устройств защищены паролем, а некоторые нет (разные прошивки). Это не может быть изменено. Защита паролем - это то, что застряло у меня.

Я отправляю данные на устройство с помощью ASCII

public void Write(string cmd)
        {
            if (!tcpSocket.Connected) return;
            byte[] buf = System.Text.ASCIIEncoding.ASCII.GetBytes(cmd.Replace("\0xFF", "\0xFF\0xFF"));
            tcpSocket.GetStream().Write(buf, 0, buf.Length);

Я искал на MD5 и застрял. Я попытался отправить пароль в виде обычного текста, введя пароль в текстовое поле и инициировав команду записи. Я также попытался отправить вывод этого кода, который я нашел в интернете

public string EncodePassword(string originalPassword)
        {
            //Declarations
            Byte[] originalBytes;
            Byte[] encodedBytes;
            MD5 md5;

            //Instantiate MD5CryptoServiceProvider, get bytes for original password and compute hash (encoded password)
            md5 = new MD5CryptoServiceProvider();
            originalBytes = ASCIIEncoding.Default.GetBytes(originalPassword);
            encodedBytes = md5.ComputeHash(originalBytes);
            //Convert encoded bytes back to a 'readable' string
            return BitConverter.ToString(encodedBytes);                            

Я даже нашел еще одну строку MD5, в которой вводились прописные и строчные буквы. Я не знаю, будет ли он работать, потому что он все еще отправляет зашифрованный пароль в ASCII или как.

Я знаю, что мой пароль правильный, потому что я могу загрузить telnet в Windows и войти в систему там. Любая помощь в получении этого клиента для аутентификации на сервере была бы очень признательна.


Простите за длину. Поскольку я не могу ответить, мне пришлось редактировать. Я думаю, что я был сбит с толку на MD5 ... После прочтения ответов, я думаю, что моя проблема - ASCII. Мне нужен простой текст.

Хорошо, вот где ярко светятся мои полосы для начинающих. Это моя первая попытка программирования с использованием какой-либо сети (если это не было так очевидно). После прочтения ответов я думаю, что моей первой проблемой является ASCII. Я предполагал, что отправленный, хотя это был простой текст. Учитывая, что когда я подключаюсь к серверу с тем же клиентом, который не требует ввода пароля, пароль ... ASCII работает просто отлично.

Так что, если я собираюсь использовать простой текст, то как бы я пошла об отправке в виде простого текста, а не байтового преобразования? Предполагая, что мое предположение, что ASCII был способом отправки простого текста, неверно ... Что я теперь думаю, что это так.

Я добавил больше кода, чтобы помочь этому.

При использовании клиента telnet для Windows устройство запрашивает пароль, и при вводе его в telnet текст не отображается до тех пор, пока после входа в систему. После входа в систему все набирается сразу.

Класс, используемый для сокета, в основном представляет собой код, который я нашел в Google с некоторыми небольшими изменениями.

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;

namespace STC_Control
{
    enum Verbs
    {
        WILL = 251,
        WONT = 252,
        DO = 253,
        DONT = 254,
        IAC = 255
    }

    enum Options
    {
        SGA = 3
    }

    class TelnetConnection
    {
        TcpClient tcpSocket;

        int TimeOutMs = 100;

        public TelnetConnection(string Hostname, int Port)
        {
            tcpSocket = new TcpClient(Hostname, Port);

        }

        public void WriteLine(string cmd)
        {
            Write(cmd + "\n");
        }

        public void Write(string cmd)
        {
            if (!tcpSocket.Connected) return;
            byte[] buf = System.Text.ASCIIEncoding.ASCII.GetBytes(cmd.Replace("\0xFF", "\0xFF\0xFF"));
            tcpSocket.GetStream().Write(buf, 0, buf.Length);
        }

        public string Read()
        {

            if (!tcpSocket.Connected) return null;

                StringBuilder sb = new StringBuilder();

                do
                {
                    ParseTelnet(sb);
                    System.Threading.Thread.Sleep(TimeOutMs);
                } while (tcpSocket.Available > 0);
                return sb.ToString();

        }

        public bool IsConnected
        {
            get { return tcpSocket.Connected; }
        }

        void ParseTelnet(StringBuilder sb)
        {
            while (tcpSocket.Available > 0)
            {
                int input = tcpSocket.GetStream().ReadByte();
                switch (input)
                {
                    case -1:
                        break;
                    case (int)Verbs.IAC:
                        // interpret as command
                        int inputverb = tcpSocket.GetStream().ReadByte();
                        if (inputverb == -1) break;
                        switch (inputverb)
                        {
                            case (int)Verbs.IAC:
                                //literal IAC = 255 escaped, so append char 255 to string
                                sb.Append(inputverb);
                                break;
                            case (int)Verbs.DO:
                            case (int)Verbs.DONT:
                            case (int)Verbs.WILL:
                            case (int)Verbs.WONT:
                                // reply to all commands with "WONT", unless it is SGA (suppres go ahead)
                                int inputoption = tcpSocket.GetStream().ReadByte();
                                if (inputoption == -1) break;
                                tcpSocket.GetStream().WriteByte((byte)Verbs.IAC);
                                if (inputoption == (int)Options.SGA)
                                    tcpSocket.GetStream().WriteByte(inputverb == (int)Verbs.DO ? (byte)Verbs.WILL : (byte)Verbs.DO);
                                else
                                    tcpSocket.GetStream().WriteByte(inputverb == (int)Verbs.DO ? (byte)Verbs.WONT : (byte)Verbs.DONT);
                                tcpSocket.GetStream().WriteByte((byte)inputoption);
                                break;
                            default:
                                break;
                        }
                        break;
                    default:
                        sb.Append((char)input);
                        break;
                }
            }

        }
    }
}

Тогда программа

public Form1()
        {
            InitializeComponent();
        }
        //declorations
        TelnetConnection tc;
        Int16 vl = 13;


        private void connect_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(roomBox.Text))
            {
                MessageBox.Show("Please enter a selection before continuing");


            }
            else
            {
                {
                    try
                    {
                        //Connects to the server
                        tc = new TelnetConnection(roomBox.Text, 23);
                        //Enables controls
                        panelAll.Enabled = true;
                    }
                    catch
                    {
                        MessageBox.Show("Server Unreachable. ");
                        panelAll.Enabled = false;
                        cState.Text = "Disconnected";
                    }

                }
            }

// Button to send login password Temp created to test login
public void p_Click(object sender, EventArgs e)
        {
            try
            {
              //sends text to server  
              tc.WriteLine("PASSWORD");

              //enables Buttons
              panelAll.Enabled = true;

              //displays return to textbox to verify login or disconnect
              rx.Text = (tc.Read());
            }
            catch
            {
                panelAll.Enabled = false;
                MessageBox.Show("Communication with device was lost.");
                cState.Text = "Disconnected";
            }
        }

----------------------------------------------- -------------------------------------------

Ответы [ 3 ]

1 голос
/ 13 октября 2011

Ваш код кажется неполным, чтобы дать полный ответ.Если возможно, предоставьте более полную логику, убранную из вашей программы.Но из того, что я могу извлечь, вот несколько непосредственных советов ...

  1. Не путайте MD5 с шифрованием.Это очень разные вещи (MD5 - это однонаправленный хэш, а шифрование - это двустороннее кодирование).Это вероятно будет источником вашей головной боли.Методы рукопожатия шифрования / хеширования должны быть согласованы обоими участниками.Если вы пытаетесь войти с помощью хеш-пароля MD5 на устройство, которое принимает только простые текстовые пароли, оно не будет распознавать его как действительный пароль.С этим сценарием буквально ничего нельзя поделать ... это должен быть простой текст.
  2. Вы предполагаете, что пароли являются ASCII?Если нет, то преобразование ASCII - плохая новость.Вероятно, здесь не проблема корня, но есть над чем подумать.

РЕДАКТИРОВАТЬ: На самом деле ... позвольте мне углубиться, потому что после дальнейших размышлений я на 90% уверен, что это ваша проблема (без дополнительной информации, конечно).

Поток логики при работе с устройством, которое поддерживает только текстовые пароли, заключается в следующем (где C - клиент [вы], а S - сервер [их]) ...

[C] Send password plain-text
[S] Got your password, thanks! I just checked it against what I know and it's good/bad

При использовании любоготип хэширования.

[C] Hash password (MD5, SHA1, etc)
[C] Send password
[S] Receive hash of password. Check against hashed password stored (or worse, hash of plain-text password stored). Respond good/bad

При шифровании соединения (когда клиент и сервер знают, какое шифрование они оба используют) ...

[C] Garble-garble-garble (password encrypted)
[S] Got it... and garble-garble-garble turns into whatever plain-text password. Checked it against local storage and .... garble-garble-garble (good/bad encrypted)

При шифровании соединения (иклиент / сервер не обязательно поддерживает одни и те же методы, но знает, как договориться о том, какие использовать) ...

[C] Which encryption methods do you support? Here's my list...
[S] Oh, well, we both support these methods. Which do you want to use?
[C] IDEA sounds good.
[S] Sounds good to me too. Start using it.
[C] Garble-garble-garble (password encrypted)
[S] Got it... and garble-garble-garble turns into whatever plain-text password. Checked it against local storage and .... garble-garble-garble (good/bad encrypted)

Как видите, очень разные методы.Они должны быть встроены в коммуникационное устройство (сервер) для успешного согласования.

0 голосов
/ 13 октября 2011

Я не думаю, что это проблема программирования. Я считаю, что это больше проблема понимания того, как на самом деле работает ваше устройство. Принимает ли он пароль в виде простого текста или принимает пароль в какой-то хешированной или зашифрованной форме?

Тот факт, что вы можете предоставить пароль через telnet, предполагает, что это обычный текст, если только в протоколе telnet не предусмотрены некоторые параметры для аутентификации.

Было бы хорошо, если бы вы могли предоставить скриншот окна telnet. Мы могли бы получить некоторые подсказки оттуда.

Я бы порекомендовал вам ввести пароль в виде простого текста, за которым следует символ новой строки \ n.

0 голосов
/ 13 октября 2011

Мне кажется, что вашим лучшим решением было бы загрузить пакет OpenSSL, установить его на устройстве и в приложении для форм, а затем использовать API-интерфейсы, чтобы использовать безопасное соединение оболочки вместо telnet для отправки команд устройства.

Таким образом, управление ключами находится за пределами вашего приложения, и вы можете использовать предварительно написанные API-интерфейсы для шифрования в тестируемом фрагменте кода.

...