2017-02-13 35 views
1

両方ともOPENSSLライブラリを使用してC++ライブラリとPHPサーバ間の通信を暗号化および復号化しようとしています。私はBlowfish CBCアルゴリズムを使用したいと思いますが、C++コードとPHPコードの結果が異なるようです。 C++コードは、ここから取り出される:OPENSSL Blowfish CBC暗号化は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出力これで:

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コードであります

C++出力は次のとおりです。

EfRhhWqGmSQ= 
11F461856A869924 

誰かが私が間違っていることを理解できるように助けてくれますか?どんな助力も非常に高く評価されます。

ありがとうございます!

編集1: 私はJWWの答えた後にC++コードを修正するために管理し、それがうまく働きました。 EVP_CIPHER_CTX_set_key_lengthしかし、私はPHPコードを返すことはできませんでしたが、最終的にはAESに移行することにしましたが、今は完璧に動作します。ありがとう!

+0

あなたは、OpenSSLのwiki上の[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 ++は、OpenSSLコールが見つからない場合に、EVP_CIPHER_CTX_set_key_lengthを追加すると正しい答えに集中します。正解は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が2回呼び出されます。まず、ブロック暗号EVP_bf_cbcを設定するためにEVP_EncryptInit_exが呼び出されます。キーの長さは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でセットキーの長さが不足していた+ +。 PHPコードを修正したら更新します。 – saw66

関連する問題