gpt4 book ai didi

php - c++中的加密和php中的解密有什么问题

转载 作者:太空宇宙 更新时间:2023-11-04 12:35:55 25 4
gpt4 key购买 nike

在这里,我有一个对字符串进行编码的 C++ 程序,我必须在 PHP 中进行解密。我已验证两个程序中的 key 和 iv 相同,但在 openssl_decrypt() 命令中仍然为 false。

    int main(int argc, char** args)
{
unsigned char *salt = (unsigned char*)"12345678";
unsigned char *data = (unsigned char*)"123456789123450";
unsigned int count = 5;
int dlen = strlen((char*)data);
unsigned int ksize = 16;
unsigned int vsize = 12;
unsigned char *key = new unsigned char[ksize];
unsigned char *iv = new unsigned char[vsize];

int ret = EVP_BytesToKey( EVP_aes_128_gcm() , EVP_sha1(), salt, data, dlen, count, key, iv);

const EVP_CIPHER* m_cipher = EVP_aes_128_gcm();
EVP_CIPHER_CTX* m_encode;
EVP_CIPHER_CTX* m_decode;
if (!(m_encode = EVP_CIPHER_CTX_new()))
cout << "ERROR :: In encode Initiallization"<< endl;

EVP_EncryptInit_ex(m_encode, m_cipher, NULL, key, iv);

if (!(m_decode = EVP_CIPHER_CTX_new()))
cout << "ERROR :: In decode Initiallization"<< endl;
EVP_DecryptInit_ex(m_decode, m_cipher, NULL, key, iv);
unsigned char* plain = (unsigned char*)"My Name IS DON !!!";
int len = strlen((char*)plain);
unsigned char* encData = new unsigned char[len];

int c_len = len;
int f_len = 0;
EVP_EncryptInit_ex(m_encode, NULL, NULL, NULL, NULL);
EVP_EncryptUpdate(m_encode, encData, &c_len, plain, len);
EVP_EncryptFinal_ex(m_encode, encData + c_len, &f_len);

len = c_len + f_len;

cout << string( encData, encData + len)<< endl;
}

下面是php解密代码。 “./abc_enc.txt”包含c++代码的加密字符串。正如我上面提到的,我为两个程序获得相同的 key 和 iv,但 openssl_decrypt 函数返回 false。有人能弄清楚是什么错误吗?

    <?
function EVP_BytesToKey($salt, $password) {
$ivlen = 12;
$keylen = 16;
$iterations = 5;
$hash = "";
$hdata = "";
while(strlen($hash)<$ivlen+$keylen)
{
$hdata .= $password.$salt;
$md_buf = openssl_digest($hdata, 'sha1');
for ($i = 1; $i < $iterations; $i++) {
$md_buf = openssl_digest ( hex2bin($md_buf),'sha1');
}
$hdata = hex2bin($md_buf);
$hash.= $hdata;
}
return $hash;
}
function decrypt($ivHashCiphertext, $password) {
$method = "aes-128-gcm";
$salt = "12345678";
$iterations = 5;
$ivlen = openssl_cipher_iv_length($method);
$ciphertext = $ivHashCiphertext;
$genKeyData = EVP_BytesToKey($salt, $password);
$keylen = 16;
$key = substr($genKeyData,0,$keylen);
$iv = substr($genKeyData,$keylen,$ivlen);
//var_dump($key);
//var_dump($iv);
$ret = openssl_decrypt($ciphertext, $method, $key, OPENSSL_RAW_DATA, $iv);
var_dump($ret);
return $ret;
}
$file = './abc_enc.txt';
$fileData = (file_get_contents($file));
$encrypted = $fileData;
$decrypted = decrypt($encrypted, '123456789123450');
?>

最佳答案

GCM-mode提供 secret 性和真实性。为了验证真实性,GCM 模式使用身份验证标签并定义了包括在内的长度。标签的 12 和 16 字节。认证强度取决于标签的长度,即标签越长,真实性证明越安全。

但是,在当前的 C++ 代码中,身份验证标记尚未确定!这意味着未使用 GCM 模式的主要功能之一,即身份验证。

虽然在 C++ 中使用 EVP 的解密独立于身份验证(这意味着即使身份验证标签不同也会执行解密),而在 PHP 中使用 openssl_decrypt 的解密只有在身份验证成功,即在 PHP 中,身份验证标记是解密所必需的。因此,必须在 C++ 代码中确定身份验证标记。为此,必须在 EVP_EncryptFinal_ex 调用之后添加以下代码:

unsigned int tsize = 16;
unsigned char *tag = new unsigned char[tsize];
EVP_CIPHER_CTX_ctrl(m_encode, EVP_CTRL_GCM_GET_TAG, tsize, tag);

这里使用了 16 字节的标签大小。此外,必须在 PHP 代码中使用身份验证标记进行解密。这是通过将身份验证标记作为 openssl_decrypt 的第 6 个参数传递来完成的。 -方法:

$ret = openssl_decrypt($ciphertext, $method, $key, OPENSSL_RAW_DATA, $iv, $tag);

只有当用于解密的标签与用于加密的标签匹配时才能进行解密。

对于已发布示例中的数据,C++ 代码生成以下身份验证标记(作为十六进制字符串):

f7c18e8b99587f3063383d68230c0e35

最后,关于使用 OpenSSL 的 AES-GCM 的更详细解释可以在这里找到 encryptiondecryption (包括对身份验证标签的考虑)。

关于php - c++中的加密和php中的解密有什么问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56376819/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com