【问题标题】:convert md5 string to base 62 string in c++在c ++中将md5字​​符串转换为base 62字符串
【发布时间】:2010-10-24 05:10:57
【问题描述】:

我正在尝试将 md5 字符串(base 16)转换为 c++ 中的 base 62 字符串。到目前为止,我发现的每个转换为 base 62 的解决方案只有在您可以将您的数字表示为 64 位整数或更小的整数时才有效。一个 md5 字符串是 128 位的,我自己一个都没有。

我应该只包含一个 bigint 库并完成它吗?

【问题讨论】:

  • 我可能是错的,但由于您没有使用 2 基数的幂,您将需要进行除法。这意味着您需要能够将 md5 表示为“数字”,而不仅仅是一串十六进制字符。 bitint 可能是唯一实用的选择。
  • Convert MD5 to base62 for URL 的可能重复项
  • 只需添加两个字符即可。 Base64 无处不在。
  • @Evan Teran - 当我问我的问题时,我意识到了这个问题。我同意我的问题非常相似。我再次问它的唯一原因是因为没有人给出令人满意的答案。另外,我实际上在钓鱼;我希望能够以 N 为基数表示任何大小的字节数组。如果我只想缩短一个 url,那么我会接受下面的 sellibitze 解决方案。我想我们俩可能都是对的;唯一的方法是使用 bigint 类,或者至少实现 bigint 所需的部分 - DIV 和 MOD。

标签: c++ md5 base62


【解决方案1】:

让我们看看。 128/log2(62)=21.497。这意味着您需要 22 个“数字”来表示 base-62。

如果您只对不超过 22 个字符且不使用超过 62 个不同字符的字符串表示感兴趣,则不需要真正的 base-62 表示。您可以将 128 位分解为更小的部分并分别编码。这样您就不需要任何 128 位算术。您可以将 128 位拆分为 2x64 位,并使用长度为 11 的字符串对每个 64 位块进行编码。这样做甚至可以仅使用 57 个不同的字符。因此,您可以消除 62 个字符中的 5 个以避免任何“视觉歧义”。例如,删除 l,1,B,8。剩下 58 个不同的字符和 11*log2(58)=64.438,这足以编码 64 位。

获得两个 64 位块并不难:

#include <climits>

#if CHAR_BIT != 8
#error "platform not supported, CHAR_BIT==8 expected"
#endif

// 'long long' is not yet part of C++
// But it's usually a supported extension
typedef unsigned long long uint64;

uint64 bits2uint64_bigendian(unsigned char const buff[]) {
   return (static_cast<uint64>(buff[0]) << 56)
        | (static_cast<uint64>(buff[1]) << 48)
        | (static_cast<uint64>(buff[2]) << 40)
        | (static_cast<uint64>(buff[3]) << 32)
        | (static_cast<uint64>(buff[4]) << 24)
        | (static_cast<uint64>(buff[5]) << 16)
        | (static_cast<uint64>(buff[6]) <<  8)
        |  static_cast<uint64>(buff[7]);
}

int main() {
   unsigned char md5sum[16] = {...};
   uint64 hi = bits2uint64_bigendian(md5sum);
   uint64 lo = bits2uint64_bigendian(md5sum+8);
}

【讨论】:

  • 感谢您让我跳出框框思考。你是对的,如果我想要的只是哈希的缩短字符串表示,这将是实际的事情。我可能会在短期内使用您的解决方案,但我真的在寻找一种更通用的解决方案来表示基数 N 中的任何字节数组。
【解决方案2】:

为简单起见,您可以使用我的 uint128_t c++ 类 (http://www.codef00.com/code/uint128.h)。有了它,基本转换器看起来就很简单了:

#include "uint128.h"
#include <iostream>
#include <algorithm>

int main() {
    char a[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    uint128_t x = U128_C(0x130eb6003540debd012d96ce69453aed);

    std::string r;
    r.reserve(22); // shouldn't result in more than 22 chars 
                   // 6-bits per 62-bit value means (128 / 6 == 21.3)

    while(x != 0) {
        r += a[(x % 62).to_integer()];
        x /= 62;
    }

    // when converting bases by division, the digits are reversed...fix that :-)
    std::reverse(r.begin(), r.end());
    std::cout << r << std::endl;
}

打印出来:

J7JWEJ0YbMGqaJFCGkUxZ

【讨论】:

  • 我喜欢你的 uint128 课程。它很适合我的短期目标。我唯一遗憾的是对boost的依赖。当 boost 成为标准库的一部分时会不会很好?
  • 抱歉,您不能使用 boost。 boost 主要是为了方便,我用它来“自动”创建各种运算符。无论哪种方式,我都希望你能以它为例子。
【解决方案3】:

GMP 为任意精度整数提供方便的 c++ 绑定

【讨论】:

    猜你喜欢
    • 2018-05-03
    • 2015-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多