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

API, COM et SDKs Delphi Discussion :

AES via CryptAPI


Sujet :

API, COM et SDKs Delphi

  1. #1
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 460
    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 460
    Points : 24 874
    Points
    24 874
    Par défaut AES via CryptAPI
    En m'inspirant sujet WebSocket HTML5 et Delphi pour l'utilisation de CryptAPI pour du MD5, j'ai regardé ce que propose Windows pour AES !

    J'ai surtout utilisé les fonctions AES de MySQL, je n'ai jamais eu besoin de le faire réellement !
    j'utilise une wcrypt2.pas trouvé sur KODERS, il me manque quelques constantes mal ça se trouve ailleurs !

    Une collègue est en ce moment en train de programmer sur son micro-proc 16bits, une version C en s'inspirant de sources trouvés sur le net, elle a un code mais qui ne semble pas donner le bon résultat !

    On a des valeurs de test, le Text en Clair, la Clé et le Cypher Text, les résultats ne sont pas les mêmes, j'ai donc baclé en Delphi une petite fonction de test qui retourne le Cypher Text ainsi que la confirmation que l'on peut récupérer la valeur d'origine !

    c'est sous XE d'où les AnsiString, oui, je sais mélange AnsiString\PByte, c'est moche, je bosse en C++2007 normalement, ça me fait un petit exercice en Delphi, j'ai perdu le reflexe du @, je me suis habitué au &

    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
    //---------------------------------------------------------------------------
    function TTestWebSocketsForm.MakeAES(const Input, Key: AnsiString; out Confirm: AnsiString; AESFinal: boolean): AnsiString;
    var
      pbContent: PByte;
      pbResult: PByte;
      pbConfirm: PByte;
      hCryptProvider: HCRYPTPROV;
      KeyBlob: packed record
        Header: BLOBHEADER;
        Size: DWORD;
        Data: array[0..15] of Byte;
      end;
      hKey, hEncryptKey, hDecryptKey: HCRYPTKEY;
      dwKeyCypherMode: DWORD;
      InputLen, ResultLen: DWORD;
    const
      PROV_RSA_AES = 24;
      CALG_AES_128 = $0000660e;
    begin
      pbContent := Pointer(PAnsiChar(Input));
     
      Result := '';
      // MS_ENH_RSA_AES_PROV
      if CryptAcquireContext(@hCryptProvider, nil, nil, PROV_RSA_AES, CRYPT_VERIFYCONTEXT) then
      begin
        KeyBlob.Header.bType := PLAINTEXTKEYBLOB;
        keyBlob.Header.bVersion := CUR_BLOB_VERSION;
        keyBlob.Header.reserved := 0;
        keyBlob.Header.aiKeyAlg := CALG_AES_128;
        keyBlob.Size := Length(Key) * SizeOf(AnsiChar);
        CopyMemory(@keyBlob.Data[0], @Key[1], keyBlob.Size);
     
        if CryptImportKey(hCryptProvider, @KeyBlob, SizeOf(KeyBlob), 0, 0, @hKey) then
        begin
          if CryptDuplicateKey(hKey, nil, 0, @hEncryptKey) then
          begin
            if CryptDuplicateKey(hKey, nil, 0, @hDecryptKey) then
            begin
              // Très important, une clé pour Encrypt et une autre pour Decrypt sinon cela fausse le calcul, curieux en ECB cela ne devrait pas, en CBC ou CFB semble tout à fait logique puisque le bloc précédent est utilisé pour le chiffrage du suivant ...
              dwKeyCypherMode := CRYPT_MODE_ECB;
              CryptSetKeyParam(hEncryptKey, KP_MODE, @dwKeyCypherMode, 0);
              CryptSetKeyParam(hDecryptKey, KP_MODE, @dwKeyCypherMode, 0);
     
              Result := Input;
              InputLen := Length(Result) * SizeOf(AnsiChar);
              ResultLen := InputLen;
              if CryptEncrypt(hEncryptKey, 0, AESFinal, 0, nil, @ResultLen, 0) then
              begin
                SetLength(Result, ResultLen);
                pbResult := Pointer(PAnsiChar(Result));
                if CryptEncrypt(hEncryptKey, 0, AESFinal, 0, pbResult, @InputLen, ResultLen) then
                begin
                  SetLength(Confirm, ResultLen);
                  pbConfirm := Pointer(PAnsiChar(Confirm));
                  CopyMemory(pbConfirm, pbResult, ResultLen);
                  if CryptDecrypt(hDecryptKey, 0, AESFinal, 0, pbConfirm, @InputLen) then
                    SetLength(Confirm, InputLen)
                  else
                    Confirm := IntToStr(GetLastError());
                end
                else
                  Result := IntToStr(GetLastError());
              end;
     
              CryptDestroyKey(hDecryptKey);
            end;
     
            CryptDestroyKey(hEncryptKey);
          end;
     
          CryptDestroyKey(hKey);
        end;
     
        CryptReleaseContext(hCryptProvider, 0);
      end;
    end;
    J'obtiens presque les bonnes valeurs !
    Tout ce joue sur AESFinal qui en censé indiquer la fin du buffer, si l'on crypte un gros buffer, dans mon test, je n'ai qu'un buffer de 128 bits, donc je mets True à bFinal (... Final is set to TRUE for the last or only block ...)

    Ce que je ne comprends pas, c'est pourquoi il me génére un Cypher Text de 256 Bits ?
    D'après les valeurs de référence, mon texte clair et chiffré sont de même longueur !
    J'obtiens bien les bons 128 premiers bits puis 128 bits non prévus !

    Si, je mets bFinal à FALSE, j'obtients le bon résultat, juste les 128 bits prévus
    Hors, c'est contraire à la documentation ...
    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

  2. #2
    Rédacteur
    Avatar de omen999
    Profil pro
    Inscrit en
    Février 2006
    Messages
    1 296
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 1 296
    Points : 3 549
    Points
    3 549
    Par défaut
    salut,
    si je continue la lecture de la doc...
    If the key is a block cipher key, the data is padded to a multiple of the block size of the cipher. If the data length equals the block size of the cipher, one additional block of padding is appended to the data. To find the block size of a cipher, use CryptGetKeyParam to get the KP_BLOCKLEN value of the key.
    nomen omen, nemo non omen - Consultez la FAQ VBScript et les cours et tutoriels VBScript
    le plus terrible lorsqu'une voiture renverse un piéton, c'est que ce sont les freins qui hurlent. (ramón)
    pas de questions techniques par mp

  3. #3
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 460
    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 460
    Points : 24 874
    Points
    24 874
    Par défaut
    Tout à fait, j'ai vu ça aussi, c'est d'ailleurs cette section remarks qui m'a poussé à cloner mes clefs avec CryptDuplicateKey !

    J'avais vu que c'était une opération volontaire de CryptAPI mais je ne pige pas la raison de cet ajout !
    Le matériel qui chiffre en AES n'applique pas cette procédure de block supplémentaire pour un bloc de 128Bits même si c'est le seul !
    Pourquoi Windows le fait si bFinal est à true ?
    Je t'avoue que les spécifications de EAS me laisse perplexe et ne parle pas de ce bourrage
    les codes C trouvés sur le Net ne font jamais cela, il travaille aussi en bloc clair de unsigned char [16] et renvoie un Cypher unsigned char [16], jamais il n'est question d'un bloc additionnel (leur structure même de code ne le permet pas)

    La Question reste ouverte, juste pour ma curiosité puisqu'en laissant bFinal à False, cela fonctionne comme le matériel interfacé ou les algo du micro-proc
    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

Discussions similaires

  1. [Kylix] PostgreSql via ODBC
    Par doykati dans le forum EDI
    Réponses: 3
    Dernier message: 08/02/2007, 10h10
  2. [TP7] Calculer sin, cos, tan, sqrt via le FPU
    Par zdra dans le forum Assembleur
    Réponses: 8
    Dernier message: 25/11/2002, 04h09
  3. Réponses: 4
    Dernier message: 05/06/2002, 12h15
  4. Réponses: 2
    Dernier message: 30/05/2002, 08h54
  5. [Kylix] Excel via kylix
    Par Billy joel dans le forum EDI
    Réponses: 1
    Dernier message: 23/05/2002, 11h57

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