Помогите с переводом фрагмента кода

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by #Smith, 6 Oct 2013.

  1. #Smith

    #Smith New Member

    Joined:
    20 Jun 2010
    Messages:
    96
    Likes Received:
    2
    Reputations:
    0
    Приветствую, участники форума.
    Прошу помощи в решении такой непростой задачи:
    Перевожу код с C на Delphi.
    Язык C я примерно знаю, но в тупик меня загнала библиотека gmp и её функции.
    Во первых, прошу знающих людей объяснить мне просто и по-русски, что это за функции mpz_... и какие атрибуты они принимают.
    Во вторых, есть ли какие-то аналоги, и чем в Delphi их можно заменить.
    Поиск уже весь перерыл.
    Инфы очень мало.


    Code:
    #include "gmp.h"
    
    bool Sign(BYTE pbSignature[128])
    {
    	const BYTE pbN[128] = 
    	{
    		...массив значений...
    	};
    	const BYTE pbD[128] = 
    	{
    		...массив значений...
    	};
    	mpz_t n, d, m, c;
    	u32 dwBytes;
    
    	mpz_init(n);  //как я понял, инициализация
    	mpz_init(d);
    	mpz_init(m);
    	mpz_init(c);
    
    	mpz_import(n, 128, 1, 1, 0, 0, pbN);  //очевидно, что это функции загрузки значений, но я не понял, что задают занчения 1, 1, 0, 0, 
    	mpz_import(d, 128, 1, 1, 0, 0, pbD);
    	mpz_import(m, 128, 1, 1, 0, 0, pbSignature);
    	mpz_powm(c, m, d, n);  //похоже на возведение в степень, но также не понятны все атрибуты
    	dwBytes = 128 - (mpz_sizeinbase(c, 2) + 7)/8;
    	mpz_export(pbSignature + dwBytes, NULL, 1, 1, 0, 0, c);
    
    	mpz_clear(c);  //освобождение занимаемой памяти
    	mpz_clear(m);
    	mpz_clear(d);
    	mpz_clear(n);
    
    	return true;
    }
     
  2. alexey-m

    alexey-m Elder - Старейшина

    Joined:
    15 Jul 2009
    Messages:
    518
    Likes Received:
    100
    Reputations:
    37
    на офицальном сайте вроде все же написано или нет?
    описание параметров передаваемых в функции описано в доке
    описание типа mpz_t должно быть где-то gmp.h
     
  3. Империал

    Joined:
    11 Mar 2010
    Messages:
    1,224
    Likes Received:
    58
    Reputations:
    1
    Для того что бы перевести программу с одного языка на другой, нужно знать оба этих языка
     
  4. #Smith

    #Smith New Member

    Joined:
    20 Jun 2010
    Messages:
    96
    Likes Received:
    2
    Reputations:
    0
    Молодец. Какой ты умный!
    Я бы без твоего дельного совета так бы и не догадался!

    А ещё знаешь, чтобы есть пищу ложкой - нужны руки, чтобы держать ложку.

    PS. Честно, задрали выёживаться.
    Не можешь помочь или не хочешь - так промолчи.
    А то этот флуд и дешёвые понты уже так надоели.
     
    #4 #Smith, 8 Oct 2013
    Last edited: 8 Oct 2013
  5. ky_kask

    ky_kask Member

    Joined:
    18 Nov 2009
    Messages:
    73
    Likes Received:
    81
    Reputations:
    6
    http://gmplib.org/manual/Initializing-Integers.html << описуха. твой код использует эту гадость.

    http://gmplib.org/manual/ << манул по этой гадости.

    если че - это линуховая примочка. Переводить ее на вынь бессмысленно.

    P.S: https://www.google.ru/#newwindow=1&q=gmp+lib+Delphi попробуй тут порыться.. мало ли чего попадется. Может и портировали ее туда уже.
     
    #5 ky_kask, 12 Oct 2013
    Last edited: 12 Oct 2013
  6. neviens

    neviens Member

    Joined:
    9 Oct 2013
    Messages:
    82
    Likes Received:
    28
    Reputations:
    3
    >#Smith
    Это подпрограмма электронной подписи чего-то. Основа её- mpz_powm(), так-же известна как modexp(). Выполняет алгорим x = y ^ e mod m, который является основой криптоалгоритма RSA. Остальные функции служат только для форматирования данных для mpz_powm().
    Я не спец по Delphi, только знаю, что там есть соответствующий кусок кода в библиотеке FGInt, который называется FGIntModExp(). Соответственно, надо смотреть, каким образом он вызывается и как для него подготавливаются данные.
    А данные следующие- модуль pbN, приватная экспонента pbD, входные данные pbSignature (обычно SHA хеш чего-то). Результат вычислений уходит обратно в pbSignature.
    Eщё надо учесть, что в наши дни RSA длиной 128 бит ломается за считаные часы, если не минуты.

    Err, с битами там всё впорядке- их 1024 там.
     
    #6 neviens, 13 Oct 2013
    Last edited: 13 Oct 2013
    1 person likes this.
  7. #Smith

    #Smith New Member

    Joined:
    20 Jun 2010
    Messages:
    96
    Likes Received:
    2
    Reputations:
    0
    Спасибо.
    Картина начинает прояснятся.
    Но pbD и pbN - это массивы, размерностью 128 байт.
    Неужели, эта криптографическая функция рассматривает их, как просто два больших числа?
    И можно поподробней про форматы.
    Мне это примерно понятно, но, что означают таинственные флаги с нолём и единицей в функциях?
     
    #7 #Smith, 13 Oct 2013
    Last edited: 13 Oct 2013
  8. neviens

    neviens Member

    Joined:
    9 Oct 2013
    Messages:
    82
    Likes Received:
    28
    Reputations:
    3
    Массивы байтов только одна из удобных форм хранения больших чисел, для mpz_powm() они становятся понятными только после преобразования функцией mpz_import(). Скорее всего функция импорта универсальна и способна импортировать и другие форматы, например, base64, base32, base10 итд, если конкретный формат и размер числа задать в аргументах ф-ии.
     
  9. #Smith

    #Smith New Member

    Joined:
    20 Jun 2010
    Messages:
    96
    Likes Received:
    2
    Reputations:
    0
    Мои эксперименты с кодом продолжаются.
    Но кажется, я опять попал в тупик.
    Похоже, что я получаю неправильные выходные данные.

    Обо всём по порядку.
    Оригинальный код:
    Code:
    bool Sign(BYTE pbSignature[128])
    {
    	const BYTE pbN[128] = 
    	{
    		0xD8,0x7B,0xA2,0x45,0x62,0xF7,0xC5,0xD1,
    		0x4A,0x0C,0xFB,0x12,0xB9,0x74,0x0C,0x19,
    		0x5C,0x6B,0xDC,0x7E,0x6D,0x6E,0xC9,0x2B,
    		0xAC,0x0E,0xB2,0x9D,0x59,0xE1,0xD9,0xAE,
    		0x67,0x89,0x0C,0x2B,0x88,0xC3,0xAB,0xDC,
    		0xAF,0xFE,0x7D,0x4A,0x33,0xDC,0xC1,0xBF,
    		0xBE,0x53,0x1A,0x25,0x1C,0xEF,0x0C,0x92,
    		0x3F,0x06,0xBE,0x79,0xB2,0x32,0x85,0x59,
    		0xAC,0xFE,0xE9,0x86,0xD5,0xE1,0x5E,0x4D,
    		0x17,0x66,0xEA,0x56,0xC4,0xE1,0x06,0x57,
    		0xFA,0x74,0xDB,0x09,0x77,0xC3,0xFB,0x75,
    		0x82,0xB7,0x8C,0xD4,0x7B,0xB2,0xC7,0xF9,
    		0xB2,0x52,0xB4,0xA9,0x46,0x3D,0x15,0xF6,
    		0xAE,0x6E,0xE9,0x23,0x7D,0x54,0xC5,0x48,
    		0x1B,0xF3,0xE0,0xB0,0x99,0x20,0x19,0x0B,
    		0xCF,0xB3,0x1E,0x5B,0xE5,0x09,0xC3,0x2B//0x3B
    	};
    	const BYTE pbD[128] = 
    	{
    		0xB0,0x20,0x6E,0x81,0x20,0xD5,0xDF,0x88,
    		0xD9,0xEA,0xB6,0x7A,0x61,0x86,0x47,0x66,
    		0x47,0x19,0xCE,0x98,0x5C,0xBB,0x70,0xA1,
    		0xBA,0xEE,0x23,0x82,0x72,0xC0,0x0E,0xC3,
    		0xE3,0x9B,0x31,0x96,0xA4,0x4B,0xC6,0xA7,
    		0xF1,0x70,0xE1,0x83,0x6C,0x0E,0x6F,0x30,
    		0x8A,0x4B,0x16,0x54,0x9A,0x02,0x3B,0x99,
    		0x61,0x5F,0x09,0xF0,0x1F,0x32,0x28,0x2E,
    		0xE7,0x4C,0x1D,0xEA,0x7F,0x00,0xE8,0x0D,
    		0x86,0x39,0xC3,0x12,0x25,0x6D,0x98,0x4F,
    		0x73,0xC3,0xA8,0xBC,0x12,0xFE,0x6F,0x6F,
    		0xBB,0xA2,0x0B,0x3B,0x0E,0x80,0x27,0x61,
    		0x9C,0x00,0x88,0x27,0x73,0xA6,0x37,0x52,
    		0xE4,0xAA,0x23,0xF1,0x97,0xA8,0x32,0x45,
    		0x14,0x41,0xDA,0x9E,0x1E,0xEE,0xF1,0x7E,
    		0xD9,0x1A,0x67,0x46,0x22,0x8D,0xE0,0xF1
    	};
    	mpz_t n, d, m, c;
    	u32 dwBytes;
    
    	mpz_init(n);
    	mpz_init(d);
    	mpz_init(m);
    	mpz_init(c);
    
    	mpz_import(n, sizeof(pbN), 1, 1, 0, 0, pbN);
    	mpz_import(d, sizeof(pbD), 1, 1, 0, 0, pbD);
    	mpz_import(m, 128/*sizeof(pbSignature)*/, 1, 1, 0, 0, pbSignature);
    	mpz_powm(c, m, d, n);
    	dwBytes = 128/*sizeof(pbSignature)*/ - (mpz_sizeinbase(c, 2) + 7)/8;
    	mpz_export(pbSignature + dwBytes, NULL, 1, 1, 0, 0, c);
    
    	mpz_clear(c);
    	mpz_clear(m);
    	mpz_clear(d);
    	mpz_clear(n);
    
    	return true;
    }

    Первая моя попытка перевести код при помощи FGIntModExp(Base, Exp, Mod, Res);

    Code:
    type
      PSignature = ^TSignature;
      TSignature = Array[0..127] of Byte;
    
    ...
    
    function Sign(pbSignature: PSignature): Boolean;
    const
      pbN: TSignature =
    	(
    		$D8, $7B, $A2, $45, $62, $F7, $C5, $D1, 
    		$4A, $0C, $FB, $12, $B9, $74, $0C, $19, 
    		$5C, $6B, $DC, $7E, $6D, $6E, $C9, $2B, 
    		$AC, $0E, $B2, $9D, $59, $E1, $D9, $AE, 
    		$67, $89, $0C, $2B, $88, $C3, $AB, $DC, 
    		$AF, $FE, $7D, $4A, $33, $DC, $C1, $BF, 
    		$BE, $53, $1A, $25, $1C, $EF, $0C, $92, 
    		$3F, $06, $BE, $79, $B2, $32, $85, $59, 
    		$AC, $FE, $E9, $86, $D5, $E1, $5E, $4D, 
    		$17, $66, $EA, $56, $C4, $E1, $06, $57, 
    		$FA, $74, $DB, $09, $77, $C3, $FB, $75, 
    		$82, $B7, $8C, $D4, $7B, $B2, $C7, $F9, 
    		$B2, $52, $B4, $A9, $46, $3D, $15, $F6, 
    		$AE, $6E, $E9, $23, $7D, $54, $C5, $48, 
    		$1B, $F3, $E0, $B0, $99, $20, $19, $0B, 
    		$CF, $B3, $1E, $5B, $E5, $09, $C3, $2B//0x3B
    	);
    	pbD: TSignature =
    	(
    		$B0, $20, $6E, $81, $20, $D5, $DF, $88, 
    		$D9, $EA, $B6, $7A, $61, $86, $47, $66, 
    		$47, $19, $CE, $98, $5C, $BB, $70, $A1, 
    		$BA, $EE, $23, $82, $72, $C0, $0E, $C3, 
    		$E3, $9B, $31, $96, $A4, $4B, $C6, $A7, 
    		$F1, $70, $E1, $83, $6C, $0E, $6F, $30, 
    		$8A, $4B, $16, $54, $9A, $02, $3B, $99, 
    		$61, $5F, $09, $F0, $1F, $32, $28, $2E, 
    		$E7, $4C, $1D, $EA, $7F, $00, $E8, $0D, 
    		$86, $39, $C3, $12, $25, $6D, $98, $4F, 
    		$73, $C3, $A8, $BC, $12, $FE, $6F, $6F, 
    		$BB, $A2, $0B, $3B, $0E, $80, $27, $61, 
    		$9C, $00, $88, $27, $73, $A6, $37, $52, 
    		$E4, $AA, $23, $F1, $97, $A8, $32, $45, 
    		$14, $41, $DA, $9E, $1E, $EE, $F1, $7E, 
    		$D9, $1A, $67, $46, $22, $8D, $E0, $F1
    	);
    var
      n, d, m, c: TFGInt;
    	tmp: String;
      data: PByte;
      dsize: u32;
    begin
      (*
      // Чистка переменных (не обязательно)
      ZeroMemory(@n, SizeOf(n));
      ZeroMemory(@d, SizeOf(d));
      ZeroMemory(@m, SizeOf(m));
      ZeroMemory(@c, SizeOf(c));
      *)
    
      Base256StringToFGInt(PChar(@pbN), n);
      Base256StringToFGInt(PChar(@pbD), d);
      Base256StringToFGInt(PChar(pbSignature), m);
      
      // Провожу вычисления
      //mpz_powm(c, m, d, n);
      FGIntModExp(m, d, n, c);
      
      // Преобразовываю результат
      FGIntToBase256String(c, tmp);
      // Копирую результат в хвост входящего параметра
      CopyMemory(@pbSignature[128 - Length(tmp)], PChar(tmp), Length(tmp));
    
      // Освобождаю память
      FGIntDestroy(c);
      FGIntDestroy(m);
      FGIntDestroy(d);
      FGIntDestroy(n);
    
      Result := True;
    end;

    Библиотека FGInt выдала ошибку при попытке инициали переменной m.

    Code:
    Base256StringToFGInt(PChar(pbSignature), m);
    Дело в том, что pbSignature содержит в начале нулевые байты, которые интерпритируются в String, как конец строки.

    Я не растерялся и по аналогии функции Base256StringToFGInt(str256: String; var FGInt: TFGInt); написал свою:

    Code:
    Procedure SignatureToFGInt(pbSignature: PSignature; Var FGInt : TFGInt);
    Var
       temp1 : String;
       i : longint;
       trans : Array[0..255] Of String;
    Begin
       temp1 := '';
       initialize8(trans);
       For i := 0 To 127 Do temp1 := temp1 + trans[pbSignature^[ i ]];
       While (temp1[1] = '0') And (temp1 <> '0') Do delete(temp1, 1, 1);
       Base2StringToFGInt(temp1, FGInt);
    End;
    После чего код функции стал выглядеть так:

    Code:
    function Sign(pbSignature: PSignature): Boolean;
    const
      pbN: TSignature =
    	(
    		$D8, $7B, $A2, $45, $62, $F7, $C5, $D1, 
    		$4A, $0C, $FB, $12, $B9, $74, $0C, $19, 
    		$5C, $6B, $DC, $7E, $6D, $6E, $C9, $2B, 
    		$AC, $0E, $B2, $9D, $59, $E1, $D9, $AE, 
    		$67, $89, $0C, $2B, $88, $C3, $AB, $DC, 
    		$AF, $FE, $7D, $4A, $33, $DC, $C1, $BF, 
    		$BE, $53, $1A, $25, $1C, $EF, $0C, $92, 
    		$3F, $06, $BE, $79, $B2, $32, $85, $59, 
    		$AC, $FE, $E9, $86, $D5, $E1, $5E, $4D, 
    		$17, $66, $EA, $56, $C4, $E1, $06, $57, 
    		$FA, $74, $DB, $09, $77, $C3, $FB, $75, 
    		$82, $B7, $8C, $D4, $7B, $B2, $C7, $F9, 
    		$B2, $52, $B4, $A9, $46, $3D, $15, $F6, 
    		$AE, $6E, $E9, $23, $7D, $54, $C5, $48, 
    		$1B, $F3, $E0, $B0, $99, $20, $19, $0B, 
    		$CF, $B3, $1E, $5B, $E5, $09, $C3, $2B//0x3B
    	);
    	pbD: TSignature =
    	(
    		$B0, $20, $6E, $81, $20, $D5, $DF, $88, 
    		$D9, $EA, $B6, $7A, $61, $86, $47, $66, 
    		$47, $19, $CE, $98, $5C, $BB, $70, $A1, 
    		$BA, $EE, $23, $82, $72, $C0, $0E, $C3, 
    		$E3, $9B, $31, $96, $A4, $4B, $C6, $A7, 
    		$F1, $70, $E1, $83, $6C, $0E, $6F, $30, 
    		$8A, $4B, $16, $54, $9A, $02, $3B, $99, 
    		$61, $5F, $09, $F0, $1F, $32, $28, $2E, 
    		$E7, $4C, $1D, $EA, $7F, $00, $E8, $0D, 
    		$86, $39, $C3, $12, $25, $6D, $98, $4F, 
    		$73, $C3, $A8, $BC, $12, $FE, $6F, $6F, 
    		$BB, $A2, $0B, $3B, $0E, $80, $27, $61, 
    		$9C, $00, $88, $27, $73, $A6, $37, $52, 
    		$E4, $AA, $23, $F1, $97, $A8, $32, $45, 
    		$14, $41, $DA, $9E, $1E, $EE, $F1, $7E, 
    		$D9, $1A, $67, $46, $22, $8D, $E0, $F1
    	);
    var
      n, d, m, c: TFGInt;
    	tmp: String;
      data: PByte;
      dsize: u32;
    begin
      (*
      // Чистка переменных (не обязательно)
      ZeroMemory(@n, SizeOf(n));
      ZeroMemory(@d, SizeOf(d));
      ZeroMemory(@m, SizeOf(m));
      ZeroMemory(@c, SizeOf(c));
      *)
    
      SignatureToFGInt(@pbN, n);
      SignatureToFGInt(@pbD, d);
      SignatureToFGInt(pbSignature, m);
      
      // Провожу вычисления
      //mpz_powm(c, m, d, n);
      FGIntModExp(m, d, n, c);
      
      // Преобразовываю результат
      FGIntToBase256String(c, tmp);
      // Копирую результат в хвост входящего параметра
      CopyMemory(@pbSignature[128 - Length(tmp)], PChar(tmp), Length(tmp));
    
      // Освобождаю память
      FGIntDestroy(c);
      FGIntDestroy(m);
      FGIntDestroy(d);
      FGIntDestroy(n);
    
      Result := True;
    end;

    Появились первые результаты:
    Вход:

    Code:
    0001FFFFFFFFFFFFFFFFFFFFFFFFFFFF
    FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    FFFFFFFFFFFFFFFFFFFFFFFF00302130
    0906052B0E03021A050004149692AEDD
    7138D9898AC6582059FF591581584772
    Выход:

    Code:
    86E25ED728B36FE3B67E379F4D41B2C3
    0C8A764091EE48B0CBA8A7CE3FD787A2
    6EE2D93E65296CCDE7518C53DF54443D
    DF92FF9E087C8874C8254D7BA4F47A72
    9DCAB0A64040663ADB08926B4869341C
    8DCDF797ED29F5E58B04FFE90401EE7B
    0ED99DF73845C12D79E1607F6224BBE5
    3C559651C49EBC16A6D8DB4C3B1B8316

    У меня есть довольно весомые основания считать, что этот результат ошибочный.

    Я решил попробовать зайти с другой стороны, и нашёл в сети такой интересный код, очень похожий на FGIntModExp(Base, Exp, Mod, Res):

    Code:
    const
      BN_BIT = 1024;//to be 32-bit aligned
      BN_DWORD = BN_BIT div 32;
    type
      PBN_NUMBER = ^TBN_NUMBER;
      TBN_NUMBER = array[0..BN_DWORD-1] of DWORD;
    
    function rsa_main(const M: TBN_NUMBER{modulus};B: TBN_NUMBER{exponent};A: TBN_NUMBER{base}): TBN_NUMBER; pascal;
    //action: x = (a^b) mod m
    var
      p: TBN_NUMBER;//temporary (a^i) mod m
      t: TBN_NUMBER;//temporary bgnumber
    asm
      push ebx
      push edi
      push esi
      cld
    //x = 1
      mov  edi,dword ptr Result
      mov  eax,1
      stosd
      mov  ecx,BN_DWORD-1
      dec  eax
      rep  stosd
    //p = a
      lea  edi,p
      mov  esi,dword ptr a
      mov  ecx,BN_DWORD
      rep  movsd
    //ebx = highestbit(b)
      mov  edi,dword ptr b
      call @bitscan
    // for (edx=0; edx<=ebx; edx++)
      xor  edx,edx
    @pwr_cycle:
      push edx
      push ebx
    // if (b.bit[edx])
      mov  eax,dword ptr b
      bt  [eax],edx
      jnc  @pwr_nobit
    // x=(x*p) mod m
      mov  edx,dword ptr Result
      call @mulmod
    @pwr_nobit:
    // p=(p*p) mod m
      lea  edx,p
      call @mulmod
    // end for
      pop  ebx
      pop  edx
      inc  edx
      cmp  edx,ebx
      jbe  @pwr_cycle
      pop  esi
      pop  edi
      pop  ebx
      jmp @end
      nop
      nop
    // input:  x in EDX
    // action: x=(x*p) mod m
    // used:  t
    @mulmod:
      lea  edi,t
      mov  ecx,BN_DWORD
      xor  eax,eax
      rep  stosd
      lea  edi,p
      call @bitscan
    @mul_cycle:
      lea  edi,t
      mov  ecx,BN_DWORD
      xor  eax,eax
    @shl_cycle:
      rcl  dword ptr [edi],1
      lea  edi,[edi+4]
      loop @shl_cycle
      call @cmpsub
      bt  dword ptr p,ebx
      jnc  @mul_nobit
      mov  esi,edx
      lea  edi,t
      xor  eax,eax
      mov  ecx,BN_DWORD
    @add_cycle:
      mov  eax,[esi]
      adc  [edi],eax
      lea  esi,[esi+4]
      lea  edi,[edi+4]
      loop @add_cycle
      call @cmpsub
    @mul_nobit:
      dec  ebx
      jns  @mul_cycle
      mov  edi,edx
      lea  esi,t
      mov  ecx,BN_DWORD
      rep  movsd
      ret
      nop
      nop
      nop
    // input:  EDI=bignumber
    // output: EBX=number of highest bit (0-based)
    @bitscan:
      mov  ebx,BN_BIT-1
    @bitscan_cycle:
      bt  [edi],ebx
      jc  @bitscan_exit
      dec  ebx
      jnz  @bitscan_cycle
    @bitscan_exit:
      ret
      nop
      nop
    // action: if (t>=m) t-=m
    @cmpsub:
      lea  esi,t
      mov  edi,dword ptr m
      mov  ecx,BN_DWORD-1
    @cmp_cycle:
      mov  eax,[esi+ecx*4]
      cmp  eax,[edi+ecx*4]
      jb  @cmpsub_exit
      ja  @sub
      dec  ecx
      jns  @cmp_cycle
    @sub:
      mov  esi,dword ptr m
      lea  edi,t
      xor  eax,eax
      mov  ecx,BN_DWORD
    @sub_cycle:
      mov  eax,[esi]
      sbb  [edi],eax
      lea  esi,[esi+4]
      lea  edi,[edi+4]
      loop @sub_cycle
    @cmpsub_exit:
      ret
    @End:
    end;
    Теперь, после модификаций, код функции стал выглядеть так:

    Code:
    function Sign(pbSignature: PSignature): Boolean;
    const
      pbN: TSignature =
    	(
    		$D8, $7B, $A2, $45, $62, $F7, $C5, $D1, 
    		$4A, $0C, $FB, $12, $B9, $74, $0C, $19, 
    		$5C, $6B, $DC, $7E, $6D, $6E, $C9, $2B, 
    		$AC, $0E, $B2, $9D, $59, $E1, $D9, $AE, 
    		$67, $89, $0C, $2B, $88, $C3, $AB, $DC, 
    		$AF, $FE, $7D, $4A, $33, $DC, $C1, $BF, 
    		$BE, $53, $1A, $25, $1C, $EF, $0C, $92, 
    		$3F, $06, $BE, $79, $B2, $32, $85, $59, 
    		$AC, $FE, $E9, $86, $D5, $E1, $5E, $4D, 
    		$17, $66, $EA, $56, $C4, $E1, $06, $57, 
    		$FA, $74, $DB, $09, $77, $C3, $FB, $75, 
    		$82, $B7, $8C, $D4, $7B, $B2, $C7, $F9, 
    		$B2, $52, $B4, $A9, $46, $3D, $15, $F6, 
    		$AE, $6E, $E9, $23, $7D, $54, $C5, $48, 
    		$1B, $F3, $E0, $B0, $99, $20, $19, $0B, 
    		$CF, $B3, $1E, $5B, $E5, $09, $C3, $2B//0x3B
    	);
    	pbD: TSignature =
    	(
    		$B0, $20, $6E, $81, $20, $D5, $DF, $88, 
    		$D9, $EA, $B6, $7A, $61, $86, $47, $66, 
    		$47, $19, $CE, $98, $5C, $BB, $70, $A1, 
    		$BA, $EE, $23, $82, $72, $C0, $0E, $C3, 
    		$E3, $9B, $31, $96, $A4, $4B, $C6, $A7, 
    		$F1, $70, $E1, $83, $6C, $0E, $6F, $30, 
    		$8A, $4B, $16, $54, $9A, $02, $3B, $99, 
    		$61, $5F, $09, $F0, $1F, $32, $28, $2E, 
    		$E7, $4C, $1D, $EA, $7F, $00, $E8, $0D, 
    		$86, $39, $C3, $12, $25, $6D, $98, $4F, 
    		$73, $C3, $A8, $BC, $12, $FE, $6F, $6F, 
    		$BB, $A2, $0B, $3B, $0E, $80, $27, $61, 
    		$9C, $00, $88, $27, $73, $A6, $37, $52,
    		$E4, $AA, $23, $F1, $97, $A8, $32, $45, 
    		$14, $41, $DA, $9E, $1E, $EE, $F1, $7E, 
    		$D9, $1A, $67, $46, $22, $8D, $E0, $F1
    	);
    begin
      PBN_NUMBER(pbSignature)^ := rsa_main(TBN_NUMBER(pbN), TBN_NUMBER(pbD), PBN_NUMBER(pbSignature)^);
    
    	Result := True;
    end;
    Входные данные те же.

    Выход:

    Code:
    B02BEF922DECC11E5D52AAF53948DF41
    D6EB49EF475475DCBE6C8F4FB8592B7E
    5077F82298AEDF6FF23E4A6469FDF2D7
    E8E6D870C4B50592235E2759D315F1D8
    288D0FA363A7A807E57AED4C09B59B68
    5BE53A63BE2AD3947C81B20D2BED1D11
    4DE318F6EA7CE967D73ECF88B465858F
    00F9B16AC8CB3C65572CDE34136D9B06



    Знающие, подскажите, что я делаю не так?
    Если у кого-то из вас есть возможность скомпилировать оригинальную функцию, отпишите, какие данные она выдаёт на выходе при моих входных данных, что в тексте.
     
    #9 #Smith, 24 Oct 2013
    Last edited: 24 Oct 2013
  10. -=Cerberus=-

    -=Cerberus=- κρυπτός γράφω

    Joined:
    29 Apr 2012
    Messages:
    1,321
    Likes Received:
    930
    Reputations:
    391
    Функция Base256StringToFGInt принимает 256ричное число

    пример:

    Base256StringToFGInt('53743034420103765853770572669989121553439102166954208710164177785895674665045',n);


    Тип PChar - указатель на значение символа.

    у себя в коде ты вызываешь оригинал так:

    Base256StringToFGInt(PChar(pbSignature), m);

    я так понимаю PChar здесь просто неуместен.
    Ты должен перевести массив байт в 256ричное число, а потом это число подставлять в функцию Base256StringToFGInt
     
  11. #Smith

    #Smith New Member

    Joined:
    20 Jun 2010
    Messages:
    96
    Likes Received:
    2
    Reputations:
    0
    Не скрою, этот вариант я тоже рассматривал.
    Но почему же тогда функция FGIntToBase256String(c, tmp); выдаёт всякое непотребство из ASCII символов?
    Просто посмотри на tmp при этих входных данных:


    Code:
    0001FFFFFFFFFFFFFFFFFFFFFFFFFFFF
    FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    FFFFFFFFFFFFFFFFFFFFFFFF00302130
    0906052B0E03021A050004149692AEDD
    7138D9898AC6582059FF591581584772
    Code:
    type
      PSignature = ^TSignature;
      TSignature = Array[0..127] of Byte;
    
    ...
    
    function SigToStr256(pbSignature: PSignature): String;
    var
      i: u16;
    begin
      Result := '';
      for i := 0 to 127 do Result := Result + IntToHex(pbSignature[i], 2);
    end;
    
    function SigToStr256R(pbSignature: PSignature): String;
    var
      i: u16;
    begin
      Result := '';
      for i := 127 downto 0 do Result := Result + IntToHex(pbSignature[i], 2);
    end;
    
    ...
    
    function Sign(pbSignature: PSignature): Boolean;
    const
      pbN: TSignature =
    	(
    		$D8, $7B, $A2, $45, $62, $F7, $C5, $D1, 
    		$4A, $0C, $FB, $12, $B9, $74, $0C, $19, 
    		$5C, $6B, $DC, $7E, $6D, $6E, $C9, $2B, 
    		$AC, $0E, $B2, $9D, $59, $E1, $D9, $AE, 
    		$67, $89, $0C, $2B, $88, $C3, $AB, $DC, 
    		$AF, $FE, $7D, $4A, $33, $DC, $C1, $BF, 
    		$BE, $53, $1A, $25, $1C, $EF, $0C, $92, 
    		$3F, $06, $BE, $79, $B2, $32, $85, $59, 
    		$AC, $FE, $E9, $86, $D5, $E1, $5E, $4D, 
    		$17, $66, $EA, $56, $C4, $E1, $06, $57, 
    		$FA, $74, $DB, $09, $77, $C3, $FB, $75, 
    		$82, $B7, $8C, $D4, $7B, $B2, $C7, $F9, 
    		$B2, $52, $B4, $A9, $46, $3D, $15, $F6, 
    		$AE, $6E, $E9, $23, $7D, $54, $C5, $48, 
    		$1B, $F3, $E0, $B0, $99, $20, $19, $0B, 
    		$CF, $B3, $1E, $5B, $E5, $09, $C3, $2B//0x3B
    	);
    	pbD: TSignature =
    	(
    		$B0, $20, $6E, $81, $20, $D5, $DF, $88, 
    		$D9, $EA, $B6, $7A, $61, $86, $47, $66, 
    		$47, $19, $CE, $98, $5C, $BB, $70, $A1, 
    		$BA, $EE, $23, $82, $72, $C0, $0E, $C3, 
    		$E3, $9B, $31, $96, $A4, $4B, $C6, $A7, 
    		$F1, $70, $E1, $83, $6C, $0E, $6F, $30, 
    		$8A, $4B, $16, $54, $9A, $02, $3B, $99, 
    		$61, $5F, $09, $F0, $1F, $32, $28, $2E, 
    		$E7, $4C, $1D, $EA, $7F, $00, $E8, $0D, 
    		$86, $39, $C3, $12, $25, $6D, $98, $4F, 
    		$73, $C3, $A8, $BC, $12, $FE, $6F, $6F, 
    		$BB, $A2, $0B, $3B, $0E, $80, $27, $61, 
    		$9C, $00, $88, $27, $73, $A6, $37, $52, 
    		$E4, $AA, $23, $F1, $97, $A8, $32, $45, 
    		$14, $41, $DA, $9E, $1E, $EE, $F1, $7E, 
    		$D9, $1A, $67, $46, $22, $8D, $E0, $F1
    	);
    var
      n, d, m, c: TFGInt;
    	tmp: String;
      data: PByte;
      dsize: u32;
    begin
      (*
      // Чистка переменных (не обязательно)
      ZeroMemory(@n, SizeOf(n));
      ZeroMemory(@d, SizeOf(d));
      ZeroMemory(@m, SizeOf(m));
      ZeroMemory(@c, SizeOf(c));
      *)
    
      Base256StringToFGInt(SigToStr256(@pbN), n);
      Base256StringToFGInt(SigToStr256(@pbD), d);
      Base256StringToFGInt(SigToStr256(pbSignature), m);
      
      // Провожу вычисления
      //mpz_powm(c, m, d, n);
      FGIntModExp(m, d, n, c);
      
      // Чищу tmp (не обязательно)
      tmp := '';
      // Преобразовываю результат
      FGIntToBase256String(c, tmp);
      // Заценим эту ерись
      ShowMessage(tmp);
    
      // Освобождаю память
      FGIntDestroy(c);
      FGIntDestroy(m);
      FGIntDestroy(d);
      FGIntDestroy(n);
    
      Result := True;
    end;
     
    #11 #Smith, 24 Oct 2013
    Last edited: 24 Oct 2013
  12. neviens

    neviens Member

    Joined:
    9 Oct 2013
    Messages:
    82
    Likes Received:
    28
    Reputations:
    3
    Base256?! Там точно нету более человеческого импорта большого числа? Например BinToFGInt(), HexToFGInt() или Base64StringToFGInt?
     
  13. neviens

    neviens Member

    Joined:
    9 Oct 2013
    Messages:
    82
    Likes Received:
    28
    Reputations:
    3
    Вроде всё работает- хеш шифруется приватным ключём, результат уходит в signature[]; и правильно дешифруется публичным ключём.
    Прикольный язык программирования- с первого раза мне так и не получилось BinToHex() сделать:
    Code:
    // fpc -O3 modexp.pas
    Program sign(output);
    {$H+} 
    Uses FGInt, classes;
    
    var
    e, d, x, y, n: TFGInt;
    tmp: String;
    
    publicExponent:  Array[0..2] of byte = (1,0,1);
    modulus: Array[0..$7F] of byte = (
    	$8B, $53, $9C, $C3, $A7, $DA, $B9, $54, $1A, $B7, $CB, $DF, $58, $44, $8A, $41,
    	$70, $45, $F4, $C0, $70, $07, $16, $70, $B5, $4C, $FF, $61, $6A, $80, $72, $0E,
    	$70, $3C, $56, $79, $0C, $6D, $D4, $C1, $C9, $9D, $BB, $00, $2E, $79, $D7, $EE,
    	$65, $36, $AD, $87, $C6, $4D, $9D, $CC, $99, $77, $D3, $BC, $A3, $A4, $0A, $10,
    	$1A, $27, $02, $11, $75, $09, $0D, $66, $80, $D9, $66, $29, $D1, $0D, $A4, $A5,
    	$63, $72, $99, $34, $C6, $31, $20, $B9, $66, $10, $A3, $77, $8D, $8C, $F2, $B5,
    	$ED, $22, $86, $3A, $5C, $38, $BE, $9D, $CE, $D9, $0B, $EA, $8A, $DF, $97, $D7,
    	$F2, $58, $6A, $8E, $9C, $2B, $62, $B9, $04, $F6, $AB, $DA, $97, $67, $86, $09
    );
    privateExponent: Array[0..$7F] of byte = (
    	$88, $04, $C7, $DD, $A7, $88, $7C, $37, $E4, $A1, $9C, $D2, $5D, $CD, $04, $20,
    	$A0, $A8, $5B, $2A, $67, $F4, $33, $6F, $33, $40, $89, $6D, $A4, $58, $E3, $80,
    	$BF, $07, $D8, $EF, $F2, $37, $63, $67, $11, $1B, $00, $CE, $4B, $91, $3E, $42,
    	$89, $E3, $58, $84, $5E, $0F, $B6, $47, $61, $68, $3F, $79, $41, $54, $CB, $50,
    	$B7, $A3, $B4, $3A, $99, $30, $C2, $CA, $2A, $A9, $B7, $D9, $02, $26, $7B, $84,
    	$91, $00, $FE, $5D, $A2, $1B, $55, $39, $21, $88, $6D, $80, $CF, $A1, $9B, $67,
    	$42, $3A, $AD, $C8, $7E, $19, $BE, $55, $BE, $29, $08, $83, $A1, $77, $98, $F5,
    	$89, $8C, $41, $DC, $C1, $11, $67, $7F, $97, $50, $BB, $E5, $56, $EE, $5F, $B5
    );
    inputHash: Array[0..$7F] of byte = (
    	$7F, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, //1st bit must be 0!
    	$FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF,
    	$FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF,
    	$FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF,
    	$FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF,
    	$FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF,
    	$FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF,
    	$FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
    );
    
    signature: Array[0..$7F] of byte;
    //HexText: array[0..$FF] of Char;
    //ptr: ^byte;
    
    begin
    	SetString(tmp, PAnsiChar(@privateExponent[0]), Length(privateExponent));	
    	Base256StringToFGInt(tmp, d);
    	
        SetString(tmp, PAnsiChar(@publicExponent[0]), Length(publicExponent));
    	Base256StringToFGInt(tmp, e);
    
        SetString(tmp, PAnsiChar(@modulus[0]), Length(modulus));									
    	Base256StringToFGInt(tmp, n);
    
        SetString(tmp, PAnsiChar(@inputHash[0]), Length(inputHash));						
    	Base256StringToFGInt(tmp, x);
    
    	FGIntModExp(x, d, n, y);                                       //private encrypt (y = x ^ d mod n)
    	FGIntToBase256String(y, tmp);
    	move(tmp, signature, Length(tmp));
    //	ptr := @signature;
    //	BinToHex(PChar(signature^), HexText, Length(signature)); //TODO
    //	writeln(HexText);
    	ConvertBase256StringToHexString(tmp, tmp);
    	writeln(tmp);
    
    	FGIntModExp(y, e, n, x);                                       //public decrypt (x = y ^ e mod n)
    	FGIntToBase256String(x, tmp);
    	ConvertBase256StringToHexString(tmp, tmp);
    	writeln(tmp);
    
    	FGIntDestroy(e);
    	FGIntDestroy(d);
    	FGIntDestroy(n);
    	FGIntDestroy(x);
    	FGIntDestroy(y);
    end.
     
  14. #Smith

    #Smith New Member

    Joined:
    20 Jun 2010
    Messages:
    96
    Likes Received:
    2
    Reputations:
    0
    Проблема решена.
    Прежде всего, огромное программерское спасибо всем, кто помогал.

    neviens, тебе персональное спасибо за активное участие в решении проблемы и исходник.
    По сути дела, ты по-своему повторил мой первый эксперимент.
    Прописав свои ключи в твоём коде, я понял, что всё работало верно, а ошибка была во входных данных.


    Ещё раз, всем спасибо!
    Вопрос закрыт.
     
    #14 #Smith, 25 Oct 2013
    Last edited: 25 Oct 2013