php - 为什么在 C++ 中从十六进制字符串转换为 base36 字符串的结果与在 PHP 中相同操作的结果不同?

标签 php c++ hex base36

C++代码如下:

#include <stdio.h>
#include <openssl/sha.h>
#include <string>
#include <gmp.h>

std::string base36enc(std::string data){
    mpz_t nr;
    mpz_init(nr);
    mpz_set_str(nr, data.c_str(), 16);
    return std::string(mpz_get_str(NULL, 36, nr));
}

//sha512 function here...

int main(){
    std::string data = "deadbeef1234d0";
    printf("Raw data to base36:\t%s\n",base36enc(data).c_str());
    printf("SHA512 data to b36:\t%s\n",base36enc(sha512(data)).c_str());
    printf("SHA512 data only  :\t%s\n",sha512(data).c_str());

    return 0;
}

输出是:

Raw data to base36:     h55o0dxfmj4
SHA512 data to b36:     clldzg9hyfl5ihp0taww8rny0jxvz67rsk1w4og26zqyt4hdrya68yme09iwtew0tdq6aro9rk3jy2m3r2zpegumccc8ssrbnfr
SHA512 data only  :     4f3aff747e9ce090e5dfc5f23ce2a37233a21cfa2db7db70c984bc9ff8b263c9e02a6a485455c8042d10112f659a965e0bbf9645ee0c0e0c0824970dd879f667

这是 PHP 代码:

<?php
$data = "deadbeef1234d0";
echo "Raw data to base36: <b>".base_convert($data, 16, 36)."</b><br>";
echo "SHA512 data to b36: <b>".base_convert(hash(sha512,$data), 16, 36)."</b><br>";
echo "SHA512 data only  : <b>".hash(sha512,$data)."</b>";

PHP 的输出是:

Raw data to base36: h55o0dxfmj4
SHA512 data to b36: g8804wccs0kc8w8ckkogoc8ssgcs8ccc0sgssgs4g0gok8k8kkgss0og44swkwsc
SHA512 data only  : 4f3aff747e9ce090e5dfc5f23ce2a37233a21cfa2db7db70c984bc9ff8b263c9e02a6a485455c8042d10112f659a965e0bbf9645ee0c0e0c0824970dd879f667

转换为base36的加密字符串在PHP和C++中有所不同。但不是加密会导致问题(散列结果始终匹配)。如果将数据中的最后一个字符更改为 1 或任何大于 0 的十六进制数字,原始数据输出将不同,我不明白为什么!

例如,如果数据是“deadbeef1234df”,raw-data-to-base36 的 C++ 输出将是“h55o0dxfmjj”,而 PHP 输出将是“h55o0dxfmjk”。

有人能帮我找到这个“魔法”的原因吗?

最佳答案

在 PHP 中,base_convert 函数在任意基数之间转换“数字”,并且由于与使用的内部“double”或“float”类型相关的属性,可能会失去大数字的精度。 Read more .

试试这个函数而不是 base_convert:

代码

function bignumber_base_convert($str, $frombase = 10, $tobase = 36)
{
    $str = trim($str);
    if (intval($frombase) != 10) {
        $len = strlen($str);
        $q = 0;
        for ($i = 0; $i < $len; $i++) {
            $r = base_convert($str[$i], $frombase, 10);
            $q = bcadd(bcmul($q, $frombase), $r);
        }
    } else {
        $q = $str;
    }

    if (intval($tobase) != 10) {
        $s = '';
        while (bccomp($q, '0', 0) > 0) {
            $r = intval(bcmod($q, $tobase));
            $s = base_convert($r, 10, $tobase) . $s;
            $q = bcdiv($q, $tobase, 0);
        }
    } else {
        $s = $q;
    }

    return $s;
}

用法

echo bignumber_base_convert(hash('sha512',$data), 16, 36) . "\n";

结果

clldzg9hyfl5ihp0taww8rny0jxvz67rsk1w4og26zqyt4hdrya68yme09iwtew0tdq6aro9rk3jy2m3r2zpegumccc8ssrbnfr

关于php - 为什么在 C++ 中从十六进制字符串转换为 base36 字符串的结果与在 PHP 中相同操作的结果不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49602428/

相关文章:

PHP如何获取基本域/url?

php - Laravel Spark - 登录时重定向

php - MySql 在 PHP 中自动更新上下文敏感关系的重复条目

c++ - 使元组包含unique_ptr时出错

c++ - 读取进程的进程内存不会返回所有内容

java - 如何从 GPS 设备 (TK06A) 读取数据

java 将十六进制 NCR 文本转换为 unicode 字符

php - 通过 PHP 将 CSV 导入 MYSQL

c++ - 如何在 C++ 中使用域名获取域 ip 地址?

node.js - 如何将十六进制字符串转换为base64以便在NodeJS中保存图像