在C#中通过TCP发送密码

时间:2011-10-13 02:20:42

标签: c# .net networking telnet

我已经离开了练习程序员,所以基本上又是新手。

我正在做的是通过Telnet或TCP登录设备。而不是通过类型命令控制设备我使用自定义表单应用程序通过预编程的按钮发送类型字符串命令。该设备是旧的编解码器。我的软件的目的是创建一个从PC上使用的按钮控制器。

我遇到的问题是我的一些设备受密码保护,而有些则不受(不同的固件)。这不能改变。密码保护是我遇到的问题。

我使用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或其他方式发送编码密码。

我知道我的密码是正确的,因为我可以在Windows中加载telnet并在那里登录。任何有助于此客户端与服务器进行身份验证的帮助将非常感激。


原谅长度。由于我无法回复,我必须编辑。我认为我在MD5上感到困惑...在阅读回复后我认为我的问题是ASCII。我需要纯文本。

好的,所以这是我的初学者条纹明亮的地方。这是我第一次尝试编程涉及任何类型的网络(如果它不是那么明显)。从阅读回复中我认为我的第一个问题是ASCII。我假设被发送虽然是纯文本。鉴于当我连接到具有不需要密码登录的相同客户端的服务器时...... ASCII工作正常。

因此,如果我要使用纯文本,那么我将如何使用纯文本而不是字节转换?假设我假设ASCII是发送纯文本的方式是错误的...我现在认为它是。

我添加了更多代码来帮助解决这个问题。

使用Windows telnet客户端时,设备会提示输入密码,当您在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 个答案:

答案 0 :(得分:1)

您的代码似乎有点不完整,无法给出完整答案。如果可能,提供从程序中删除的更完整的逻辑流程。但是从我能收集的内容来看,这里有一些直接的提示......

  1. 不要将MD5与加密混淆。它们是非常非常不同的东西(MD5是单向散列,而加密是双向编码)。这很可能成为您头痛的根源。加密/散列握手方法必须由两位参与者达成一致。如果您尝试使用密码的MD5哈希登录到只接受纯文本密码的设备,则它不会将其识别为有效密码。对于这种情况,你几乎无能为力......它必须是纯文本。
  2. 您认为密码是ASCII吗?如果没有,ASCII转换是坏消息。可能不是这里的根本问题,而是需要考虑的事情。
  3. 编辑:其实......让我更深入一点,因为经过深思熟虑后,我大约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)
    

    正如您所看到的,方法非常不同。必须将这些内置到通信设备(服务器)中才能成功协商。

答案 1 :(得分:0)

在我看来,您最好的解决方案是下载OpenSSL软件包,将其安装在设备和表单应用程序上,然后使用API​​来使用安全shell连接而不是telnet来发送设备命令。 / p>

这样,密钥管理就在您的应用之外,您可以使用预先编写的API在经过测试的代码中进行加密。

答案 2 :(得分:0)

我不认为这是一个编程问题。我相信这更像是一个了解你的设备实际工作方式的问题。它是以纯文本形式接受密码,还是以某种散列或加密形式接受密码?

您可以通过telnet提供密码这一事实表明它是纯文本,除非telnet协议为某些用于身份验证提供了条件。

如果您能提供telnet窗口的屏幕截图,那将是件好事。我们或许可以从那里得到一些提示。

我建议您提交纯文本密码,后跟\ n新行字符。