Priya Karthish Ответов: 2

Проблема преобразования кода ASCII из VB в C#


Я преобразовал следующий криптокод из VB в C#. Проблема, с которой я сталкиваюсь, заключается в том, что если ввод с является ABCD,то в VB он преобразуется как
æf~m

‡

а в C# он преобразуется как
æf~m

?


Если входной сигнал s равен 15 символам, то он преобразуется правильно. Вот код VB:-
Private Function cryptEntry(s$) As String

    Dim k$, r$, i%

    k = "§$=)%;:-:*(""§%""§=("             

    r = Left$(s + String(15, Chr$(32)), 15)           

    For i = 1 To Len(r)

        Mid$(r, i, 1) = Chr$(Asc(Mid$(r, i, 1)) Xor Asc(Mid$(k, i, 1)))

    Next i

    cryptEntry = r

End Function


Что я уже пробовал:

Мой код на языке Си# :-

private string cryptEntry(string s)
        {
            string k = "", r = "";
            try
            {
                k = "§$=)%;:-:*(\"§%\"§=(";
                string insideString = "", concatString = "", leftString = "";
                insideString = new String(' ', 15);
                concatString = String.Concat(s, insideString);
                leftString = concatString.Substring(0, 15);
                r = leftString;
                StringBuilder sb = new StringBuilder(r);
                for (int i = 0; i < r.Length; i++)
                {
                    string rmid = r.Substring(i, 1);
                    string kmid = k.Substring(i, 1);
                    sb[i] = Convert.ToChar((Convert.ToInt32(Convert.ToChar(rmid)) ^ Convert.ToInt32(Convert.ToChar(kmid))));
                }
                r = sb.ToString();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            return r;

        }

Maciej Los

Это очень хорошо сформулированный вопрос!

Priya Karthish

Спасибо тебе

2 Ответов

Рейтинг:
4

Richard Deeming

Проблема в том, что VB-это Asc и Chr функции не имеют прямого эквивалента в C#. Они прекрасно работают, когда вы имеете дело с символами, код ANSI которых меньше, чем 128 Кроме того, они будут отличаться от значений Unicode, с которыми имеет дело C#.

В вашем примере 13 - й символ вывода из вашего VB - кода будет равен 8225 (). Тот же символ из кода C# будет 135*. Это визуально то же самое. тот же персонаж[^], но не та же самая кодовая точка.

Если вы можете изменить свой VB код для использования AscW и ChrW, то ваш вывод C# будет соответствовать.

В противном случае вам нужно будет добавить ссылку на Microsoft.VisualBasic сборка и использование функций VB:

private string cryptEntry(string s)
{
    const string k = "§$=)%;:-:*(\"§%\"§=(";
    string r = s.PadRight(15, ' ').Substring(0, 15);
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < r.Length; i++)
    {
        sb.Append(Strings.Chr(Strings.Asc(r[i]) ^ Strings.Asc(k[i])));
    }
    return sb.ToString();
}
Строки.Метод АСК (Майкрософт.На Языке VisualBasic) | Майкрософт Документы[^]
Строки.Метод Chr(Int32) (Microsoft.VisualBasic) | Microsoft Docs[^]

* NB: Выход из строя Asc и Chr зависит от кодовой страницы компьютера, на котором выполняется ваш код. Если есть хоть какая-то возможность того, что ваш код будет работать на компьютерах с разными локалями, то вы не можете гарантировать, что выходные данные будут совпадать.


Maciej Los

Часть после "* NB" - самая важная.
5ed!

Priya Karthish

Спасибо

Рейтинг:
1

Maciej Los

Что ж...
Я изменился cryptEntry способ получения этой формы:

private string cryptEntry(string s)
{
    char[] kchars = "§$=)%;:-:*(\"§%\"§=(".ToArray();
	char[] rchars = s.PadRight(15, ' ').Substring(0,15).ToArray();
	
    for (int i = 0; i < rchars.Length; i++)
        rchars[i] = (char)((int)rchars[i] ^ (int)kchars[i]);

	return new string(rchars);
}

и проверил это таким образом:
string input  = "ABCD";
string output  = cryptEntry(input);
char[] o = output.ToArray();
for (int i = 0; i < o.Length; i++)
    Console.WriteLine("{0} {1}", o[i], (int)o[i]);


Это создает тот же набор символов, что и функция vb:
æ 230
f 102
~ 126
m 109
05 5
1B 27
1A 26
13
1A 26

 10
08 8
02 2
‡ 135
05 5
02 2


0x01AA

Хороший вариант, 5. но это s+ new String((char)32, 15)).Substring(0,15) можно написать гораздо проще: s.PadRight(15, ' ') :)

Maciej Los

Моя виртуальная пятерка, Бруно!
Кстати: я очень сосредоточился на функции VB ;)

0x01AA

Спасибо :). Я был не совсем прав. Чтобы быть в безопасности это должно быть больше s.PadRight(15, ' ').Substring(0,15)... Это на всякий случай s это все уже длиннее, чем 15 символов.

Maciej Los

Хорошая мысль!

Priya Karthish

Спасибо за ваши усилия. Я отладил свой код и ваш тоже. Значение XOR одинаково в обоих случаях. Зашифрованный код фактически сохраняется в базе данных в виде типа данных varchar. Вот где на самом деле произошло несоответствие.

Maciej Los

ОК.
Если ваш вопрос был решен, пожалуйста, примите мой ответ.

Priya Karthish

К сожалению, это не решается. При сохранении в базе данных sql, все еще существует mistmatch. В моем проекте шифрование происходит с помощью c#, а дешифрование выполняется с помощью dll, сделанной в VB. После шифрования, вместо doubledagger(‡), questionmark(?) есть, мне нужно решение для этого. Посмотрите на вопрос выше, и вы увидите разницу.

Maciej Los

Как я уже упоминал, я протестировал метод c# и vb. Оба возвращают один и тот же набор символов. Итак, я не знаю, почему у вас есть 2 разных результата...

Richard Deeming

Как вы тестировали метод VB? С помощью Strings.Chr и Strings.Asc дать мне 8225 как 13-й символ, а не 135.

Если я изменю его на ChrW и AscW, Я получаю тот же результат, что и код C#.

Maciej Los

Я скопировал cryptEntry() затем функция для модуля VBA:

Sub Main()
    Dim s As String, o As String

    s = "ABCD"
    o = cryptEntry(s)
    
    For i = 1 To Len(o)
        Debug.Print Mid(o, i, 1), Asc(Mid(o, i, 1))
    Next

End Sub

Результат: 135 на 13-м символе.

Richard Deeming

Может быть, это проблема с кодовой страницей. Asc и Chr возвращайте различные результаты в зависимости от текущей кодовой страницы, тогда как AscW и ChrW всегда используйте Юникод.

Maciej Los

Наверное, ты прав, Ричард.
Я использую польскую версию MS Office, где кодовая страница по умолчанию-Windows-1250 (или 1252). Панель кода VBA использует новый шрифт Curier (Центральная Европа), так что...
Я постараюсь использовать разные способы и дам вам знать.

Richard Deeming

1252 здесь.

Некоторые возможно полезные сведения в этом ответе на ошибку сервера:
windows - Как я могу вручную определить кодовую страницу и локаль текущей ОС - ошибка сервера[^]

Maciej Los

Ну, редактор кода VBA использует ту же кодовую страницу из региональных настроек ОС Windows: MS Access VBA code editor кодировка символов и копирование/вставка - переполнение стека[^]
[РЕДАКТИРОВАТЬ]
1250 здесь. Проверено таким образом:

    Dim enc As Variant
    enc = Application.DefaultWebOptions.Encoding
    Debug.Print enc


DefaultWebOptions.Свойство кодирования (Excel) | Microsoft Docs[^]