Программа Delphi, генерирующая неверный CRC16, хочет воспроизвести поведение в C #

Я унаследовал приложение Delphi, которое мне нужно преобразовать в приложение C # на моей работе.

Одна часть использует то, что должно быть функцией CRC16 во внешней dll, чтобы создать контрольную сумму для некоторых данных. Проблема в том, что этот сгенерированный CRC не соответствует ни одному из CRC, которые мне удалось сгенерировать в другом месте.

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

http://www.lammertbies.nl/comm/info/crc-calculation.html

Итак, мой единственный вывод сейчас состоит в том, что приложение Delphi не генерирует действительную контрольную сумму CRC16. Это оставляет мне два варианта

1] Попробуйте выяснить, какой тип CRC он генерирует

2] Каким-то образом вызовите функции в DLL изнутри С#

Я пробовал оба и потерпел неудачу с треском.

--

Все исходники есть на гитхабе -

https://github.com/delphi2sharp/delphisharp/blob/master/CRC16Test/CRC16Test/Program.cs

https://github.com/delphi2sharp/delphisharp/blob/master/DelphiCRC16Test/Unit1.pas

и CRC.DLL тоже есть.

--

Любая помощь будет принята с благодарностью.

Спасибо


person NoPyGod    schedule 14.02.2012    source источник
comment
Знаем ли мы, о какой версии Delphi мы говорим? Если я правильно понимаю, Delphi не получал полной поддержки Unicode до 2009 года; хотя эта разница не зависит от характера данных, которые вы пытаетесь выполнить CRC...   -  person Russ Clarke    schedule 14.02.2012
comment
Регистрационные данные никогда не включают символы, кроме A-Z, 1-9. Так что это не проблема.   -  person NoPyGod    schedule 14.02.2012
comment
Я только что заметил это сообщение на форуме в MSDN; это имеет особое отношение к объектам, которые возвращают строку delphi, что здесь возможно. social.msdn.microsoft .com/forums/en-US/csharpgeneral/thread/   -  person Russ Clarke    schedule 14.02.2012
comment
На самом деле это вызывает беспокойство; в зависимости от указанной кодировки в .net они будут либо 16-битными, либо 32-битными, и это будет иметь значение для CRC.   -  person Russ Clarke    schedule 14.02.2012
comment
Я бы хотел, чтобы минусующие прокомментировали, почему они проголосовали против, особенно по вопросу с ответами и комментариями.   -  person Shaun Wilde    schedule 15.02.2012


Ответы (3)


Я думаю, что вам нужен двухэтапный подход.

1./ На данный момент напишите оболочку «unsafe/pInvoke» и вызовите родную dll.

2./ После замены приложения Delphi и управления кодированием и декодированием напишите более стандартную функцию CRC.

Вызов родной DLL не так уж и сложен, взгляните на некоторые примеры на pinvoke.net.

person Tim Jarvis    schedule 14.02.2012
comment
Это, конечно, правда, но я боюсь, что здесь мы лечим симптом, а не причину; если эта dll CRC вычисляет нестандартным способом, у вас нет гарантии того, как это может привести к столкновению в будущем. - person Russ Clarke; 14.02.2012
comment
Проверьте ответ на ваш ответ, я рассмотрел эти проблемы. Если я смогу добиться этого с помощью Pinvoke, я буду счастлив. - person NoPyGod; 14.02.2012
comment
Верно; сюжет закручивается! Если вы готовы проглотить эти опасения, то Тим и Шон абсолютно правы. P/Invoke — это то, что вам нужно. - person Russ Clarke; 14.02.2012
comment
Я согласен с Тимом, двухэтапный подход как способ избавиться от плохой реализации. У меня был похожий сценарий с плохо реализованным алгоритмом шифрования, но в этом сценарии мне пришлось разобрать сборку x86 и заново реализовать на C#; не тот подход, который я бы рекомендовал, если его можно избежать. - person Shaun Wilde; 14.02.2012

Если вам нужна обратная совместимость, почему бы вам не использовать оболочку pInvoke оригинальной родной dll.

person Shaun Wilde    schedule 14.02.2012
comment
Ваша DLL предоставляет 3 метода CRC_16, CRC_32 и CRC_CCITT, что касается фактического синтаксиса оболочки pinvoke, о котором я мог догадаться, но я не знаю, что такое CRC_MAKE (или происходит ли какое-то неявное приведение). Что находится в CRC.INC? - person Shaun Wilde; 14.02.2012
comment
CRC.INC определяет вызовы CRC.DLL. Не спрашивайте меня, как это работает, Delphi для меня новинка. CRC_MAKE определяется в верхней части CRC.INC, вам просто нужно передать 0 для этого. - person NoPyGod; 14.02.2012
comment
Ах, я не заметил дополнительных файлов в GitHub — как вы можете видеть из файлов .INC — объявление pascal должно быть в состоянии действовать как руководство к вашему pInvoke [DllImport CRC.DLL, EntryPoint=CRC_16 CharSet=CharSet. Auto, SetLastError=true] public extern static void CRC_16(byte[], int, byte); - person Shaun Wilde; 14.02.2012
comment
Возможно, вам придется поиграть со значением charset - person Shaun Wilde; 14.02.2012
comment
Продолжайте получать «Попытка чтения или записи защищенной памяти. Это часто указывает на то, что другая память повреждена. - person NoPyGod; 14.02.2012
comment
Может быть, он читает за пределы длины буфера - он завершается NULL? - person Shaun Wilde; 14.02.2012

Во-первых, я прошу прощения за то, что опубликовал это как ответ; это слишком громоздко, чтобы вставить комментарий.

Значит, у вас нет исходного кода CRC.Dll?

Глядя на него, он выглядит как еще один файл на основе Delphi, который зависит как минимум от Kernel32.dll; кроме того, что я не могу сказать об этом Mac. Наблюдение состоит в том, что это различие может быть связано с различиями Unicode между Delphi и .Net.

Однако, если вы переносите это на .Net, есть ли какая-либо причина, по которой вы не можете просто заменить этот CRC заведомо хорошим решением или вам нужно сохранить некоторую обратную совместимость? Если так; вы не можете использовать общий код CRC в .Net и сделать пакетное обновление устаревшего материала?

Если не; тогда, возможно, ответ заключается в том, чтобы отказаться от этого сделанного на заказ генератора CRC и использовать что-то, что подтверждает ваши ожидания и обеспечивает воспроизводимые точные результаты.

person Russ Clarke    schedule 14.02.2012
comment
Являются ли данные текстовыми, XML, двоичными или чем-то еще? - person Russ Clarke; 14.02.2012
comment
Обратная совместимость имеет важное значение. У нас есть база данных, полная серийных ключей для нашего приложения, которое развернуто на сотнях компьютеров по всей стране. Выполняя побитовые операции с серийным номером, мы можем видеть, какие функции нашего приложения включены для клиента. Это было бы очень просто, НО, прежде чем мы сможем выполнять эти побитовые операции, нам нужно декодировать серийный номер DES, и для этого нам нужно получить контрольную сумму CRC16 нескольких регистрационных данных пользователя и использовать их в качестве декодирования. ключ. - person NoPyGod; 14.02.2012
comment
Говоря это, мы пересматриваем нашу систему регистрации в течение следующих 6 месяцев и переходим к подходу онлайн-проверки. Когда мы это сделаем, я определенно не буду использовать ту же процедуру CRC. Но для старых клиентов (многие из них никогда не перейдут на новую систему, потому что они просто откажутся) они продолжат использовать старую систему. - person NoPyGod; 14.02.2012
comment
В таком случае; безопасный рефакторинг и пакетное обновление могут быть самым разумным вариантом; Из-за сортировочных различий и вашей неспособности понять, почему эта dll CRC не создает стандартный результат; нет никакого способа узнать, возвращает ли ваш экземпляр этой DLL через вызов платформы С# правильный результат или нет. - person Russ Clarke; 14.02.2012
comment
... как предлагает Расс, но, возможно, с дополнительным столбцом для нового CRC - даже глядя на массовые данные, вы можете увидеть то, что не соответствует здравому смыслу, то есть общий шаблон между двумя числами, который может помочь определить, где первоначальная реализация CRC была плохо реализована - затем вы можете добавить эту ошибку к своей хорошей реализации, и вуаля, у вас есть метод BadlyImplementedCRC в C # - person Shaun Wilde; 14.02.2012