OpenSSL 在 C++ 和 PHP 中的不一致
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] = ' ';
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] = ' ';
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
所以我得到 39D35A2E6EF8F8E36F3BC1FD8B6B32 (C++) 与 39D35A2E6EF8F8E36F3BC1FD8B06B302 (PHP) 相反。最后,十六进制数据将存储在数据库中,并在以后检索。提前感谢所有的帮助,对不起我的糟糕语言。
所以问题出在 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;
}
第二个输出(B6/B06)中还有另一个额外的0。 这些可能是输出中唯一的低字节,并且您有不同的格式设置。
如果您显示C++ StrToHex,则可能是一个简单的格式字符串修复,例如 %x 到 %0x。
相关文章:
- 大于65535的C++数组[size]引发不一致的溢出
- 在 C++(和 C)中进行类型转换时明显不一致
- 填充上编译器生成的复制构造函数之间的不一致
- 犰狳的 print() 方法和 cout 在从 Rcpp 调用时顺序不一致
- CreateDIBSection为同一图像返回不一致的位图位值
- 在 Qml 中从 QSqlTableModel 中删除单行时视图不一致
- 模板参数推导不一致
- 声明中不一致的no是否违反ODR?
- 如何删除分支因子不一致的树,最大为 30,40
- 从 C++ 函数与 Python 函数返回的不一致值用于偏斜正态分布
- 从 C 字符串构造 std::string 与从另一个 std::string 构造 std::string 不一致
- 这种比较是否不一致(或者存在其他问题)?
- 以下可变参数模板行为是否不一致?
- 如何修复我的链表读数不一致的问题?
- 在C++17中,为什么类模板和函数模板的指针类型推导明显不一致
- void 函数中的指针参数返回不一致的值
- 如何查找导致结果不一致的代码
- 跨平台 mySQL 与字符集不一致
- C++:不一致的 std::p ow( 类型 ) 定义
- OpenSSL 在 C++ 和 PHP 中的不一致