Статус: Участник
Группы: Участники
Зарегистрирован: 01.06.2018(UTC) Сообщений: 10  Откуда: Санкт-Петербург Сказал(а) «Спасибо»: 1 раз
|
Всем дня доброго! Имеется код, написанный на Delphi Код:Utils:=CreateOleObject('CAPICOM.Utilities');
Signer.Certificate := Crt;
SignedData.Content:= Utils.HexToBinary(ToCAPICOM(input));
podpis := SignedData.Sign(Signer, false, 0);
Разработчик преобразует строку сначала в Utf8 (в шестнадцатеричном виде), потом подписывает данные подобным образом, применяя при этом преобразование в двоичный вид. Я знаю, что в Delphi на каждый символ приходится 2 байта, т.е. используется кодировка UCS-2. Пожалуйста, подскажите, как подобное написать в C++? Как взять нужный сертификат и подписать им - я знаю. Все работает, пока не нужно подписывать кириллицу. Как только в подписи есть знаки кириллицы - сервис перестает принимать мою подпись.
|
|
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 26.07.2011(UTC) Сообщений: 14,081   Сказал «Спасибо»: 612 раз Поблагодарили: 2375 раз в 1868 постах
|
|
|
|
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 01.06.2018(UTC) Сообщений: 10  Откуда: Санкт-Петербург Сказал(а) «Спасибо»: 1 раз
|
Автор: Андрей Писарев  Преобразования нужны,т.к. там widestring в COM. Т.е. при использовании C++ и функции CadesSignMessage подобные преобразования не нужны?
|
|
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 26.07.2011(UTC) Сообщений: 14,081   Сказал «Спасибо»: 612 раз Поблагодарили: 2375 раз в 1868 постах
|
Автор: Евгений Тонишев  Автор: Андрей Писарев  Преобразования нужны,т.к. там widestring в COM. Т.е. при использовании C++ и функции CadesSignMessage подобные преобразования не нужны? Передавать необходимо байты, как есть. |
|
|
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 01.06.2018(UTC) Сообщений: 10  Откуда: Санкт-Петербург Сказал(а) «Спасибо»: 1 раз
|
Автор: Андрей Писарев  Передавать необходимо байты, как есть. Всё равно слабо понял этот момент. Ладно, спасибо за подсказки, буду дальше Интернеты рыть.
|
|
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 26.07.2011(UTC) Сообщений: 14,081   Сказал «Спасибо»: 612 раз Поблагодарили: 2375 раз в 1868 постах
|
Delphi через COM, без преобразований, читаем в Buffer из файла: Код:
Buffer: WideString;
...
FileStm = TFileStream.Create(...)
Buffer = SysAllocStringByteLen(размер файла)
FileStm.ReadBuffer(Buffer, размер файла)
SignedData.Content:=Buffer;
Примеры на C++ в SDK или в MSDN - пример |
|
|
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 26.07.2011(UTC) Сообщений: 14,081   Сказал «Спасибо»: 612 раз Поблагодарили: 2375 раз в 1868 постах
|
Автор: Евгений Тонишев  Автор: Андрей Писарев  Передавать необходимо байты, как есть. Всё равно слабо понял этот момент. Ладно, спасибо за подсказки, буду дальше Интернеты рыть. Необходимо корректно передавать на вход функции данные. Обычно это основная проблема, если не смотреть работающие примеры, с кодировкой, например. Также, если требуется подписывать файлы больше, например, 5-10 мб - лучше использовать поточные криптографические функции. В данном случае смотреть примеры с CryptMsgOpenToEncode\CryptMsgOpenToDecode, CryptMsgUpdate, заодно и прогресс в % подписи больших файлов можно визуализировать. |
|
 1 пользователь поблагодарил Андрей * за этот пост.
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 01.06.2018(UTC) Сообщений: 10  Откуда: Санкт-Петербург Сказал(а) «Спасибо»: 1 раз
|
Автор: Андрей Писарев  Delphi через COM, без преобразований, читаем в Buffer из файла: Я правильно понимаю, что в Вашем примере ключевым является использование WideString вместо String? Если так, то Ваш код не работает в моё случае без дополнительных преобразований. На сайте, где я пытаюсь проверить подпись, перед тем, как подписывать данные, производятся следующие преобразования данных: Код:function _to_utf8_hex(s) {
var c, d = "";
for (var i = 0; i < s.length; i++) {
c = s.charCodeAt(i);
if (c <= 0x7f) {
d += _to_hex(c)
} else if (c >= 0x80 && c <= 0x7ff) {
d += _to_hex(((c >> 6) & 0x1f) | 0xc0);
d += _to_hex((c & 0x3f) | 0x80)
} else {
d += _to_hex((c >> 12) | 0xe0);
d += _to_hex(((c >> 6) & 0x3f) | 0x80);
d += _to_hex((c & 0x3f) | 0x80)
}
};
return d
}
и затем они подписываются подобным образом Код:function SignTextWorker(SigData, Signer, silent, data) {
if (data.convert_to_utf8 == 1) {
var CU = getCAPICOMObject("Utilities"),
text = _to_utf8_hex(data.text);
if (text.length % 4) text += '00';
SigData.Content = CU.HexToBinary(text)
} else SigData.Content = data.text;
return SigData.Sign(Signer, false, CAPICOM_ENCODE_BASE64)
}
Я так понимаю, это связано с тем, что плагин для браузера не умеет напрямую работать с двоичными данными, о чем написано в данной статье. Я сделал такое же преобразование в Delphi: Код:function ToCAPICOM(input: string) : string;
var
ch: Char;
i, code: Integer;
begin
Result := '';
for i := 1 to input.Length do
begin
code := Ord(input[i]);
if code <= 127 then
begin
Result := Result + IntToHex(code, 2);
end
else if (code >= 128) and (code <= 2047) then
begin
Result := Result + IntToHex((((code shr 6) and 31) or 192), 2);
Result := Result + IntToHex(((code and 63) or 128), 2);
end
else
begin
Result := Result + IntToHex(((code shr 12) or 224), 2);
Result := Result + IntToHex((((code shr 6) and 63) or 128), 2);
Result := Result + IntToHex(((code and 63) or 128), 2);
end;
end;
if Result.Length mod 4 > 0 then
begin
Result := Result + '00';
end;
end;
//Подпись
function podpis(input: String) : String;
begin
Utils:=CreateOleObject('CAPICOM.Utilities');
Signer.Certificate := Crt;
SignedData.Content:= Utils.HexToBinary(ToCAPICOM(input));
podpis := SignedData.Sign(Signer, false, 0);
end;
Все заработало. Без преобразования с помощью функции ToCAPICOM подпись формируется неверно и сайт ее отклоняет. Так же, как я выше говорил, не работает вариант с WideString. Вопрос же состоит в том, как подобные преобразования написать на C++? Автор: Андрей Писарев  Обычно это основная проблема Тяжелая тема, если честно. :(
|
|
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 26.07.2011(UTC) Сообщений: 14,081   Сказал «Спасибо»: 612 раз Поблагодарили: 2375 раз в 1868 постах
|
Цитата:Вопрос же состоит в том, как подобные преобразования написать на C++? Из SDK на C++ не работают примеры? |
|
|
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 01.06.2018(UTC) Сообщений: 10  Откуда: Санкт-Петербург Сказал(а) «Спасибо»: 1 раз
|
Автор: Андрей Писарев  Из SDK на C не работают примеры? Да примеры то работают, даже кириллицу подписывают и нормально делают проверку данной подписи (возвращают тот же текст, что и был подписан). Но площадка не принимает подпись.
|
|
|
|
|
|
Быстрый переход
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.
Important Information:
The Форум КриптоПро uses cookies. By continuing to browse this site, you are agreeing to our use of cookies.
More Details
Close