3

I'm using ed25519-donna to digitally sign.

The keys are unsigned char[32], and the signatures are unsigned char[64].

I've found this base64 encoding, but it only decodes into string.

I've found and tried many techniques but am still unsure of how to convert.

How can a base64 decoded string be converted to an unsigned char[32]?

Community
  • 1
  • 1
  • it doesn't need to be converted. its base already is `unsigned char*`, and by design usable as `unsigned char const*`. You have no issue just passing `var` as the `unsigned char const*` parameter, where `var` is declared as `unsigned char var[32];` and properly loaded with your binary key/signature. – WhozCraig Feb 18 '14 at 20:03
  • Ah. That makes considerably more sense. There are a plethora of base64 encode/decode implementations out there already. Usually your crypto API has one (Microsoft CryptoAPI and OpenSSL certainly do). If you're looking for a reasonable implementation [this may work for you](http://base64.sourceforge.net/b64.c). It isn't terribly hard to simply feed it data from a vector or flat array rather than a file, and its pretty solid. – WhozCraig Feb 18 '14 at 20:47
  • If they are `std::string` you should simply be able to use any base64 decode algorithm passing the string `c_str()` and `length()` respectively. Ultimately its all string-to-bytes or bytes-to-string in the end. – WhozCraig Feb 18 '14 at 21:01
  • @WhozCraig I apologize, but I still cannot figure this out. I tried `strncpy` and many others. I just can't get it. Would you mind posting a quick example of how to convert a `string` to a `unsigned char[32]` or `unsigned char[64]? Thank you so very very much in advance!` –  Feb 18 '14 at 21:19

3 Answers3

5

Gracchus:

Here it is. Enjoy!

#include <iostream>
#include <string>

struct BASE64_DEC_TABLE {
    signed char n[256];

    BASE64_DEC_TABLE() {
        for(int i=0; i<256; ++i)    n[i] = -1;
        for(unsigned char i='0'; i<='9'; ++i) n[i] = 52+i-'0';
        for(unsigned char i='A'; i<='Z'; ++i) n[i] = i-'A';
        for(unsigned char i='a'; i<='z'; ++i) n[i] = 26+i-'a';
        n['+'] = 62;
        n['/'] = 63;
    }
    int operator [] (unsigned char i) const { return n[i]; }
};

size_t Base64Decode(const std::string& source, void* pdest, size_t dest_size) {
    static const BASE64_DEC_TABLE b64table;
    if(!dest_size) return 0;
    const size_t len = source.length();
    int bc=0, a=0;
    char* const pstart = static_cast<char*>(pdest);
    char* pd = pstart;
    char* const pend = pd + dest_size;
    for(size_t i=0; i<len; ++i) {
        const int n = b64table[source[i]];
        if(n == -1) continue;
        a |= (n & 63) << (18 - bc);
        if((bc += 6) > 18) {
            *pd = a >> 16; if(++pd >= pend) return pd - pstart;
            *pd = a >> 8;  if(++pd >= pend) return pd - pstart;
            *pd = a;       if(++pd >= pend) return pd - pstart;
            bc = a = 0;
    }    }
    if(bc >= 8) {
        *pd = a >> 16; if(++pd >= pend) return pd - pstart;
        if(bc >= 16) *(pd++) = a >> 8;
    }
    return pd - pstart;
}

int main() {
    std::string base64_string = "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=";
    unsigned char decoded_data[32] = {0};

    Base64Decode(base64_string, decoded_data, sizeof(decoded_data));

    for(auto b : decoded_data) {
        std::cout << static_cast<unsigned>(b) << ' ';
    }
    std::cout << std::endl;
    return 0;
}
Christopher Oicles
  • 3,017
  • 16
  • 11
1

A more efficient solution for base64 decoding is using Boost C++ library. Base64 decoding function using Boost C++ library can be found at : attempt to decode a value not in base64 char set

Community
  • 1
  • 1
ap6491
  • 805
  • 1
  • 10
  • 26
0

This post here talks about decoding a base64 string to an unsigned char (uint8_t) array. There's a lot there, and it also seems someone took the code there and posted it here (or vice-verca.)

After looking at all these threads and options (as mentioned above there's a lot of tools out there for this), I used the open source one from Apple's open source libraries. There are many issues with the various code snippets posted in the other SO post that dissuaded me so I decided to stick with the one from Apple since it looked quite clean and has good provenance. I tested it out with a some base64 strings I converted with this online tool and it was all correct.

You need to replace #include "lib.h" with:

#include <stddef.h>
#include <string.h>
#include <stdlib.h>

And then make a quick base64.h to include (the one I found on Apple's open source didn't seem to match)

#ifndef _BASE64_H_
#define _BASE64_H_

#ifdef __cplusplus
extern "C" {
#endif

size_t base64_decode(char *source, unsigned char *target, size_t targetlen);
int base64_encode(unsigned char *source, size_t sourcelen, char *target, size_t targetlen);

#ifdef __cplusplus
}
#endif

#endif //_BASE64_H_
Papyrus
  • 232
  • 3
  • 10