Pinvoking adwapi.dll - функции cryptDecrypt и cryptEncrypt, странная проблема - PullRequest
0 голосов
/ 20 марта 2011

Я наблюдаю странное поведение этой функции, строка, которую я хочу зашифровать, содержит 14 байтов, если я использую функцию для отправки длины буфера = 14, она завершается неудачно («внутренняя ошибка» - очень описательная и наиболее полезная) код ошибки), но работает, когда длина буфера (и самого буфера) составляет 128 байт.

Я преодолел эту проблему, создав массив размером 128 байт, и скопировал 14 байтов из простого текста (который я хочу зашифровать),

Когда я расшифровываю эти байты, я должен еще раз передать функции весь 128-байтовый массив (в котором теперь зашифрован каждый байт, даже те, что из # 13- # 127 (что, я думаю, следовало ожидать)). К счастью для меня, первые 14 байтов расшифровываются, как и должны, а остальные - бессмысленные.

Я хотел бы знать, почему метод шифрования завершается неудачей, если входящий буфер имеет размер не более 128 байт, а также почему для функции дешифрования также требуется массив из 128 байт, это какая-то дополнительная операция?

Вот как я вызываю функцию шифрования:

System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();  // encoding type
byte[] buff = new byte[128];     // this is my buffer array, instantiated and initiated
string String2Encrypt = "Testing";      // this is the string I need encrypted
byte[] tempo = encoding.GetBytes(String2Encrypt);   // getting bytes from string
Buffer.BlockCopy(tempo, 0, buff, 0, tempo.Length);    // copying the small array into the large one
uint inputlength = Convert.ToUInt32(tempo.Length);   // getting the size of the small array 


bool DidIt = UnsafeNativeMethods.CryptEncrypt(MyKey, IntPtr.Zero, 1, 0, buff, ref inputlength, outputdatalength);     // calling the function

// в этом случае MyKey является указателем на ключ шифрования, 2-й аргумент равен нулю, 3-й является «истиной» (больше нет данных), нет флагов, массив байтов (128), в этом случае Testing.Length это 7, 128

Вот как я расшифровал это:

IntPtr UserKeyLocal = MyUserKey;     // taking an argument (MyUserKey) and "filling" the local variable, not really relevant
byte[] dataCopy = new byte[buff.Length];   // init and insta the datacopy array (128 byte)
Buffer.BlockCopy(buff, 0, dataCopy, 0, (int)buff.Length);   // copying the argument array into a local version (I used this for testing to go around another problem), irrelevant
uint locinputlength = inputlength;  // another argument made local
bool DidIT = UnsafeNativeMethods.CryptDecrypt(UserKeyLocal, IntPtr.Zero, true, 0, dataCopy, ref locinputlength);     // calling the function

Результат будет выглядеть так: Тестирование? R ???? 7? Д ????? $ ?? ?? щ м%? Б ?? е? Стоит? 74p?) N9 ?? ш? R * O) Е i?+?> [& alpha; S ???} Ct? п? & ?? б? Р!? и1 ??%? JQ ??? /? тр? 5wB ????

Он почти работает, как задумано, но мне нужно иметь возможность получить ТОЛЬКО часть "Тестирование" строки без использования трюков, таких как подстрока.

То, что я пытаюсь сделать (возможно, есть альтернативный способ), это; У меня есть двоичный файл (файл), в котором есть «Тестирование», зашифрованное открытым ключом, который я получил из сертификата, который я экспортировал из SmartCard. Мне нужно проверить (расшифровать) этот файл с помощью моей SmartCard (я использую ее CSP) с закрытым ключом. Как видите, это ПОЧТИ работает.

Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 20 марта 2011

Я думаю, причина того, что буфер должен быть 128 байтов, заключается в том, что используется блочный шифр.В этом случае длина буфера должна быть кратна размеру блока.При использовании блочного шифра буфера в любом случае может потребоваться больше размера данных, чтобы в него могли быть записаны зашифрованные или дешифрованные данные (длина (зашифрованная)! = Длина (открытый текст)).

После вызова CryptDecrypt параметр pdwDataLen (locInputLength в вашем коде) будет содержать длину фактических данных, которые были расшифрованы.Если вы берете только первые locInputLength байтов dataCopy, это даст вам то, что вам нужно?

Ссылки: http://msdn.microsoft.com/en-us/library/aa379913(VS.85).aspx http://msdn.microsoft.com/en-us/library/aa379924(VS.85).aspx

0 голосов
/ 21 марта 2011

Да, это сделал! просто как пирог!

            byte[] buffer = new byte[locinputlength];
            Buffer.BlockCopy(dataCopy, 0, buffer, 0, (int)locinputlength);
            return buffer;

Одна из тех вещей, которую вы просто не "видите", пока не отступите немного назад и не посмотрите на вещь с несколько иной точки зрения;)

...