Исходники DSA

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by slesh, 9 Jan 2011.

  1. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Народ, может кто-нибудь встречал в природе исходники DSA (алгоритм цифровой подписи, чем-то похож на RSA)
    Нужны исходники на Си/С++ или Delphi. Желательно как можно меньшего размера, потрашить исходники уже существующих либ как-то не хочется, а таскать их с собой - без варианта.
    Ну или на крайняк rsa (когда-то видел очень маленький исходник, но потерял его).

    было бы время, сам бы написал, но вся херня в написании модуля длинной арифметики

    Хотя вот думаю может заюзать цифровую подпись на основе стандартного виндового двига, но что-то особо не нашел как создавать открытые и закрытые ключи и юзать их напрямую из памяти (не сохраняя в хранилище)
     
    #1 slesh, 9 Jan 2011
    Last edited: 9 Jan 2011
  2. alexey-m

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

    Joined:
    15 Jul 2009
    Messages:
    518
    Likes Received:
    100
    Reputations:
    37
    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.
    
     
    1 person likes this.
  3. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Спасиб. Как нибудь попробую заюзать. Вот тока осталось найти нормальный генератор ключей.

    А вообще подошелбы и стандартный cryptoapi с с сертификатами PKCS #7
    но как-то стрёмно что сертификат добавлять в хранилище надо для проверки подписи
     
  4. s0l_ir0n

    s0l_ir0n Active Member

    Joined:
    14 Mar 2009
    Messages:
    399
    Likes Received:
    144
    Reputations:
    18
    #4 s0l_ir0n, 10 Jan 2011
    Last edited: 10 Jan 2011
  5. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    2 s0l_ir0n это уже сто раз видел, но неподходит, еслибы ты более внимательнее погляделбы, то увиделбы что юзается платная либа. Темболее опятьже их либа основана на частично на CryptoApi
     
    #5 slesh, 10 Jan 2011
    Last edited: 10 Jan 2011
  6. s0l_ir0n

    s0l_ir0n Active Member

    Joined:
    14 Mar 2009
    Messages:
    399
    Likes Received:
    144
    Reputations:
    18
    Ну тогда могу предложить только делфи реализацию, т.к. сам использую.
    Смотреть в сторону fgint, у них есть примеры реализации рса,дса, эл-гамаля и эллиптических кривых

    http://www.submanifold.be/triade/GInt/gint.html
     
    1 person likes this.
  7. POS_troi

    POS_troi Elder - Старейшина

    Joined:
    1 Dec 2006
    Messages:
    1,569
    Likes Received:
    466
    Reputations:
    108
    2slesh

    А как насчет crypto++. Можно выдернуть DSA и будет все красиво )

    Туплю, вчитался в первый пост =/
     
  8. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Crypto API подходит на все 100% но увы завал на том, что сертификаты(открытые ключи) не должны быть в виде файлов и не должны помещатсья в хранилище сертификатов. Причем именно этот момент является самым обязательным