2012-09-28 5 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

どのように暗号化された文字列を渡していますか?クッキー、dbなど。 – solidau

+0

Windowsプログラムに戻しますか?印刷を介して、それはブラウザの出力としてそれをとります。 – Michael

+3

初期化ベクトル(IV)はどこで扱いますか? IVを設定しないと、PHPはすべてのバイトを ''\ 0' 'に設定したものを使います。あなたの解読ルーチンにそれを供給しているようには見えません。あなたは本当にIVを使うべきです、そうでなければCBCを捨てECBを使うかもしれません(もちろん、セキュリティを犠牲にして)。 – NullUserException

答えて

9

あなたが提供する情報は、特定のために言って十分ではありませんが、私はあなたの問題はキーの長さだと思います。

PHPコードでは、「12345678」をキーとして渡します。また、AES128のキー長は128ビットまたは16バイトです。 mcrypt_encryptのドキュメントに記載されているように、PHPは残りのバイトをゼロバイトで埋めます。

C++コードでは、キーバッファへのポインタのみをDecrypt関数に渡します。しかし、その後、あなたはそれからキーBLOBに16のバイトをコピーします。「12345678後にメモリに常駐してしまった8バイトより

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

:あなたのようなあなたの関数を呼び出す場合は、

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

"定数はキーblobにコピーされ、CryptImportKeyに渡されます。したがって、CとPHPコードのキーは実際には異なり、パディングエラーのために復号化に失敗します。

0

私はPHPとC#のうち、MD5のがらくたをdroped、彼ら

それを読ん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

の下を参照してください。今正しく動作しています。

ここで同じ回答を探している場合は、ここではサンプルコードをご覧ください。独自のキーと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

ヘッダ必須:

#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を使用し、アルゴリズムに必要な長さに変換します。