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; |