繁体   English   中英

C++ 和 PHP 中的 OpenSSL 不一致

[英]OpenSSL inconsistency in C++ and PHP

我正在尝试编写一段代码来加密/解密将存储在数据库中的数据(例如密码)。 目标是数据可以在 C++、PHP 和 Java 中使用。 问题是我没有在 C++ 和 PHP 中获得相同的加密数据(我没有处理 Java jet)。 C++代码:

void CSSLtestDlg::TryIt()
{
    CString msg, tmp;

    /* A 256 bit key */
    unsigned char *key = (unsigned char *)"01234567890123456789012345678901";
    /* A 128 bit IV */
    unsigned char *iv = (unsigned char *)"01234567890123456";
    /* Message to be encrypted */
    unsigned char *plaintext = (unsigned char *)"Some_plain_text";

    msg = "Original text is: Some_plain_text";

    /* Buffer for ciphertext. Ensure the buffer is long enough for the
    * ciphertext which may be longer than the plaintext, dependant on the
    * algorithm and mode
    */
    unsigned char ciphertext[128];

    /* Buffer for the decrypted text */
    unsigned char decryptedtext[128];

    int decryptedtext_len, ciphertext_len;
    /* Initialise the library */
    ERR_load_crypto_strings();
    OpenSSL_add_all_algorithms();
    OPENSSL_config(NULL);

    /* Encrypt the plaintext */
    ciphertext_len = encryptIt (plaintext, strlen ((char *)plaintext), 
        key, iv, ciphertext);

    ciphertext[ciphertext_len] = '\0';

    tmp.Format("\nEncrypted text (in HEX) is: %s", StrToHex(ciphertext));
    msg += tmp;

    /* Decrypt the ciphertext */
    decryptedtext_len = decryptIt(ciphertext, ciphertext_len, 
        key, iv, decryptedtext);

    /* Add a NULL terminator. We are expecting printable text */
    decryptedtext[decryptedtext_len] = '\0';

    tmp.Format("\nDecrypted text is: %s", decryptedtext);
    msg += tmp;

    AfxMessageBox(msg);

    /* Clean up */
    EVP_cleanup();
    ERR_free_strings();
}

int CSSLtestDlg::encryptIt(unsigned char *plaintext, int plaintext_len, 
 unsigned char *key,  unsigned char *iv, unsigned char *ciphertext)
{
  EVP_CIPHER_CTX *ctx;

  int len;

  int ciphertext_len;

  /* Create and initialise the context */
  if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();

  /* Initialise the encryption operation. IMPORTANT - ensure you use a key
   * and IV size appropriate for your cipher
   * In this example we are using 256 bit AES (i.e. a 256 bit key). The
   * IV size for *most* modes is the same as the block size. For AES this
   * is 128 bits */
  if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
    handleErrors();

  /* Provide the message to be encrypted, and obtain the encrypted output.
   * EVP_EncryptUpdate can be called multiple times if necessary
   */
  if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
    handleErrors();
  ciphertext_len = len;

  /* Finalise the encryption. Further ciphertext bytes may be written at
   * this stage.
   */
  if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors();
  ciphertext_len += len;

  /* Clean up */
  EVP_CIPHER_CTX_free(ctx);

  return ciphertext_len;
}

int CSSLtestDlg::decryptIt(unsigned char *ciphertext, int ciphertext_len, 
unsigned char *key, unsigned char *iv, unsigned char *plaintext)
{
  EVP_CIPHER_CTX *ctx;

  int len;

  int plaintext_len;

  /* Create and initialise the context */
  if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();

  /* Initialise the decryption operation. IMPORTANT - ensure you use a key
   * and IV size appropriate for your cipher
   * In this example we are using 256 bit AES (i.e. a 256 bit key). The
   * IV size for *most* modes is the same as the block size. For AES this
   * is 128 bits */
  if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
    handleErrors();

  /* Provide the message to be decrypted, and obtain the plaintext output.
   * EVP_DecryptUpdate can be called multiple times if necessary
   */
  if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
    handleErrors();
  plaintext_len = len;

  /* Finalise the decryption. Further plaintext bytes may be written at
   * this stage.
   */
  if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) handleErrors();
  plaintext_len += len;

  /* Clean up */
  EVP_CIPHER_CTX_free(ctx);

  return plaintext_len;
}

结果:

Original text is: Some_plain_text
Encrypted text (in HEX) is: 39D35A2E6EF8F8E36F3BC1FD8B6B32
Decrypted text is: Some_plain_text

PHP代码:

$key = "01234567890123456789012345678901";
$iv = "01234567890123456";
$msg = "Some_plain_text";

if(function_exists('openssl_encrypt'))
{
    echo("Original text is:" . $msg . "<br>");
    $encrypted_msg = openssl_encrypt($msg, "aes-256-cbc", $key, OPENSSL_RAW_DATA, $iv);
    if ($encrypted_msg == FALSE)
        $log->logDebug("openssl_encrypt error!");
    else
    {
        echo("Encrypted text (in HEX) is:" . strToHex($encrypted_msg) . "<br>");
        $decrypted_msg = openssl_decrypt($encrypted_msg, "aes-256-cbc", $key, OPENSSL_RAW_DATA , $iv);
        echo("Decrypted text is:" . $decrypted_msg . "<br>");
    }
}
else echo("openssl_encrypt doesn't exists!<br>");

function strToHex($string)
{
    $hex = '';
    for ($i=0; $i<strlen($string); $i++)
    {
        $ord = ord($string[$i]);
        $hexCode = dechex($ord);
        $hex .= substr('0'.$hexCode, -2);
    }
    return strToUpper($hex);
}

结果:

Original text is:Some_plain_text
Encrypted text (in HEX) is:39D35A2E6EF8F8E36F3BC1FD8B06B302
Decrypted text is:Some_plain_text

所以我得到 39D35A2E6EF8F8E36F3BC1FD8B6 B32 (C++) 与 39D35A2E6EF8F8E36F3BC1FD8B06 B302 (PHP) 相对。 最后,HEX 数据将存储在 DB 中并稍后检索。 预先感谢所有的帮助,并为我的语言不好而道歉。

所以问题出在 StrToHex() 函数中的 C++ 代码中(我忘记在原始问题中发布)所以这里是:

CString StrToHex(unsigned char* str)
{       
    CString tmp;
    CString csHexString;    
    int nCount = strlen((char *)str);            
    for( int nIdx =0; nIdx < nCount; nIdx++ )      
    {          
        int n = str[nIdx];
        //tmp.Format( _T("%X"), n ); --> this is wrong
        tmp.Format( _T("%02X"), n ); // --> this is OK
        csHexString += tmp;      
    }   
    return csHexString;
}

第二个输出中还有另一个额外的 0 (B6/B06)。 这些可能是输出中唯一的低字节,并且您有不同的格式设置。

如果你展示你的 C++ StrToHex,它可能是一个简单的格式字符串修复,比如 %x 到 %0x。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM