Народ, может кто-нибудь встречал в природе исходники DSA (алгоритм цифровой подписи, чем-то похож на RSA) Нужны исходники на Си/С++ или Delphi. Желательно как можно меньшего размера, потрашить исходники уже существующих либ как-то не хочется, а таскать их с собой - без варианта. Ну или на крайняк rsa (когда-то видел очень маленький исходник, но потерял его). было бы время, сам бы написал, но вся херня в написании модуля длинной арифметики Хотя вот думаю может заюзать цифровую подпись на основе стандартного виндового двига, но что-то особо не нашел как создавать открытые и закрытые ключи и юзать их напрямую из памяти (не сохраняя в хранилище)
slesh не помню где брал код, реализует RSA и длинную арифметику может и подойдет Code: unit RSA; interface type PIntegerArray = ^TIntegerArray; TIntegerArray = array of Integer; PByteArray = ^TByteArray; TByteArray = array of Byte; const BN_BIT = 1024;//to be 32-bit aligned BN_DWORD = BN_BIT div 32; type TBigNumber = array[0..BN_DWORD-1] of Cardinal; function RSAMain(const M: TBigNumber{modulus}; B: TBigNumber{exponent}; A: TBigNumber{base}): TBigNumber; pascal; function LongMulAdd(var Data; Multiplicator, Addend, Count: Integer): Integer; register; function BaseBinary(Numbers: TIntegerArray; var Buffer; BitsCount, Base: Integer): Integer; function BaseStrToBinary(const Str: String; var Buffer; BitsCount: Integer; const NumberChars, Mask: String): Boolean; function BinToHexStr(Numb: TBigNumber; nSize: Cardinal): String; function BigNumbToChar(var Numb: TBigNumber): PChar; procedure CryptBuff(var Buffer: Pointer; var nSize: Cardinal; Key: Pointer; szKey: Cardinal; Revers: Boolean = True); procedure DeCryptBuff(Buffer, OpenKey, PrivateKey: Pointer; Revers: Boolean = True); implementation procedure CvtInt; asm OR CL,CL JNZ @CvtLoop @C1: OR EAX,EAX JNS @C2 NEG EAX CALL @C2 MOV AL,'-' INC ECX DEC ESI MOV [ESI],AL RET @C2: MOV ECX,10 @CvtLoop: PUSH EDX PUSH ESI @D1: XOR EDX,EDX DIV ECX DEC ESI ADD DL,'0' CMP DL,'0'+10 JB @D2 ADD DL,('A'-'0')-10 @D2: MOV [ESI],DL OR EAX,EAX JNE @D1 POP ECX POP EDX SUB ECX,ESI SUB EDX,ECX JBE @D5 ADD ECX,EDX MOV AL,'0' SUB ESI,EDX JMP @z @zloop: MOV [ESI+EDX],AL @z: DEC EDX JNZ @zloop MOV [ESI],AL @D5: end; function IntToHex(Value: Integer; Digits: Integer): string; // FmtStr(Result, '%.*x', [Digits, Value]); asm CMP EDX, 32 // Digits < buffer length? JBE @A1 XOR EDX, EDX @A1: PUSH ESI MOV ESI, ESP SUB ESP, 32 PUSH ECX // result ptr MOV ECX, 16 // base 16 EDX = Digits = field width CALL CvtInt MOV EDX, ESI POP EAX // result ptr CALL System.@LStrFromPCharLen ADD ESP, 32 POP ESI end; function Ceil(const X: Extended): Integer; begin Result := Integer(Trunc(X)); if Frac(X) > 0 then Inc(Result); end; function Log2(const X: Extended): Extended; asm FLD1 FLD X FYL2X FWAIT end; { M: modulus B: exponent A: base} function RSAMain(const M: TBigNumber; B: TBigNumber; A: TBigNumber): TBigNumber; pascal; //action: x = (a^b) mod m var p: TBigNumber;//temporary (a^i) mod m t: TBigNumber;//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; function LongMulAdd(var Data; Multiplicator, Addend, Count: Integer): Integer; register; asm push edi push esi push ebx mov ebx,edx mov esi,eax mov edi,ecx mov ecx,Count @1: mov eax,[esi] xor edx,edx mul ebx add eax,edi adc edx,0 mov [esi],eax mov edi,edx add esi,4 dec ecx jnz @1 @End: mov eax,edi pop ebx pop esi pop edi end; function BaseBinary(Numbers: TIntegerArray; var Buffer; BitsCount, Base: Integer): Integer; var Buf: array of Cardinal; A, MaxBitsCount, BufSize, BufSizeB, ZeroCount: Integer; begin Result:= 0; MaxBitsCount:= Ceil(Log2(Base)*Length(Numbers)); BufSize:= (MaxBitsCount + 31) div 32; BufSizeB:= BufSize*4; SetLength(Buf, BufSize); for A:=0 to High(Numbers) do Result:= LongMulAdd(Buf[0], Base, Numbers[A], BufSize); Move(Buf[0], Buffer, BufSizeB); ZeroCount:= (BitsCount + 7)div 8 - BufSizeB; if ZeroCount>0 then FillChar(TByteArray(Buffer)[BufSizeB], ZeroCount, 0); end; function BaseStrToBinary(const Str: String; var Buffer; BitsCount: Integer; const NumberChars, Mask: String): Boolean; var Buf: TIntegerArray; A, Index, Base, Count: Integer; begin Result:= False; Base:= Length(NumberChars); if (Length(Str)>0) and (BitsCount>0) and (Base>1) then begin SetLength(Buf, Length(Str)); Count:= 0; for A:=1 to Length(Str) do begin Index:=Pos(Str[A],NumberChars)-1; if Index>=0 then begin Buf[Count]:=Index; Inc(Count); end; end; if Count>0 then begin SetLength(Buf,Count); BaseBinary(Buf, Buffer, BitsCount, Base); Result:= True; end; end; end; function BinToHexStr(Numb: TBigNumber; nSize: Cardinal): String; var i: Cardinal; p: PByte; begin Result:= ''; p:= @Numb; for i:= SizeOf(Numb)-1 downto 0 do begin Result:= Result + IntToHex(Byte(Ptr(Cardinal(p)+i)^),2); end; end; function BigNumbToChar(var Numb: TBigNumber): PChar; asm nop end; procedure CryptBuff(var Buffer: Pointer; var nSize: Cardinal; Key: Pointer; szKey: Cardinal; Revers: Boolean = True); var E,M,H,S: TBigNumber; i,j: Cardinal; p: Pointer; begin FillChar(E, SizeOf(E), 0); FillChar(H, SizeOf(H), 0); E[0]:= 65537; Move(Key^, M, szKey); p:= @H; j:= 0; // if nSize >= szKey then nSize:= szKey; if Revers then begin for i:= nSize - 1 downto 0 do begin TByteArray(p)[j]:= TByteArray(Buffer)[i]; Inc(j); end; end else Move(Buffer^, p^, nSize); S:= RSAMain(M,E,H); nSize:= SizeOf(S); ReallocMem(Buffer,nSize); Move(S, Buffer^, nSize); end; procedure DeCryptBuff(Buffer, OpenKey, PrivateKey: Pointer; Revers: Boolean = True); var D,M,H,S: TBigNumber; i,j: Cardinal; p: Pointer; begin Move(PrivateKey^, D, SizeOf(TBigNumber)); Move(OpenKey^,M, SizeOf(TBigNumber)); FillChar(H, SizeOf(H), 0); j:= 0; p:= @H; if Revers then begin for i:= SizeOf(TBigNumber) - 1 downto 0 do begin TByteArray(p)[j]:= TByteArray(Buffer)[i]; Inc(j); end; end else Move(Buffer^, p^, SizeOf(TBigNumber)); S:= RSAMain(M,D,H); Move(S, Buffer^, SizeOf(TBigNumber)); end; end.
Спасиб. Как нибудь попробую заюзать. Вот тока осталось найти нормальный генератор ключей. А вообще подошелбы и стандартный cryptoapi с с сертификатами PKCS #7 но как-то стрёмно что сертификат добавлять в хранилище надо для проверки подписи
2 s0l_ir0n это уже сто раз видел, но неподходит, еслибы ты более внимательнее погляделбы, то увиделбы что юзается платная либа. Темболее опятьже их либа основана на частично на CryptoApi
Ну тогда могу предложить только делфи реализацию, т.к. сам использую. Смотреть в сторону fgint, у них есть примеры реализации рса,дса, эл-гамаля и эллиптических кривых http://www.submanifold.be/triade/GInt/gint.html
2slesh А как насчет crypto++. Можно выдернуть DSA и будет все красиво ) Туплю, вчитался в первый пост =/
Crypto API подходит на все 100% но увы завал на том, что сертификаты(открытые ключи) не должны быть в виде файлов и не должны помещатсья в хранилище сертификатов. Причем именно этот момент является самым обязательным