конвертировать строку md5 в строку 62 base в c ++ - PullRequest
0 голосов
/ 24 октября 2010

Я пытаюсь преобразовать строку md5 (база 16) в строку базы 62 в c ++.каждое решение, которое я нашел для преобразования в базу 62, работает, только если вы можете представить свое число как 64-битное целое число или меньше.строка md5 128 бит, и я никуда не пойду с этим сам.

мне просто включить библиотеку bigint и покончить с этим?

Ответы [ 3 ]

4 голосов
/ 24 октября 2010

Посмотрим. 128 / log2 (62) = 21,497. Это означает, что вам нужно 22 "цифры" для представления base-62.

Если вас просто интересует строковое представление, которое не длиннее 22 символов и не использует более 62 различных символов, вам не нужно реальное представление base-62. Вы можете разбить 128 бит на более мелкие части и кодировать части по отдельности. Таким образом, вам не понадобится 128-битная арифметика. Вы можете разделить 128 бит на 2x64 бит и закодировать каждый 64-битный блок строкой длиной 11. Это возможно даже с 57 различными символами. Таким образом, вы можете исключить 5 из 62 символов, чтобы избежать «визуальной неоднозначности». Например, удалить 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);
}
2 голосов
/ 24 октября 2010

Для простоты вы можете использовать мой класс 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
0 голосов
/ 24 октября 2010

GMP обеспечивает удобную привязку c ++ для целых чисел произвольной точности

...