【问题标题】:How do I base58 encode a string?我如何对字符串进行 base58 编码?
【发布时间】:2012-02-16 17:57:34
【问题描述】:
char (* text)[1][45+1];
text = calloc(5000,(130+1));
strcpy(0[*text],"sometext)");

现在我想将“sometext”编码为 base58,但是,我不知道如何,而且奇怪的是,在 C 中没有一个 BASE58 的示例。

我感兴趣的 base58 编码使用这些符号:

123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ

它已经过优化以减少误读的风险,例如,0 和 'O' 都消失了。

附言 不要介意变量的奇怪分配和声明,我正在试验。

【问题讨论】:

  • Here's a PHP sample,您可以轻松移植。
  • 我不想忘恩负义之类的,但那些都是 PHP 的。
  • 表现出一些主动性。 @Cicada 建议你可以 port 他们。还是您希望为您完成这项工作?
  • 顺便说一句,为什么这样的语法?使代码尽可能不透明?
  • @LinusKleen 请告诉我们您如何在 C 中像在 PHP 中那样对无限位整数进行除法。您很快就会发现这并不简单(尽管并非不可能,并且有实现,但肯定不是 1-liners)。

标签: c base


【解决方案1】:

我使用 Crypto++ 库的简单代码:


  string base58_encode(Integer num, string vers)
  {
    string alphabet[58] = {"1","2","3","4","5","6","7","8","9","A","B","C","D","E","F",
    "G","H","J","K","L","M","N","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c",
    "d","e","f","g","h","i","j","k","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
    int base_count = 58; string encoded; Integer div; Integer mod;
    while (num >= base_count)
    {
        div = num / base_count;   mod = (num - (base_count * div));
        encoded = alphabet[ mod.ConvertToLong() ] + encoded;   num = div;
    }
    encoded = vers + alphabet[ num.ConvertToLong() ] + encoded;
    return encoded;
  }
它仅适用于加密货币钱包。可以为其他任务更改字符串。

【讨论】:

  • 出于好奇,为什么不用字符串文字来定义alphabet呢?
  • 那是 C++,不是 C
【解决方案2】:

这是一个看似纯c的实现。

https://github.com/trezor/trezor-crypto/blob/master/base58.c

【讨论】:

  • 这看起来很有趣(“针对嵌入式设备进行了高度优化”),但它没有任何关于如何使用它的文档或示例,并且在代码上倾注 15-20 分钟也没有让它变得明显。 (相对新手,我了解基础但仍然很容易被抛出。:P)
  • 我的想法完全正确;其实你可能比我先进。我只是在报告它声称的内容,这是我自己未经证实的说法。使用风险自负(并且请返回发布您学到的任何对我们处境中的其他人有所帮助的内容)。
【解决方案3】:

这是我为 Amithings 创建的大数的 PHP 实现,超出整数 (Integer -> http://php.net/manual/en/language.types.integer.php)。

例如,试试下面的例子(不要忘记将你的 ID 以字符串格式传递给函数。使用 PHP 函数 strval()):

$number = '123456789009876543211234567890';
$result = base58_encode($number);
echo('Encoded: ' . $result . '<br>');
echo('Decoded: ' . base58_decode($result) . '<br>');

重要提示:您可以考虑通过包含某种密钥/密码/加密来更改此例程,以确保其他人无法解码您的数据库 ID。

function base58_encode($input)
{
    $alphabet = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ';
    $base_count = strval(strlen($alphabet));
    $encoded = '';
    while (floatval($input) >= floatval($base_count))
    {
        $div = bcdiv($input, $base_count);
        $mod = bcmod($input, $base_count);
        $encoded = substr($alphabet, intval($mod), 1) . $encoded;
        $input = $div;
    }
    if (floatval($input) > 0)
    {
        $encoded = substr($alphabet, intval($input), 1) . $encoded;
    }
    return($encoded);
}

function base58_decode($input)
{
    $alphabet = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ';
    $base_count = strval(strlen($alphabet));
    $decoded = strval(0);
    $multi = strval(1);
    while (strlen($input) > 0)
    {
        $digit = substr($input, strlen($input) - 1);
        $decoded = bcadd($decoded, bcmul($multi, strval(strpos($alphabet, $digit))));
        $multi = bcmul($multi, $base_count);
        $input = substr($input, 0, strlen($input) - 1);
    }
    return($decoded);
}

【讨论】:

    【解决方案4】:

    Satoshi 有参考实现 (https://github.com/bitcoin/bitcoin/blob/master/src/base58.h)

    但是,他使用了一些实用程序 bignum 类来执行此操作,并且它是在 C++ 中的。如果您可以访问 bignum 库,您只需继续除以 58,直到数字被分解。如果你没有 bignum 库,AFAIK 你就不走运了。

    【讨论】:

      【解决方案5】:

      你不应该编码字符串,你应该编码整数

      如果以字符串开头,则必须先决定如何将其解释为整数(可能是 base128 之类的),然后在 base58 中重新编码。

      【讨论】:

        猜你喜欢
        • 2011-07-02
        • 1970-01-01
        • 1970-01-01
        • 2021-05-19
        • 2014-03-27
        • 2011-06-24
        • 2011-10-06
        • 2012-12-23
        • 1970-01-01
        相关资源
        最近更新 更多