PHP-шифрование и расшифровка Windows
Я застрял. Похоже, что шифрование AES, выполняемое PHP, не может быть расшифровано в окнах.
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);
}
Что может быть неправильным?
Ответы
Ответ 1
Предоставленной вам информации недостаточно, чтобы сказать наверняка, но я думаю, что ваша проблема - это длина ключа.
В PHP-коде вы передаете "12345678" в качестве ключа. А AES128 имеет длину ключа 128 бит или 16 байт.
PHP накладывает оставшиеся нулевые байты, как указано в документации по mcrypt_encrypt.
В коде С++ вы передаете только указатель на свой буфер ключей для функции расшифровки. Но затем вы копируете 16 байтов из него в ключевой BLOB:
aes_blob128.keySize = 16;
memcpy(aes_blob128.bytes, key, 16);
Затем, если вы вызываете свою функцию следующим образом:
char dest[16];
bool result = Decrypt(string_from_php,"12345678",dest);
чем 8 байтов, которые находятся в памяти после того, как константа "12345678" будет скопирована в ключевое blob и передана в CryptImportKey в качестве реального ключа. Таким образом, ключ в C и в PHP-коде будет фактически другим, и дешифрование завершится неудачно из-за ошибки заполнения.
Ответ 2
Функции PHP MCRYPT немного отличаются от функций дешифрования Windows.
Поскольку функция mcrypt принимает ключ любой длины и преобразует его в длину, требуемую алгоритмом, добавив \0
в конец строки ключа.
Обратите внимание, чтобы создать ключ с указанной длиной, необходимой для шифрования с помощью алгоритма с обеих сторон.
используйте md5 на ключе, а затем преобразуйте его в длину, необходимую для алгоритма.
Ответ 3
См. ниже URL
Шифрование в PHP, расшифровка в С# (WP7/Silverlight) с использованием 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
Прочитайте его
Я бросил MD5 дерьмо из PHP и С#, и теперь они работают нормально.
На всякий случай, когда вы бросили здесь, ища тот же ответ, вот пример кода. Не забудьте сделать свой собственный ключ и 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);
}
С++
Шифровать-расшифровать записи базы данных контактов с помощью Symbian С++
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;
}
}
С#
byte[] cripted = EncryptStringToBytes("Test", System.Text.Encoding.UTF8.GetBytes("00000000000000000000000000000000"), System.Text.Encoding.UTF8.GetBytes("0000000000000000"));