2016-08-26 8 views
0

Я хотел бы декодировать строку большого файла в C++.base64 decode C++ fail end of line byte

Размер цепи: 1827500 символы и файл: 1370626 байт

Моя проблема заключается в том, что функция декодирования не работает. Декодированный файл отличается от исходного файла.

Ниже приведены два способа, которые я пробовал

Первый:

char *base64_decode(const std::string &input, long *size) 
{ 
    BIO *p_bio_mem = nullptr; 
    BIO *p_bio_b64 = nullptr; 
    char *retrnvalue; 

    p_bio_b64 = BIO_new(BIO_f_base64()); 
    if (!p_bio_b64) { throw std::runtime_error("BIO_new failed"); } 
    BIO_set_flags(p_bio_b64, BIO_FLAGS_BASE64_NO_NL); //Don't require trailing newlines 

    p_bio_mem = BIO_new_mem_buf((void*)input.c_str(), input.length()); 
    if (!p_bio_mem) { throw std::runtime_error("BIO_new failed"); } 
    BIO_push(p_bio_b64, p_bio_mem); 

    // read result from chain 
    // read sequence (reverse to write): buf <<-- p_bio_b64 <<-- p_bio_mem 
    std::vector<char> buf((input.size() * 3/4) + 1); 
    std::string result; 
    for (;;) 
    { 
     auto nread = BIO_read(p_bio_b64, buf.data(), buf.size()); 
     if (nread < 0) { return NULL; //fail} 
     if (nread == 0) { break; } // eof 
     result.append(buf.data(), nread); 
    } 

    BIO_free_all(p_bio_b64); 
    *size = buf.size(); 
    retrnvalue = new char[*size]; 
    memcpy(retrnvalue, buf.data(), *size); 

    return retrnvalue; 
} 

Второе:

кодекс здесь: How do I base64 encode (decode) in C?

Некоторые конец строки различны:

Diff with WinMerge

Но не весь файл:

Left visualiser of WinMerge diff

Можете ли вы сказать мне, почему? и/или сказать мне еще один способ кодирования файла для удобства переноса?

У меня есть это на входе: drive.google.com/file/d/0B1i4Ez8N86wFblJnaFF6YVNVTWs/view

И я хочу это выход: drive.google.com/file/d/0B1i4Ez8N86wFdl9OUE5UMFB3R28/view

(извините, я не могу поставить более двух ссылок)

PS: Когда я декодирую «certutil -decode» в пакетном режиме, он работает без проблем.

SOLVED: проблема решена, проблема была решена. Закрепить с функцией ofstream записи

+0

См. [EVP Encryption | C++ Programs] (http://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption#C.2B.2B_Programs) в вики OpenSSL. Он показывает, как использовать интеллектуальные указатели для управления ресурсами. Также см. [Как получить результат PKCS7_sign в char * или std :: string] (http://stackoverflow.com/a/38079093/608639). он предоставляет кучу интеллектуальных указателей для типов данных OpenSSL. – jww

+0

Чтение 1827500 в память ОК на рабочем столе, но оно подавит устройство Android или iOS. Вероятно, вам придется переключиться на потоковое шифрование и дешифрование (и, возможно, кодирование и декодирование). – jww

+0

Благодарим вас за шифрование EVP. Этот проект не для других устройств, спасибо вам в любом случае – OOM

ответ

0

SOLVED: проблема решена, проблема была решена. Исправление с функцией записи по потоку

1

Ваш код для чтения данных base64-е изд является довольно перепутались:

std::vector<char> buf((input.size() * 3/4) + 1); 
std::string result; 
for (;;) 
{ 
    auto nread = BIO_read(p_bio_b64, buf.data(), buf.size()); 
    if (nread < 0) { return NULL; } //fail 
    if (nread == 0) { break; } // eof 
    result.append(buf.data(), nread); 
} 

BIO_free_all(p_bio_b64); 
*size = buf.size(); 
retrnvalue = new char[*size]; 
memcpy(retrnvalue, buf.data(), *size); 

return retrnvalue; 

Читаешь ваши данные в строку под названием result, но вы ничего с этим не делают. Затем вы копируете содержимое буфера с нуля в буфер вывода. Вы также можете покончить с указателем size и просто вернуть std::string вместо необработанного char*.

Другой возможный вопрос линии

BIO_set_flags(p_bio_b64, BIO_FLAGS_BASE64_NO_NL); //Don't require trailing newlines 

Если вход действительно содержит символ новой строки, то эта строка будет вызывать проблемы.Если вы хотите работать с входным сигналом, который может или не может содержать символы перевода строки, вам нужно, чтобы сделать эту строку условно:

if (input.find('\n') == std::string::npos) { 
    BIO_set_flags(p_bio_b64, BIO_FLAGS_BASE64_NO_NL); //Don't require trailing newlines 
} 

Все вместе, это будет выглядеть примерно так:

std::string base64_decode(const std::string &input) 
{ 
    BIO *p_bio_mem = nullptr; 
    BIO *p_bio_b64 = nullptr; 

    p_bio_b64 = BIO_new(BIO_f_base64()); 
    if (!p_bio_b64) { throw std::runtime_error("BIO_new failed"); } 
    if (input.find('\n') == std::string::npos) { 
     BIO_set_flags(p_bio_b64, BIO_FLAGS_BASE64_NO_NL); //Don't require trailing newlines 
    } 

    p_bio_mem = BIO_new_mem_buf((void*)input.c_str(), input.length()); 
    if (!p_bio_mem) { throw std::runtime_error("BIO_new failed"); } 
    BIO_push(p_bio_b64, p_bio_mem); 

    std::stringstream result; 
    std::vector<char> buf(1024); 
    while (auto nread = BIO_read(p_bio_b64, buf.data(), buf.size())) 
    { 
     if (nread < 0) { throw std::runtime_error("OMGZ"); } //fail 
     result.write(buf.data(), nread); 
    } 

    BIO_free_all(p_bio_b64); 
    return result.str(); 
} 

LIVE DEMO

Возможно, вы захотите добавить некоторые ошибки, чтобы очистить свои BIO экземпляры в случае ошибки (например, в ответе, на который вы ссылались), но это не то, что вызывает неправильный результат.

+0

Да Я в режиме отладки. Извините за ясность кода. Но проблема остается такой же. – OOM

+0

Вы уверены, что ваши входные данные все в одной строке и не заканчиваются символом новой строки? Если это не так, удалите строку 'BIO_set_flags (p_bio_b64, BIO_FLAGS_BASE64_NO_NL);'. –

+0

Благодарим вас за ответ. Я попытался прокомментировать строку, но все концы строк отсутствуют. https://s16.postimg.org/lqnny9qlh/befaft.jpg – OOM