Приветствую, участники форума. Прошу помощи в решении такой непростой задачи: Перевожу код с 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; }
на офицальном сайте вроде все же написано или нет? описание параметров передаваемых в функции описано в доке описание типа mpz_t должно быть где-то gmp.h
Молодец. Какой ты умный! Я бы без твоего дельного совета так бы и не догадался! А ещё знаешь, чтобы есть пищу ложкой - нужны руки, чтобы держать ложку. PS. Честно, задрали выёживаться. Не можешь помочь или не хочешь - так промолчи. А то этот флуд и дешёвые понты уже так надоели.
http://gmplib.org/manual/Initializing-Integers.html << описуха. твой код использует эту гадость. http://gmplib.org/manual/ << манул по этой гадости. если че - это линуховая примочка. Переводить ее на вынь бессмысленно. P.S: https://www.google.ru/#newwindow=1&q=gmp+lib+Delphi попробуй тут порыться.. мало ли чего попадется. Может и портировали ее туда уже.
>#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 там.
Спасибо. Картина начинает прояснятся. Но pbD и pbN - это массивы, размерностью 128 байт. Неужели, эта криптографическая функция рассматривает их, как просто два больших числа? И можно поподробней про форматы. Мне это примерно понятно, но, что означают таинственные флаги с нолём и единицей в функциях?
Массивы байтов только одна из удобных форм хранения больших чисел, для mpz_powm() они становятся понятными только после преобразования функцией mpz_import(). Скорее всего функция импорта универсальна и способна импортировать и другие форматы, например, base64, base32, base10 итд, если конкретный формат и размер числа задать в аргументах ф-ии.
Мои эксперименты с кодом продолжаются. Но кажется, я опять попал в тупик. Похоже, что я получаю неправильные выходные данные. Обо всём по порядку. Оригинальный код: 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 Знающие, подскажите, что я делаю не так? Если у кого-то из вас есть возможность скомпилировать оригинальную функцию, отпишите, какие данные она выдаёт на выходе при моих входных данных, что в тексте.
Функция Base256StringToFGInt принимает 256ричное число пример: Base256StringToFGInt('53743034420103765853770572669989121553439102166954208710164177785895674665045',n); Тип PChar - указатель на значение символа. у себя в коде ты вызываешь оригинал так: Base256StringToFGInt(PChar(pbSignature), m); я так понимаю PChar здесь просто неуместен. Ты должен перевести массив байт в 256ричное число, а потом это число подставлять в функцию Base256StringToFGInt
Не скрою, этот вариант я тоже рассматривал. Но почему же тогда функция 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;
Base256?! Там точно нету более человеческого импорта большого числа? Например BinToFGInt(), HexToFGInt() или Base64StringToFGInt?
Вроде всё работает- хеш шифруется приватным ключём, результат уходит в 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.
Проблема решена. Прежде всего, огромное программерское спасибо всем, кто помогал. neviens, тебе персональное спасибо за активное участие в решении проблемы и исходник. По сути дела, ты по-своему повторил мой первый эксперимент. Прописав свои ключи в твоём коде, я понял, что всё работало верно, а ошибка была во входных данных. Ещё раз, всем спасибо! Вопрос закрыт.