Шифрование OPENSSL Blowfish CBC отличается от PHP до переполнения стека

Я пытаюсь зашифровать и расшифровать связь между библиотекой C ++ и сервером PHP, используя библиотеку OPENSSL в обоих из них. Я хочу использовать алгоритм Blowfish CBC, но, похоже, результаты различаются между кодом C ++ и кодом PHP. Код C ++ взят отсюда:

Это код PHP:

<?php
function strtohex($x)
{
$s='';
foreach (str_split($x) as $c) $s.=sprintf("%02X",ord($c));
return($s);
}$encryptedMessage = openssl_encrypt("input", "BF-CBC", "123456", 0, "initvect");echo $encryptedMessage;
echo "\n";
echo strtohex($encryptedMessage);

Вывод PHP таков:

x9jDa2WMwvQ=
78396A446132574D7776513D

Это код C ++:

bool do_encrypt(const char *in, unsigned char *out, int *outlen, unsigned    char *key, unsigned char *iv)
{
int buflen, tmplen;

EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_EncryptInit_ex(&ctx, EVP_bf_cbc(), nullptr, key, iv);

if (!EVP_EncryptUpdate(&ctx, out, &buflen, (unsigned char*)in,     strlen(in)))
{
return false;
}

if (!EVP_EncryptFinal_ex(&ctx, out + buflen, &tmplen))
{
return false;
}

buflen += tmplen;
*outlen = buflen;
EVP_CIPHER_CTX_cleanup(&ctx);

return true;
}

unsigned char output[2048] = { 0 };
int outLen;

auto result = do_encrypt("input", output, &outLen, (unsigned char*)"123456", (unsigned char*)"initvect");

BIGNUM *outputStr = BN_new();
BN_bin2bn(output, outLen, outputStr);

cout << base64_encode(output, outLen) << "\n";
cout << BN_bn2hex(outputStr) << "\n";

Вывод C ++ такой:

 EfRhhWqGmSQ=
11F461856A869924

Может кто-нибудь помочь мне понять, что я делаю не так? Любая помощь будет очень ценится.

Спасибо!

Изменить 1:
Мне удалось исправить код C ++ после jww-х ответьте, и это сработало хорошо. Я скучал по EVP_CIPHER_CTX_set_key_length Однако я не мог заставить код PHP возвращать то же самое, и в конце концов мы решили перейти на AES, и теперь он работает без нареканий. Спасибо!

1

Решение

Для вашего кода OpenSSL, я считаю, вам нужно позвонить EVP_CIPHER_CTX_set_key_length чтобы сказать библиотеке ключ всего 6 байтов.

Позвольте мне бросить Crypto ++ на арену ниже. OpenSSL и Crypto ++ сойдутся при правильном ответе, как только вы добавите недостающий EVP_CIPHER_CTX_set_key_length OpenSSL вызов. Правильный ответ 32CEBA7E046431EB (в шестнадцатеричном виде).

Я не знаю, что происходит с PHP:

x9jDa2WMwvQ=
78396A446132574D7776513D

принимая во внимание x ASCII 0x78, 9 это ASCII 0x39, я предполагаю, что вы закодировали строку Base64 в шестнадцатеричном формате.


$ cat test.cxx
#include "blowfish.h"#include "modes.h"#include "channels.h"#include "filters.h"#include "base64.h"#include "hex.h"using namespace CryptoPP;

#include <iostream>
#include <string>
using namespace std;

int main(int argc, char* argv[])
{
const byte key[] = "123456";   // 6
const byte  iv[] = "initvect"; // 8
CBC_Mode<Blowfish>::Encryption encryptor;
encryptor.SetKeyWithIV(key, 6, iv, 8);

string r1, r2;
ChannelSwitch chsw;

Base64Encoder e1(new StringSink(r1));
HexEncoder e2(new StringSink(r2));
chsw.AddDefaultRoute(e1);
chsw.AddDefaultRoute(e2);

string msg = "input";
StringSource ss(msg, true,
new StreamTransformationFilter(encryptor,
new Redirector(chsw)));

cout << r1 << endl;
cout << r2 << endl;

return 0;
}

Результатом тестовой программы является:

$ ./test.exe
Ms66fgRkMes=
32CEBA7E046431EB

Вот часть OpenSSL вещей. уведомление EVP_EncryptInit_ex называется дважды. Первый, EVP_EncryptInit_ex вызывается для установки блочного шифра EVP_bf_cbc, Длина ключа задается с помощью EVP_CIPHER_CTX_set_key_length, Потом второе EVP_EncryptInit_ex вызывается для установки ключа и iv.

#include <openssl/evp.h>

#include <iostream>
#include <iomanip>
#include <stdexcept>
using namespace std;

typedef unsigned char byte;

int main()
{
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);

int rc;
const byte key[] = "123456";   // 6
const byte  iv[] = "initvect"; // 8

rc = EVP_EncryptInit_ex(&ctx, EVP_bf_cbc(), NULL, 0, 0);
if (rc != 1)
throw runtime_error("EVP_EncryptInit_ex failed");

rc = EVP_CIPHER_CTX_set_key_length(&ctx, 6);
if (rc != 1)
throw runtime_error("EVP_CIPHER_CTX_set_key_length failed");

rc = EVP_EncryptInit_ex(&ctx, NULL, NULL, key, iv);
if (rc != 1)
throw runtime_error("EVP_EncryptInit_ex failed");

const byte msg[] = "input";
byte buf[32];
int len1 = sizeof(buf), len2 = sizeof(buf);

rc = EVP_EncryptUpdate(&ctx, buf, &len1, msg, 5);
if (rc != 1)
throw runtime_error("EVP_EncryptUpdate failed");

rc = EVP_EncryptFinal_ex(&ctx, buf+len1, &len2);
if (rc != 1)
throw runtime_error("EVP_EncryptFinal_ex failed");

for(unsigned int i=0; i<len1+len2; i++)
cout << std::hex << setw(2) << setfill('0') << (int)buf[i];
cout << endl;

EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]