Avatar billede spathiphyllum Nybegynder
26. november 2007 - 11:58 Der er 8 kommentarer

Wincrypt hvordan

Hej,

jeg forsøger at finde ud af hvorledes man bruger wincrypt algoritmerne.
Egentlig skal jeg bare kryptere en tekststreng og gemme den i en tekstfil. Principielt kan jeg nøjes med en funktion der tager en tekststreng og et password som argumenter og som krypterer det i en buffer (+ en funktion der gør det modsatte).
Essentielt er dette vel funktionerne CryptEncrypt og CryptDecrypt.

Jeg har googlet rundt, men jeg kan ikke finde ud af det, selvom der er et utal af sider derude om emnet. Har nogen et eksempel?
Almindelig XOR kryptering er ikke inde i billedet.


S.
Avatar billede bertelbrander Novice
26. november 2007 - 19:34 #1
Har du kikket på eksemplerne fra msdn:
http://msdn2.microsoft.com/en-us/library/aa382358.aspx
http://msdn2.microsoft.com/en-us/library/aa382044.aspx

Jeg har aldrig brugt funktionerne men kan sikkert godt strikke et eksempel sammen.
Avatar billede spathiphyllum Nybegynder
26. november 2007 - 20:50 #2
Hej BB,

tak for dit bidrag, men jeg har set de sider du forslår samt mange, mange andre. Jeg skal være den første til at indrømme at jeg ikke fortsår så meget om emnet, og især ikke om impmenteringen som MS ar valgt.
Basalt set så har jeg brug for en funktion der tager en tekst og et password som argument og spytter den krypterede tekst ud (eller evt. krypterer teksten i dens egen buffer). Hvad der sker mellem input og ouput (hash, session keys og hva-ved-jeg) er lige nu mindre vigtigt for mig. Jeg skal ikke kryptere filer, jeg skal ikke arbejde med databaser, jeg har ikke 117 brugere; jeg skal bare kryptere en tekststreng.

Hvorfor kan MS ikke bare give en funktion der gør det svære arbejde?
Er der nogen her der kan?

S.
Avatar billede bertelbrander Novice
26. november 2007 - 20:59 #3
MS har lavet funktionen så den kan ALT, du har kun brug meget lidt.

Jeg kan godt strikke en funktion sammen senere på aftenen, der kan netop det du efterspørger.
Avatar billede spathiphyllum Nybegynder
26. november 2007 - 21:10 #4
BB,

det er vældig pænt af dig.
Venligst vær opmærksom på at jeg bruger ren C (ikke C++).

Mange tak på forhånd.
S.
Avatar billede bertelbrander Novice
27. november 2007 - 00:00 #5
Jeg har lavet et program ud fra eksemplerne.
Der er to funktioner, en til encryption og en de decryption

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <wincrypt.h>

#define KEYLENGTH  0x00800000
#define ENCRYPT_ALGORITHM CALG_RC4

BOOL EncryptString(const char* aInp, unsigned char* aDest, const char* PassWord);
BOOL DecryptString(const unsigned char* aInp, char* aDest, const char* PassWord);

void MyHandleError(LPTSTR psz, int nErrorNumber);

int main(void)
{
  char PassWord[32];
  char Input[32];
  unsigned char Encrypted[32];
  char Output[32];
  unsigned int n;

  printf("The string to encrypt: ");
  fflush(stdout);
  fgets(Input, sizeof(Input), stdin);
  if(Input[0] && Input[strlen(Input) - 1] == '\n')
      Input[strlen(Input) - 1] = 0;

  printf("Password: ");
  fflush(stdout);
  fgets(PassWord, sizeof(PassWord), stdin);
  if(PassWord[0] && PassWord[strlen(PassWord) - 1] == '\n')
      PassWord[strlen(PassWord) - 1] = 0;

  if(!EncryptString(Input, Encrypted, PassWord))
  {
      printf("Failed to encrypt\n");
      return EXIT_FAILURE;
  }
  printf("Encrypted data:");
  for(n = 0; n < strlen(Input); n++) /* The size of the encrypted data is the same as the size of the input. */
  {
      printf(" %02X", Encrypted[n]);
  }
  printf("\n");
  if(!DecryptString(Encrypted, Output, PassWord))
  {
      printf("Failed to decrypt\n");
      return EXIT_FAILURE;
  }
  printf("After Decrypt: %s\n", Output);
  return EXIT_SUCCESS;
}

BOOL EncryptString(const char* aInp, unsigned char* aDest, const char* aPassWord)
{
  BOOL Return = TRUE;
  HCRYPTPROV hCryptProv = 0;
  HCRYPTKEY hKey = 0;
  HCRYPTHASH hHash = 0;

  if(!CryptAcquireContext(&hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
  {
      MyHandleError("Error during CryptAcquireContext!\n", GetLastError());
      Return = FALSE;
  }
  else if(!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash))
  {
      MyHandleError("Error during CryptCreateHash!\n", GetLastError());
      Return = FALSE;
  }
  else if(!CryptHashData(hHash, (BYTE *)aPassWord, strlen(aPassWord), 0))
  {
      MyHandleError("Error during CryptHashData. \n", GetLastError());
      Return = FALSE;
  }

  else if(!CryptDeriveKey(hCryptProv, ENCRYPT_ALGORITHM, hHash, KEYLENGTH, &hKey))
  {
      MyHandleError("Error during CryptDeriveKey!\n", GetLastError());
      Return = FALSE;
  }
  else
  {
      DWORD Count = strlen(aInp);
      strcpy((char *)aDest, aInp);
      if(!CryptEncrypt(hKey, 0, TRUE, 0, aDest, &Count, Count))
      {
          MyHandleError("Error during CryptEncrypt. \n", GetLastError());
          Return = FALSE;
      }
  }

  if(hHash)
  {
      if(!(CryptDestroyHash(hHash)))
      {
        MyHandleError("Error during CryptDestroyHash.\n", GetLastError());
      }
  }

  if(hKey)
  {
      if(!(CryptDestroyKey(hKey)))
      {
        MyHandleError("Error during CryptDestroyKey!\n", GetLastError());
      }
  }

  if(hCryptProv)
  {
      if(!(CryptReleaseContext(hCryptProv, 0)))
      {
        MyHandleError("Error during CryptReleaseContext!\n", GetLastError());
      }
  }
  return Return;
}

BOOL DecryptString(const unsigned char* aInp, char* aDest, const char* aPassWord)
{
  BOOL Return = TRUE;

  HCRYPTPROV hCryptProv = 0;
  HCRYPTKEY hKey = 0;
  HCRYPTHASH hHash = 0;

  memset(aDest, 0, strlen((char *)aInp) + 1);
  if(!CryptAcquireContext(&hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
  {
      MyHandleError("Error during CryptAcquireContext!\n", GetLastError());
  }
  else if(!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash))
  {
      MyHandleError("Error during CryptCreateHash!\n", GetLastError());
      Return = FALSE;
  }
  else if(!CryptHashData(hHash, (BYTE *)aPassWord, strlen(aPassWord), 0))
  {
      MyHandleError("Error during CryptHashData. \n", GetLastError());
      Return = FALSE;
  }
  else if(!CryptDeriveKey(hCryptProv, ENCRYPT_ALGORITHM, hHash, KEYLENGTH, &hKey))
  {
      MyHandleError("Error during CryptDeriveKey!\n", GetLastError());
      Return = FALSE;
  }
  else
  {
      // Decrypt data.
      DWORD dwCount = strlen((char *)aInp);
      strcpy(aDest, (char *)aInp);
      if(!CryptDecrypt(hKey, 0, TRUE, 0, (BYTE *)aDest, &dwCount))
      {
          MyHandleError("Error during CryptDecrypt. \n", GetLastError());
          Return = FALSE;
      }
  }
  if(hHash)
  {
      if(!(CryptDestroyHash(hHash)))
      {
        MyHandleError("Error during CryptDestroyHash.\n", GetLastError());
      }
  }

  if(hKey)
  {
      if(!(CryptDestroyKey(hKey)))
      {
        MyHandleError("Error during CryptDestroyKey!\n", GetLastError());
      }
  }

  if(hCryptProv)
  {
      if(!(CryptReleaseContext(hCryptProv, 0)))
      {
        MyHandleError("Error during CryptReleaseContext!\n", GetLastError());
      }
  }

  return Return;
}

void MyHandleError(LPTSTR psz, int nErrorNumber)
{
    fprintf(stderr, "An error occurred in the program. \n");
    fprintf(stderr, "%s\n", psz);
    fprintf(stderr, "Error number %x.\n", nErrorNumber);
}
Avatar billede spathiphyllum Nybegynder
27. november 2007 - 13:16 #6
BB,
dit eksempel ser ud til at virke fint.
Tusind tak skal du have for din hjælp.

VH
S.
Avatar billede spathiphyllum Nybegynder
28. november 2007 - 10:05 #7
Hej igen BB,

et lille problem:

Hvis jeg bruger calloc til at at allokere tre buffers (som ovenfor navngivet Input, Output og Encrypted) med størrelsen 30 mb (ja, desværre!), så virker det ikke.
Det ender med at Encrypted bliver fx 100 bytes (målt med strlen, størrelsen afhænger af password), og nøjagtigt det samme for Output.
Hvad går galt? Er der en øvre grænse for string-længde for RSA? Googling giver lidt tvetydige infoer her.

Igen mange tak for hjælpen.
S.
Avatar billede bertelbrander Novice
28. november 2007 - 19:42 #8
My fault; de krypterede data er ikke en streng, det kan være vilkårlige data. Hvis tilfældigvis en af disse bytes er 0 vil længden blive forkert.
Jeg har tilføjet en size parameter til funktionerne for at angive længden på data.
Jeg tror ikke det er nødvendigt at kryptere i små blokke, men man kan godt.

En fixet version:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <wincrypt.h>

#define KEYLENGTH  0x00800000
#define ENCRYPT_ALGORITHM CALG_RC4

BOOL EncryptString(const char* aInp, unsigned char* aDest, DWORD aSize, const char* PassWord);
BOOL DecryptString(const unsigned char* aInp, char* aDest, DWORD aSize, const char* PassWord);

void MyHandleError(LPTSTR psz, int nErrorNumber);

int main(void)
{
  char PassWord[32];
  char Input[32];
  unsigned char Encrypted[32];
  char Output[32];
  unsigned int n;

  printf("The string to encrypt: ");
  fflush(stdout);
  fgets(Input, sizeof(Input), stdin);
  if(Input[0] && Input[strlen(Input) - 1] == '\n')
      Input[strlen(Input) - 1] = 0;

  printf("Password: ");
  fflush(stdout);
  fgets(PassWord, sizeof(PassWord), stdin);
  if(PassWord[0] && PassWord[strlen(PassWord) - 1] == '\n')
      PassWord[strlen(PassWord) - 1] = 0;

  if(!EncryptString(Input, Encrypted, strlen(Input), PassWord))
  {
      printf("Failed to encrypt\n");
      return EXIT_FAILURE;
  }
  printf("Encrypted data:");
  for(n = 0; n < strlen(Input); n++) /* The size of the encrypted data is the same as the size of the input. */
  {
      printf(" %02X", Encrypted[n]);
  }
  printf("\n");
  if(!DecryptString(Encrypted, Output, strlen(Input), PassWord))
  {
      printf("Failed to decrypt\n");
      return EXIT_FAILURE;
  }
  Output[strlen(Input)] = 0; /* Make the output a null terminated string */
  printf("After Decrypt: %s\n", Output);
  return EXIT_SUCCESS;
}

BOOL EncryptString(const char* aInp, unsigned char* aDest, DWORD aSize, const char* aPassWord)
{
  BOOL Return = TRUE;
  HCRYPTPROV hCryptProv = 0;
  HCRYPTKEY hKey = 0;
  HCRYPTHASH hHash = 0;

  if(!CryptAcquireContext(&hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
  {
      MyHandleError("Error during CryptAcquireContext!\n", GetLastError());
      Return = FALSE;
  }
  else if(!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash))
  {
      MyHandleError("Error during CryptCreateHash!\n", GetLastError());
      Return = FALSE;
  }
  else if(!CryptHashData(hHash, (BYTE *)aPassWord, strlen(aPassWord), 0))
  {
      MyHandleError("Error during CryptHashData. \n", GetLastError());
      Return = FALSE;
  }

  else if(!CryptDeriveKey(hCryptProv, ENCRYPT_ALGORITHM, hHash, KEYLENGTH, &hKey))
  {
      MyHandleError("Error during CryptDeriveKey!\n", GetLastError());
      Return = FALSE;
  }
  else
  {
      DWORD Count = aSize;
      memcpy(aDest, aInp, aSize);
      if(!CryptEncrypt(hKey, 0, TRUE, 0, aDest, &Count, Count))
      {
          MyHandleError("Error during CryptEncrypt. \n", GetLastError());
          Return = FALSE;
      }
  }

  if(hHash)
  {
      if(!(CryptDestroyHash(hHash)))
      {
        MyHandleError("Error during CryptDestroyHash.\n", GetLastError());
      }
  }

  if(hKey)
  {
      if(!(CryptDestroyKey(hKey)))
      {
        MyHandleError("Error during CryptDestroyKey!\n", GetLastError());
      }
  }

  if(hCryptProv)
  {
      if(!(CryptReleaseContext(hCryptProv, 0)))
      {
        MyHandleError("Error during CryptReleaseContext!\n", GetLastError());
      }
  }
  return Return;
}

BOOL DecryptString(const unsigned char* aInp, char* aDest, DWORD aSize, const char* aPassWord)
{
  BOOL Return = TRUE;

  HCRYPTPROV hCryptProv = 0;
  HCRYPTKEY hKey = 0;
  HCRYPTHASH hHash = 0;

  if(!CryptAcquireContext(&hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
  {
      MyHandleError("Error during CryptAcquireContext!\n", GetLastError());
  }
  else if(!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash))
  {
      MyHandleError("Error during CryptCreateHash!\n", GetLastError());
      Return = FALSE;
  }
  else if(!CryptHashData(hHash, (BYTE *)aPassWord, strlen(aPassWord), 0))
  {
      MyHandleError("Error during CryptHashData. \n", GetLastError());
      Return = FALSE;
  }
  else if(!CryptDeriveKey(hCryptProv, ENCRYPT_ALGORITHM, hHash, KEYLENGTH, &hKey))
  {
      MyHandleError("Error during CryptDeriveKey!\n", GetLastError());
      Return = FALSE;
  }
  else
  {
      // Decrypt data.
      DWORD dwCount = aSize;
      memcpy(aDest, aInp, aSize);
      if(!CryptDecrypt(hKey, 0, TRUE, 0, (BYTE *)aDest, &dwCount))
      {
          MyHandleError("Error during CryptDecrypt. \n", GetLastError());
          Return = FALSE;
      }
  }
  if(hHash)
  {
      if(!(CryptDestroyHash(hHash)))
      {
        MyHandleError("Error during CryptDestroyHash.\n", GetLastError());
      }
  }

  if(hKey)
  {
      if(!(CryptDestroyKey(hKey)))
      {
        MyHandleError("Error during CryptDestroyKey!\n", GetLastError());
      }
  }

  if(hCryptProv)
  {
      if(!(CryptReleaseContext(hCryptProv, 0)))
      {
        MyHandleError("Error during CryptReleaseContext!\n", GetLastError());
      }
  }

  return Return;
}

void MyHandleError(LPTSTR psz, int nErrorNumber)
{
    fprintf(stderr, "An error occurred in the program. \n");
    fprintf(stderr, "%s\n", psz);
    fprintf(stderr, "Error number %x.\n", nErrorNumber);
}
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester