C# 中 NX 客户端中的密码加扰算法

The password scrambling algorithm in NX client in c#

本文关键字:算法 密码 NX 客户端      更新时间:2023-10-16

我目前正在尝试从QT-C++移植NX的密码加扰算法到 C#。

源:http://www.nomachine.com/ar/view.php?ar_id=AR01C00125

我当前的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace mynamespace
{
class NxScramble
{
    string ToScramble = "";
    int numValidCharList = 85;
    String dummyString = "{{{{";
    char[] validCharList = new char[]
    {
      '!',  '#',  '$',  '%',  '&',  '(', ')',  '*',  '+',  '-',
      '.',  '0',   '1',  '2',   '3',  '4',  '5',  '6', '7', '8',
      '9', ':',  ';',  '<',  '>',  '?',  '@',  'A',  'B', 'C',
      'D',  'E',  'F',  'G',  'H',  'I',  'J',  'K',  'L', 'M',
      'N', 'O',  'P',  'Q',  'R',  'S',  'T', 'U', 'V', 'W',
      'X',  'Y',  'Z',  '[', ']',  '_',  'a',  'b',  'c',  'd',
      'e',  'f',  'g',  'h',  'i',  'j',  'k',  'l',  'm',  'n',
      'o',  'p',  'q',  'r',  's',  't',  'u',  'v',  'w',  'x',
      'y',  'z',  '{',  '|',  '}'
    };
    public NxScramble(string s)
    {
        ToScramble = s;
    }
    public string scrambleString()
    {
        string sRet = "";
        if (ToScramble == null || ToScramble.Equals(""))
        {
            return ToScramble;
        }
        string str = encodePassword(ToScramble);
        if (str.Length < 32)
        {
            str += dummyString;
        }
        for (int iR = (str.Length - 1); iR >= 0; iR--)
        {
            //
            // Reverse string
            //
            sRet += str.ElementAt(iR);
        }
        if (sRet.Length < 32)
        {
            sRet += dummyString;
        }
        int k = getRandomValidCharFromList();
        int l = k + sRet.Length - 2;
        sRet.Insert(0, k.ToString());
        string retStr = "";
        for (int i1 = 1; i1 < sRet.Length; i1++)
        {
            int j = findCharInList(sRet.ElementAt(i1));
            if (j == -1)
            {
                return ToScramble;
            }
            int i = (j + l * (i1 + 1)) % validCharList.Length;
            /*
             * sRet.ref(i1) = validCharList[i];
             */
            retStr += validCharList[i];
        }
        char c = (char)(getRandomValidCharFromList() + 2);
        sRet += c;
        retStr = retStr.Replace("&", @"&amp;");
        retStr = retStr.Replace(""", @"&quot;");
        retStr = retStr.Replace("'", @"&apos;");
        retStr = retStr.Replace("<", @"&lt;");
        retStr = retStr.Replace(">", @"&gt;");
        return retStr;
    }
    private string encodePassword(string p)
    {
        string sPass = ":";
        string sTmp = "";
        if (p.Equals(""))
        {
            return "";
        }
        for (int i = 0; i < p.Length; i++)
        {
            char c = (char)p.ElementAt(i);
            sTmp = String.Format("{0:d}:", (c + i + 1));
            sPass += sTmp;
            sTmp = "";
        }
        return sPass;
    }
    private int findCharInList(char c)
    {
        int i = -1;
        for (int j = 0; j < numValidCharList; j++)
        {
            if (validCharList[j] == c)
            {
                i = j;
                return i;
            }
        }
        return i;
    }
    private char getRandomValidCharFromList()
    {
        int k = DateTime.Now.Second;
        return validCharList[k];
    }
}
}

它从给定的密码生成一个字符串,并将其添加到nxclient 的 XML 配置文件:

        NxScramble nxs = new NxScramble(passPhrase);
        string ScambledPass = nxs.scrambleString();
        string nxconfig = @"
        ....
        ....
        <group name='Login' >
        <option key='Auth' value='"+ ScambledPass + @"' />
        <option key='Guest Mode' value='false' />
        <option key='Guest password' value='' />
        <option key='Guest username' value='' />
        <option key='Login Method' value='nx' />
        <option key='Public Key' value='
        .........
        .........
        ' />
        <option key='User' value='" + username + @"' />
        </group>
        ";

但是NXClient一直说"身份验证失败"。所以我很确定我的 C#-Port 的 C++ 代码中一定有错误。特别是我不确定原始代码的这一行: sRet.ref(i1) = validCharList[i];

我不知道 ref(i1) 在做什么。

如果有人发现我的错误:)那就太好了

提前致谢

scrambleString() 的上层代码部分确实初始化并处理sRet,以及最后返回的retStr下部,使其工作 sRet根本没有使用。您可能应该结合retStr/sRet,也许只是使用一个字符串...

sRet.ref(i1) = validCharList[i]

上面的代码只是一个简单的字符赋值,替换 pos 处的字符 i1 sRet 在 pos i 的字符串validCharList中带有字符。