2017-02-13 16 views
1

두 경우 모두 OPENSSL 라이브러리를 사용하여 C++ 라이브러리와 PHP 서버 간의 통신을 암호화하고 해독하려고합니다. Blowfish CBC 알고리즘을 사용하고 싶지만 결과가 C++ 코드와 PHP 코드간에 다른 것 같습니다. 는 C++ 코드는 여기에서 촬영되어OPENSSL Blowfish CBC 암호화가 PHP와 다른 점

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"; 
:

x9jDa2WMwvQ= 
78396A446132574D7776513D 

이는 C++ 코드 :

<?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의 출력이있다 :

이것은 PHP 코드

C++ 출력은 다음과 같습니다.

EfRhhWqGmSQ= 
11F461856A869924 

누군가 내가 잘못하고있는 것을 이해할 수 있도록 도와 줄 수 있습니까? 어떤 도움이라도 대단히 감사하겠습니다.

감사합니다!

편집 1 : 나는 jww의 대답 한 후 C++ 코드를 해결하기 위해 관리하고 그것을 잘 작동. EVP_CIPHER_CTX_set_key_length 그러나 나는 PHP 코드를 반환 할 수 없었고 결국에는 AES로 전환하기로 결정했습니다. 이제는 완벽하게 작동합니다. 감사!

+0

당신은 OpenSSL이 위키 [EVP 대칭 암호화 및 암호 해독 (http://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption) 얼핏을 할 수 있습니다.사실, 기밀성과 신뢰성을 모두 제공하므로 인증 된 암호화를 사용해야합니다. OpenSSL wiki에서 [EVP Authenticated Encryption and Decryption] (http://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption)을 참조하십시오. – jww

+0

제안 해 주셔서 감사합니다. 나는 그것을 들여다 볼 것이다. 그러나 지금은 PHP 엔드 포인트를 변경하여 다른 암호화를 사용하는 것은 쉽지 않습니다. – saw66

+0

블로우 피시는 더 이상 보안이 보장되지 않습니다. 발명가도 이제는 AES를 사용합니다. – zaph

답변

0

OpenSSL 코드의 경우, EVP_CIPHER_CTX_set_key_length으로 전화하여 라이브러리에 키가 6 바이트임을 알릴 필요가 있다고 생각합니다.

아래의 경기장에 Crypto ++을 버리자. OpenSSL 및 Crypto ++는 누락 된 EVP_CIPHER_CTX_set_key_length OpenSSL 호출을 추가하면 올바른 대답으로 수렴합니다. 정답은 32CEBA7E046431EB (16 진수)입니다.

내가 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

고마워요! 당신 말이 맞아요. C++에서 set-key-length가 누락되었습니다. 내가 고칠게 PHP 코드를 업데이 트됩니다. – saw66