powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Microsoft CrytoAPI и RSA
4 сообщений из 4, страница 1 из 1
Microsoft CrytoAPI и RSA
    #39642040
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Никто не знает, как работает функция CryptDecrypt в MS CryptoAPI?

Проблема в следующем: мне нужно зашифровать некие данные алгоритмом RSA с длиной ключа 1024 бита, чтобы потом их можно было расшифровать через CryptoAPI. На данный момент имею следующий код (вырезал всё лишнее):

В CryptoAPI генерируется ключевая пара RSA и экспортируется публичный ключ
Код: pascal
1.
2.
3.
4.
...
CryptGenKey(FProvider, AT_KEYEXCHANGE, 1024 shl 16, FUserKeyPair); 
CryptExportKey(FUserKeyPair, 0, PUBLICKEYBLOB, 0, @Key[0], BlobSize);
...


Потом выгруженный ключ делится на экспоненту и модуль:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
  procedure ExtractPublicKey(Blob: PByte; BlobSize: Integer; E, N: TBigNum);
  var
    PubKeyHdr: TPublicKeyStruc;
    RsaPubKey: TRsaPubKey;
    ModSize: Integer;
  begin
    if BlobSize < SizeOf(RsaPubKey) + SizeOf(PubKeyHdr) then
      raise Exception.Create('Invalid size of PUBLICKEYBLOB.');
    Move(Blob^, PubKeyHdr, SizeOf(PubKeyHdr));
    Inc(Blob, SizeOf(PubKeyHdr));
    Move(Blob^, RsaPubKey, SizeOf(RsaPubKey));
    Inc(Blob, SizeOf(RsaPubKey));
    ModSize := RsaPubKey.bitlen shr 3;
    if ModSize > BlobSize - SizeOf(RsaPubKey) - SizeOf(PubKeyHdr) then
      raise Exception.Create('Invalid size of PUBLICKEYBLOB.');
    E.CopyDigit(RsaPubKey.pubexp);
    N.CopyBytes(Blob, ModSize);
  end;


Т.к. в описании функции CryptDecrypt сказано что она использует PKCS #1 Padding , то реализовал его таким образом:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
  function PKCS1Padding(Data: Pointer; Size: Integer; BitLen: Integer): TBytes;
  var
    Bound: Integer;
    Index: Integer;
  begin
    if (BitLen mod 8 > 0) or (Size + 11 > BitLen shr 3) then
      raise Exception.Create('Invalid bit length or data is too large.');
    Bound := BitLen shr 3;
    SetLength(Result, Bound);
    PWord(Result)^ := $0200;
    Dec(Bound, Size);
    for Index := 2 to Bound - 1 do
      Result[Index] := 1 + Byte(Random(255));
    Result[Bound] := $00;
    Move(Data^, Result[Bound + 1], Size);
  end;


Cамо шифрование выглядит как-то так:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
var
  Message: string;
  PubKey: TBytes;
  Binary: TBytes;
  MsgNum: TBigNum;
...
  CAPI.PublicKeyExport(PubKey); // CAPI - самописная обёртка над CryptoAPI
  // RSA - класс RSA из библиотеки uCrypto: https://github.com/arkusuma/uCrypto
  ExtractPublicKey(PByte(PubKey), Length(PubKey), RSA.E, RSA.N); 
  Binary := PKCS1Padding(PByte(Message), Length(Message) * SizeOf(Char), 1024);
  MsgNum := TBigNum.CreateBytes(PByte(Binary), Length(Binary));
  try
    Assert(MsgNum.Compare(RSA.N) < 0, 'M must be in range of 0..N-1');
    RSA.Encrypt(MsgNum); // inline-функция для вызова MsgNum.PowMod(E, N);
    ... 


И в итоге при расшифровке текста в этот момент мы получаем NTE_BAD_DATA:
Код: pascal
1.
2.
3.
4.
  ...
  if not CryptDecrypt(FUserKeyPair, 0, TRUE, 0, Data, DataSize) then
    RaiseLastOSErrorEx(sFailedDecryption);
  ...



Шифрование и расшифровка что в uCrypto что в CryptoAPI работают нормально, если расшифровывать в той же библиотеке, в какой и шифруется. А вот как их заставить работать между собой? Возможно кто-нибудь знает какие-то нюансы, которые я упустил?

P.S: Шифрование требуется произовдить без CryptoAPI, т.к. в итоге данные могут шифроваться там, где его нет (linux, etc), в данный момент это не рабочее приложение, а испытательный стенд, где я пытаюсь понять как оно вообще работает.
...
Рейтинг: 0 / 0
Microsoft CrytoAPI и RSA
    #39642055
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мда, разобрался, данные после PKCS1Padding() нужно было перевернуть...
...
Рейтинг: 0 / 0
Microsoft CrytoAPI и RSA
    #39642092
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp,

дописал бы...
...
Рейтинг: 0 / 0
Microsoft CrytoAPI и RSA
    #39642201
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
makhaonalekcvp,
дописал бы...

Там нечего дописывать, одну строчку поменять (BE = Big-Endian):
Код: pascal
1.
MsgNum := TBigNum.CreateBytesBE(PByte(Binary), Length(Binary));


После этого всё работает. Просто я когда экспериментировал модуль пробовал так загружать, не помогало. А оказывается надо было сообщение перевернуть, т.к. оно по-умолчанию в Big-Endian формате.
...
Рейтинг: 0 / 0
4 сообщений из 4, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Microsoft CrytoAPI и RSA
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]