IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Delphi Discussion :

[DCPCrypt] Optimisation de dérivation de clé avec PBKDF2


Sujet :

Delphi

  1. #1
    Membre régulier Avatar de ALEX77
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 138
    Points : 76
    Points
    76
    Par défaut [DCPCrypt] Optimisation de dérivation de clé avec PBKDF2
    Bonjour

    J'ai parcouru le web pour trouver comment créer une fonction de dérivation de clé PBKDF2 et je souhaiterais savoir si on peut optimiser le code de l'unité que j'ai écrite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    unit PBKDF2Unit;
     
    interface
     
    const HASH_RIPEMD160         = 1;
          HASH_SHA512            = 2;
     
    uses DCPsha512, DCPripemd160, DCPcrypt2, Math;
     
    function PBKDF2(pass, salt: ansistring; count, kLen: Integer; algorithm : byte): ansistring;
     
    implementation
     
    function PBKDF2(pass, salt: ansistring; count, kLen: Integer; algorithm : byte): ansistring;
    var block_count, hashSizeBytes, i, j : integer;
        xorsum, last : ansistring;
        hashObject : TDCP_hash;
     
      function XorBlock(s, x: ansistring): ansistring; inline;
      var i: Integer;
      begin
       SetLength(Result, Length(s));
       for i := 1 to Length(s) do Result[i] := Char(Byte(s[i]) xor Byte(x[i]));
      end;
     
      function RPad(x: ansistring; c: Char; s: Integer): ansistring; inline;
      var i : Integer;
      begin
       Result := x;
       if Length(x) < s then for i := 1 to s-Length(x) do Result := Result + c;
      end;
     
      function CalcDigest(text: ansistring): ansistring; inline;
      begin
       hashObject.Init;
       hashObject.UpdateStr(text);
       SetLength(Result, hashSizeBytes);
       hashObject.Final(Result[1]);
      end;
     
      function HMAC(message, key : ansistring) : ansistring; inline;
      const blocksize = 64;
      begin
       // Definition RFC 2104
       if Length(key) > blocksize then key:= CalcDigest(key);
       key := RPad(key, #0, blocksize);
       Result := CalcDigest(XorBlock(key, RPad('', #$36, blocksize)) + message);
       Result := CalcDigest(XorBlock(key, RPad('', #$5c, blocksize)) + result);
      end;
     
      function IntX(i: Integer): ansistring; inline;
      begin
       Result := Char(i shr 24) + Char(i shr 16) + Char(i shr 8) + Char(i);
      end;
     
    begin
     result:= '';
     
     case algorithm of
      HASH_RIPEMD160 : hashObject:= TDCP_ripemd160.Create(nil);
      HASH_SHA512    : hashObject:= TDCP_sha512.Create(nil);
     end;
     
     try
      hashSizeBytes:= hashObject.GetHashSize div 8;
      block_count:= ceil(kLen / hashSizeBytes);
      for i:= 1 to block_count do
      begin
       last:= salt + IntX(i); // OK
       // first iteration
       last:= HMAC(last,pass); // OK
       xorsum:= last;
       // perform the other count - 1 iterations
       for j:= 1 to (count-1) do
       begin
        last:= HMAC(last,pass);
        xorsum:= XorBlock(xorsum,last);
       end;
       result:= result+xorsum;
      end;
      result:= copy(result,1,kLen);
     finally
      hashObject.free;
     end;
    end;
     
    end.
    ça fonctionne plutôt bien mais le principal problème reste la vitesse avec le hashage ripemd160 ; avec 2000 itérations faut compter environ 125-140 ms ; peut-on amélorer ce temps ?

    Merci pour vos réponses

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    la présence de inline , tu as donc au moins une version D2007,
    il faudrait vérifier si le inline fait vraiment effet (pas de warning ?), si il s'applique !
    Si le inline ne s'applique pas tu peux passer les AnsiString en const
    Pour les variables locales qui n'ont pas de compteur de référence, cela évite une allocation, en D7 c'était notable, avec FastMM cela l'est nettement moins
    Comme ton Char/Byte semble compatible avec ton AnsiString[], je suppose une version antérieure à D2009
    D2007, je ne sais plus si cette version avait déjà FastMM intégré ou non ?! il me semble que c'est le cas

    D'ailleurs Result[i] peut être amélioré en manipulant via PAnsiChar

    ta fonction RPad devrait être totalement repensé, la concaténation Result := Result + ... est ce qu'il y a de plus lent,
    même si avec FastMM le gain se faible va voir ce sujet, où je propose une alternative au Format : SetLengthStuff/CopyStuff qui faisait des merveilles sur des AnsiString en D7

    tu as un autre Result := Result + ..., il semble que klen soit la taille maximale, autant allouer le buffer d'un seul coup, et utiliser Move sur du PAnsiChar pour le remplir
    Beaucoup de réallocation évitée ! même si FastMM divise par 100 le coût de ces opérations par rapport à D7

    Pour intX, faudrait voir si l'on triche avec un record union, si c'est plus rapide que plusieurs shr
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
     
      function IntX(i: Integer): ansistring; inline;
      type
        TDecomposedInteger = packed record
          case Integer of
            0: (b0, b1, b2, b3: Char);
            1: (i: Integer);
        end;
      begin
        Result := TDecomposedInteger(I).b0 + TDecomposedInteger(I).b1 + TDecomposedInteger(I).b2 + TDecomposedInteger(I).b3;  
      end;
    A priori, tu utilises la lib DCPcrypt V2,
    je pense que t'adresser à l'auteur pour avoir un code d'utilisation optimal de sa lib donnera peut-être un meilleur résultat que sur le forum
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre régulier Avatar de ALEX77
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 138
    Points : 76
    Points
    76
    Par défaut
    Salut et merci pour ton aide

    Effectivement en réécrivant la function RPad je passe de 140ms à 47 environ pas mal.
    Voici le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
      function RPad(x: AnsiString; aChar: AnsiChar; aCharCount: Integer): AnsiString; inline;
      var PadCount: Integer;
      begin
       PadCount := ACharCount - Length(x);
       if PadCount > 0 then
       begin
        SetLength(Result, ACharCount);
        FillChar(Result[1], AcharCount, AChar);
        Move(x[1], Result[1], Length(x));
       end else Result := x;
      end;
    J'essaie maintenant de voir avec la function XorBlock si tu as une idée...

Discussions similaires

  1. Optimisation du temps de production avec FOP
    Par polymorphisme dans le forum XML/XSL et SOAP
    Réponses: 3
    Dernier message: 14/04/2011, 16h46
  2. Réponses: 4
    Dernier message: 24/07/2010, 11h35
  3. Réponses: 0
    Dernier message: 23/07/2010, 10h04
  4. [Optimisation] Utilisation de l'index avec une date
    Par Batou69 dans le forum Développement
    Réponses: 13
    Dernier message: 23/10/2009, 08h47
  5. Réponses: 7
    Dernier message: 25/03/2009, 15h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo