2012-09-28 162 views
13

我卡住了。似乎由PHP完成的AES加密無法在Windows中解密。PHP加密和Windows解密

PHP代碼:

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

Windows代碼: 「S」 具有由上述響應從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); 
} 

什麼可能是錯的?

+0

你怎麼傳遞加密的字符串?即餅乾,數據庫等.. – solidau

+0

傳遞給Windows程序?通過打印並將其作爲瀏覽器的輸出。 – Michael

+3

你在哪裏處理初始化向量(IV)?如果你沒有設置IV,PHP會使用其所有字節設置爲''\ 0''的字符;但它看起來並不像你提供給你的解密程序。儘管如此,你真的應該使用IV,否則可能會溝通CBC並使用ECB(當然是以犧牲安全爲代價)。 – NullUserException

回答

9

您提供的信息是不夠的,肯定地說,但我覺得你的問題是密鑰長度。

在PHP代碼中,您將「12345678」作爲關鍵字。 AES128的密鑰長度爲128位或16字節。 PHP填充零字節的剩餘部分,如mcrypt_encrypt上的文檔所述。

在C++代碼中,只將指向密鑰緩衝區的指針傳遞給Decrypt函數。但你16個字節複製從它的密鑰團:

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

然後,如果你打電話給你的功能,如:

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

比碰巧駐留在內存中的「12345678之後的8個字節「常量將被複制到密鑰塊並傳遞給CryptImportKey作爲實際密鑰。因此,C和PHP代碼中的密鑰實際上是不同的,由於填充錯誤,解密將失敗。

0

請參見下面的網址

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

讀它

我DROP掉了MD5屁滾尿流的PHP和C#,和他們一現在工作正常。

爲防萬一你在這裏尋找相同的答案,這裏是一個示例代碼。不要忘了讓自己的密鑰和IV

PHP(雖然這些波紋管會的工作,不建議使用!):

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-使用Symbian C++解密聯繫人數據庫條目

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

header要求:

#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

加密聯繫人字段

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

解密聯繫人字段

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 MCRYPT函數與Windows解密函數有點不同。

由於mcrypt函數採用任意長度的密鑰並通過在密鑰字符串的末尾添加\0將其轉換爲算法所需的長度。

請注意創建一個具有指定長度的密鑰,以便在算法的兩側進行加密。

在密鑰上使用md5,然後將其轉換爲算法所需的長度。