1

I am on a Windows-XP platform, using C++98. Here is my problem:

  1. I receive a number encoded in base64 in a char array. The number is 16 bytes long
  2. After decoding the number to base10, I end up with a number of 12 bytes long
  3. Those 12 bytes (still in a char array) should be converted to a ASCII representation (requirement).

An example:

  • Reception of data : "J+QbMuDxYkxxtSRA" (in a char array : 16 bytes)
  • Decoding from base64: 0x27 0xE4 0x1B 0x32 0xE0 0xF1 0x62 0x4C 0x71 0xB5 0x24 0x40 (hex in a char array: 12 bytes)
  • Conversion from decimal to ASCII : "12345678912345678912345678912" (in a char array: 29 bytes)

I am currently stuck at the last step, I have no idea how to do it. When I searched, the only thing I found is how to convert from int to string (so, for an int containing the value 10, a sprintf("%d", buffer) would do the trick I guess. Since my number is greater than 8 bytes/64 bits (12 bytes) and is not stored in a int/unsigned long long, I am pretty sure I need to do something else to convert my number.

Any help would be greatly appreciated

EDIT for a code example (link to the base64 library : http://libb64.sourceforge.net/

#include <iostream>
#include <cstring>
#include "b64/decode.h"

class Tokenizer{
public:
    Tokenizer();
    void decodeFrame(char *buffer, int bufferSize);
    void retrieveFrame(char *buffer);
private:
    char m_frame[255];
};

using namespace std;
int main(int argc, char *argv[])
{
    Tokenizer token;

    char base64Message[] = "J+QbMuDxYkxxtSRA";  // base64 message of 16 (revelant) bytes
    char asciiMessage[30] = {0};                // final message, a number in ascii representation of 29 bytes

    cout << "begin, message = " << base64Message << endl;

    token.decodeFrame(base64Message, 16);              // decode from base64 and convert to ASCII
    token.retrieveFrame(asciiMessage);          // retrieve the ASCII message

    cout << "final message : " << asciiMessage << endl;                       // the message should be "12345678912345678912345678912"

    return 0;
}
Tokenizer::Tokenizer()
{
}
void Tokenizer::decodeFrame(char *buffer, int bufferSize)
{
    memset(m_frame, 0x00, 255);
    char decodedFrame[255] = {0};  // there is maximum 255 byte in ENCODED (base64). When decoded, the size will automatically be lower
    int decodedSize = 0;
    base64::decoder base64Decoder;  // base64 to base10 decoder, found there: http://libb64.sourceforge.net/

    decodedSize = base64Decoder.decode(buffer, bufferSize, decodedFrame); // int decode(const char* code_in, const int length_in, char* plaintext_out)

    // the frame now must be decoded to produce ASCII, I have no idea how to do it
    for(int i = 0; i < 30; i++){    m_frame[i] = decodedFrame[i]; }
}
void Tokenizer::retrieveFrame(char *buffer)
{
    if(buffer != NULL){
        for(int i = 0; m_frame[i] != 0; i++){
            buffer[i] = m_frame[i];
        }
    }
}
Farouk
  • 23
  • 4
  • 1
    Are you working with C *or* C++? There is no such language as C/C++, they are different things. Please modify your question to properly indicate which language you are using. – Toby Feb 28 '17 at 16:46
  • 1
    Also, you are much more likely to get help if you show the code that you have so far as this shows effort on your part. People will otherwise be very reluctant to just write a program for you from scratch – Toby Feb 28 '17 at 16:47
  • If you can decode the base64 into bytes, why don't you just store the bytes straight into a int/long/long long/whatever fits? – Chris Turner Feb 28 '17 at 16:47
  • Does this help? http://stackoverflow.com/questions/42373267/convert-encoded-stdstring-from-base16-to-base10/42375883#42375883 – Mark Ransom Feb 28 '17 at 16:48
  • @ChrisTurner are there any native types that are at least 12 bytes long? – Mark Ransom Feb 28 '17 at 16:49
  • 2
    Please [edit] your question to show [what you have tried so far](http://whathaveyoutried.com). You should include a [mcve] of the code that you are having problems with, then we can try to help with the specific problem. You should also read [ask]. – Toby Speight Feb 28 '17 at 16:50
  • 1
    Please provide a link to the specification of "C/C++98". There are only the two distinct languages C (specified in ISO/IEC 9899) and C++ (ISO/IEC 14882). As there has never been a C98 version, I suspect you use C++. – too honest for this site Feb 28 '17 at 16:55
  • @MarkRansom Ah...yeah...never mind what I said - for some reason I thought a long long was 16 bytes :/ – Chris Turner Feb 28 '17 at 16:56
  • @MarkRansom: Some platforms support an `_int128` type. Is it relevant how many bytes it needs? – too honest for this site Feb 28 '17 at 16:57
  • @Olaf the question specifies that the number in question has a 12-byte representation, so nothing smaller would be adequate. Since `__int128` is 16 bytes, it would certainly qualify. Then there are two questions remaining: how to convert the string of bytes to a `__int128`, and how to convert the `__int128` to a decimal representation. – Mark Ransom Feb 28 '17 at 17:19
  • @MarkRansom: The number of bytes alone is irrelevant for the range a type can represent, it's the number of used bits (i.e. excluding padding bits). Without `CHAR_BIT` it is unclear how many bits OP wants, but Windows never supported architectures with anything else than 8 bits/byte (i.e. an octet). Taking this into account, a 128 bit integer type would consist of 16 octets, which is more than the requested 12 octets. About the rest: we are not a coding service and that's a minor programming task. – too honest for this site Feb 28 '17 at 17:29
  • @Olaf: it's a minor programming task *if you know how*. It's obvious the asker doesn't know how or the question wouldn't have come up. – Mark Ransom Feb 28 '17 at 17:37
  • @MarkRansom: It is something OP should know if he got this assignment. Otherwise he has the wrong job or did not follow the course well enough. One way or the other, the question is too broad, we are not a coding or tutoring service. – too honest for this site Feb 28 '17 at 17:41

2 Answers2

1

Building on an earlier answer you can easily build an arbitrary length integer from a bunch of bytes.

const char *example = "\x27\xE4\x1B\x32\xE0\xF1\x62\x4C\x71\xB5\x24\x40";
Bignum bn = 0;
for (int i = 0; i < 12; ++i)
{
    bn *= 256;
    bn += example[i] & 0xff;
}
std::cout << bn << std::endl;

See the whole code here: http://coliru.stacked-crooked.com/a/d1d9f39a6d575686

Community
  • 1
  • 1
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • I understand what your code is doing, and while doing tests it perfectly does what I want (thanks for the http://coliru.stacked-crooked.com/, really useful)... But I don't understand the mathematical reasoning behind it. Anyway, thank you, you have been a big help – Farouk Mar 01 '17 at 11:19
  • @Farouk `*= 256` is the same as `<< 8`, so it's shifting the old value by 8 bits to make room for each new byte. The `& 0xff` is to remove any sign extension and make sure the byte is in the 0-255 range. – Mark Ransom Mar 01 '17 at 15:09
0

@Farouk : your error in your reasonment is due to at the convertion base64 string to decimal (base10) directly. Indeed this convertion change the original number, you have jumping a step in your convertion for more details follow below : example : receive base64 : J+QbMuDxYkxxtSRA

**your steps :**
**base64 -> dec**  : 39 18162 3170 76 113 22784
**dec -> hex**     : 153D8AE2CE845159A0

**logical steps:**
**base64 -> hex**  : 27e41b32e0f1624c71b52440
**hex -> deci**    : 12345678912345678912345678912
**deci -> hex**    : 27E41B32E0F1624C71B52440
**hex -> base64**  : J+QbMuDxYkxxtSRA

For the solution c++ to convert base64tohex i thinks you can find a librairy on the web if not i can code for you this convertion later.

Frez
  • 1
  • 2
  • For me you can stay on char * during all the convertion. With this way you haven't the issue of number bigger than 8 bytes. see https://github.com/littlstar/b64.c for keep a char *. – Frez Mar 01 '17 at 08:52