2012-09-28 20 views
13

Sono bloccato. Sembra che la crittografia AES fatta da PHP non possa essere decifrata in Windows.PHP Encrypt and Windows Decrypt

codice PHP:

$encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128,"12345678", "test", MCRYPT_MODE_CBC)); 

codice di Windows: "s" ha la stringa che viene creato dalla risposta di cui sopra dopo la conversione di ritorno da Base64.

bool Decrypt(char* s,char* key,char* dest) 
{ 
// Create the crypto provider context. 
HCRYPTPROV hProvider = NULL; 
if (!CryptAcquireContext(&hProvider, 
    NULL, // pszContainer = no named container 
    MS_ENH_RSA_AES_PROV, // pszProvider = default provider 
    PROV_RSA_AES, 
    0)) 
     return false; 


// Construct the blob necessary for the key generation. 
aes128keyBlob aes_blob128; 

aes_blob128.header.bType = PLAINTEXTKEYBLOB; 
aes_blob128.header.bVersion = CUR_BLOB_VERSION; 
aes_blob128.header.reserved = 0; 
aes_blob128.header.aiKeyAlg = CALG_AES_128; 
aes_blob128.keySize = 16; 
memcpy(aes_blob128.bytes, key, 16); 

HCRYPTKEY hKey = NULL; 
if (!CryptImportKey(hProvider, 
    (BYTE*)(&aes_blob128), 
    sizeof(aes_blob128), 
    NULL, // 
    0,  // 
    &hKey)) { 

     ... 
    } 


// Set Mode 
DWORD dwMode = CRYPT_MODE_CBC; 
CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0); 


DWORD length = 16; 
BOOL X = CryptDecrypt(hKey, 
    NULL, // hHash = no hash 
    TRUE, // Final 
    0, 
    (BYTE*)s, 
    &length); 
//int le = GetLastError(); 
memcpy(dest,s,16); 

CryptDestroyKey(hKey); 
CryptReleaseContext(hProvider, 0); 
} 

Cosa potrebbe essere che non va?

+0

come stai passando la stringa crittografata? cioè cookie, db ecc. – solidau

+0

Passandolo nuovamente al programma Windows? Via stampa e lo prende come output del browser. – Michael

+3

Dove stai gestendo il vettore di inizializzazione (IV)? Se non si imposta un IV, PHP ne usa uno con tutti i suoi byte impostati su ''\ 0''; ma non sembra che tu lo stia fornendo alla tua routine di decrittazione. Dovresti davvero usare una flebo, altrimenti potresti anche cullare la CBC e usare la BCE (a scapito della sicurezza, ovviamente). – NullUserException

risposta

9

Le informazioni che hai fornito non è sufficiente per dire con certezza, ma credo che il problema è la lunghezza della chiave.

Nel codice PHP si passa "12345678" come chiave. E AES128 ha una lunghezza chiave di 128 bit o 16 byte. I pad PHP restano con zero byte, come indicato nella documentazione su mcrypt_encrypt.

Nel codice C++ si passa solo il puntatore al buffer delle chiavi per decrittografare la funzione. Ma poi si copia 16 byte da esso per il BLOB chiave:

aes_blob128.keySize = 16; 
memcpy(aes_blob128.bytes, key, 16); 

Poi se si chiama la funzione come:

char dest[16]; 
bool result = Decrypt(string_from_php,"12345678",dest); 

rispetto agli 8 byte che accadono a risiedere in memoria dopo la "12345678 La costante " verrà copiata nel blob della chiave e passata a CryptImportKey come chiave effettiva. Quindi la chiave in C e nel codice PHP sarebbe in realtà diversa e la decrittografia fallirà a causa di un errore di riempimento.

0

Vedere sotto URL

Encrypt in PHP, Decrypt in C# (WP7/Silverlight) using AES/Rijndael

http://pumka.net/2009/12/16/rsa-encryption-cplusplus-delphi-cryptoapi-php-openssl-2/

http://www.developer.nokia.com/Community/Wiki/Encrypt-Decrypt_contacts_database_entries_using_Symbian_C%2B%2B

leggerlo

ho droped la merda MD5 di PHP e C#, e un ora funziona correttamente.

Nel caso in cui sei passato qui cercando la stessa risposta, ecco un codice di esempio. Non dimenticate di fare il proprio chiave e iv

PHP (anche se quelli qui sotto saranno lavorare, non è raccomandato per l'uso!):

function encrypt128($message) { 

    $vector = "0000000000000000"; 
    $key = "00000000000000000000000000000000"; 

    $block = mcrypt_get_block_size('rijndael_128', 'cbc'); 
    $pad = $block - (strlen($message) % $block); 
    $message .= str_repeat(chr($pad), $pad); 

    $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', 'cbc', ''); 
    mcrypt_generic_init($cipher, $key, $vector); 
    $result = mcrypt_generic($cipher, $message); 
    mcrypt_generic_deinit($cipher); 

    return base64_encode($result); 
} 

C++

Encrypt- Decifrare le voci del database dei contatti utilizzando Symbian C++

http://www.developer.nokia.com/Community/Wiki/Encrypt-Decrypt_contacts_database_entries_using_Symbian_C%2B%2B

intestazioni richieste:

#include <cntdb.h> // CContactDatabse, 
#include <cntitem.h> //CContactItem,CContactItemFieldSet 

http://www.developer.nokia.com/Community/Wiki/Encrypt-Decrypt_contacts_database_entries_using_Symbian_C%2B%2B

Encrypt Contatto I campi

void CEncryptContactContainer::EncryptAll() 
{ 
    CContactDatabase *contactDB = CContactDatabase::OpenL(); 
    CleanupStack::PushL(contactDB); 

    TContactIter iter(*contactDB); 
    TContactItemId aContactId; 

//Developer can take Heap based descriptor for large/unknown size of contact items. 
    TBuf16<70> aValue; 

    const CContactIdArray* contactArray = contactDB->SortedItemsL(); 

    TInt cnt=contactArray->Count(); 

    for(TInt i=0;i<cnt;i++) 
    { 
     CContactItem* contactItem=NULL; 

     contactItem= contactDB->OpenContactL((*contactArray)[i]); 
     CleanupStack::PushL(contactItem); 

     CContactItemFieldSet& fieldSet= contactItem->CardFields(); 
     TInt fieldCount=fieldSet.Count(); // This will give number of contact fields. 

     for(TInt index=0; index < fieldCount; index++) 
     { 
      CContactItemField& field = fieldSet[index]; 
      const CContentType& type = field.ContentType(); 
      if(!(type.ContainsFieldType(KUidContactFieldBirthday))) 
      { 
       TPtrC name = contactItem->CardFields()[index].TextStorage()->Text(); 
       aValue.Copy(name); 
       Encrypt(aValue); // Call real encyption here 
       contactItem->CardFields()[index].TextStorage()->SetTextL(aValue); 
      } 
     } //Inner for loop ends here 
     contactDB->CommitContactL(*contactItem); 
     CleanupStack::PopAndDestroy(contactItem); 
    } //Outer for loop ends here 
    CleanupStack::PopAndDestroy(contactDB); 
} 

void CEncryptContactContainer:: Encrypt (TDes& aValue) 
{ 
    for(TInt iCount=0; iCount< aValue.Length();iCount++) 
    { 
     aValue[iCount]+=3; 
    } 
} 

Decrypt Contatto I campi

void CEncryptContactContainer::DecryptAll() 
{ 
    CContactDatabase *contactDB = CContactDatabase::OpenL(); 
    CleanupStack::PushL(contactDB); 

    TContactIter iter(*contactDB); 
    TContactItemId aContactId; 
    TBuf16<70> aValue; 

    const CContactIdArray* contactArray = contactDB->SortedItemsL(); 

    TInt cnt=contactArray->Count(); 

    for(TInt i=0;i<cnt;i++) 
    { 
     CContactItem* contactItem=NULL; 

     contactItem= contactDB->OpenContactL((*contactArray)[i]); 
     CleanupStack::PushL(contactItem); 

     CContactItemFieldSet& fieldSet= contactItem->CardFields(); 
     TInt fieldCount=fieldSet.Count(); // This will give number of contact fields. 

     for(TInt index=0; index < fieldCount; index++) 
     { 
      CContactItemField& field = fieldSet[index]; 
      const CContentType& type = field.ContentType(); 
      if(!(type.ContainsFieldType(KUidContactFieldBirthday))) 
      { 
       TPtrC name = contactItem->CardFields()[index].TextStorage()->Text(); 
       aValue.Copy(name); 
       Decrypt(aValue); 
       contactItem->CardFields()[index].TextStorage()->SetTextL(aValue); 
      } 
     } //Inner for loop ends here 
     contactDB->CommitContactL(*contactItem); 
     CleanupStack::PopAndDestroy(contactItem); 
    } //Outer for loop ends here 
    CleanupStack::PopAndDestroy(contactDB); 
} 

void CEncryptContactContainer:: Decrypt (TDes& aValue) 
{ 
    for(TInt iCount=0; iCount< aValue.Length();iCount++) 
    { 
     aValue[iCount]-=3; 
    } 
} 

C#:

byte[] cripted = EncryptStringToBytes("Test", System.Text.Encoding.UTF8.GetBytes("00000000000000000000000000000000"), System.Text.Encoding.UTF8.GetBytes("0000000000000000")); 
1

PHP Le funzioni di MCRYPT sono leggermente diverse rispetto alle funzioni di decrittografia di Windows.

Poiché la funzione mcrypt utilizza la chiave di qualsiasi lunghezza e la converte alla lunghezza richiesta dall'algoritmo, aggiunge \0 alla fine della stringa di chiavi.

Si prega di notare per creare una chiave con la lunghezza specificata richiesta per la crittografia dall'algoritmo su entrambi i lati.

utilizzare md5 sulla chiave e quindi convertirlo nella lunghezza richiesta per l'algoritmo.