Im Folgenden meine Beispielimplementierungen von Base58 Kodierung und Dekodierung.
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <tommath.h>
static char _b58_alphabet[]="123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
char *base58_encode(mp_int *n)
{
static char encoded[256];
int i, p=sizeof(encoded)-1;
unsigned long base, mod;
base=strlen(_b58_alphabet); /* sizeof is 59, not 58 */
for(encoded[p--]=0; ((i=mp_cmp_d(n, base))==MP_GT)||(i==MP_EQ); ) {
mp_div_d(n, base, n, &mod);
encoded[p--]=_b58_alphabet[mod];
if(p==0) {
return NULL; /* string buffer overflow */
}
}
if((i=mp_get_int(n)) > 0) {
encoded[p]=_b58_alphabet[i];
}
return &encoded[p];
}
ssize_t strpos(char *haystack, char needle)
{
char *p;
for(p=haystack; *p != 0; p++) {
if(*p == needle) {
return (p-haystack);
}
}
return -1; /* not found */
}
int base58_decode(const char *s, mp_int *ret)
{
size_t base=strlen(_b58_alphabet);
ssize_t i, k;
mp_int a, m;
if(mp_init_multi(&a, &m, NULL) != MP_OKAY) {
return -1;
}
mp_set(ret, 0);
mp_set(&m, 1);
for(i=strlen(s)-1; i>=0; i--) {
mp_copy(&m, &a);
if((k=strpos(_b58_alphabet, s[i])) < 0) {
mp_clear_multi(&a, &m, NULL);
return -1; /* illegal char in string */
}
mp_mul_d(&a, k, &a);
mp_add(&a, ret, ret);
mp_mul_d(&m, base, &m);
}
mp_clear_multi(&a, &m, NULL);
return 0;
}
int main(int argc, char **argv)
{
char *s=NULL;
mp_int n, q;
int ret;
char buf[256];
if((ret=mp_init_multi(&n, &q, NULL)) != MP_OKAY) {
printf("bignum alloc failed\n");
return 1;
}
mp_read_radix(&n, "7ffffffffffffffff", 16);
s=base58_encode(&n);
printf("result=%s\n", s);
base58_decode(s, &q);
mp_toradix(&q, buf, 16);
printf("result=%s\n", buf);
mp_clear_multi(&n, &q, NULL);
return 0;
}
To compile, you also need libtommath
/* gcc base58.c -lcrypto */
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "base58.h"
//#include <openssl/bn.h>
static char _b58_alphabet[]="123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
int strpos(char *haystack, char needle);
char *base58_encode(BIGNUM *n)
{
static char encoded[256];
int i, p=sizeof(encoded)-1;
BN_ULONG base, mod;
BIGNUM *bb=NULL;
if ((bb=BN_new()) == NULL) {
return NULL;
}
base=strlen(_b58_alphabet); /* sizeof is 59, not 58 */
BN_set_word(bb, base);
for (encoded[p--]=0; BN_cmp(n, bb) >= 0; ) {
mod=BN_div_word(n, base);
encoded[p--]=_b58_alphabet[mod];
if (p==0) {
return NULL; /* string buffer overflow */
}
}
if ((i=BN_get_word(n)) > 0) {
encoded[p]=_b58_alphabet[i];
}
BN_free(bb);
return &encoded[p];
}
int strpos(char *haystack, char needle)
{
char *p;
for (p=haystack; *p != 0; p++) {
if (*p == needle) {
return (p-haystack);
}
}
return -1; /* not found */
}
/* in case of error, memory is not freed yet */
BIGNUM *base58_decode(const char *s)
{
int i, k, base=strlen(_b58_alphabet);
BIGNUM *a, *m, *ret;
if ((ret=BN_new())==NULL||(a=BN_new())==NULL||(m=BN_new())==NULL) {
return NULL;
}
BN_set_word(ret, 0);
BN_set_word(m, 1);
for (i=strlen(s)-1; i>=0; i--) {
BN_copy(a, m);
if ((k=strpos(_b58_alphabet, s[i])) < 0) {
BN_free(a);
BN_free(m);
BN_free(ret);
return NULL; /* illegal char in string */
}
BN_mul_word(a, k);
BN_add(ret, ret, a);
BN_mul_word(m, base);
}
BN_free(a);
BN_free(m);
return ret;
}
int main(int argc, char **argv)
{
char *s=NULL;
BIGNUM *n=NULL, *q=NULL;
if ((n=BN_new()) == NULL) {
printf("bignum alloc failed\n");
return 1;
}
// BN_dec2bn(&n, "12345678901234567890");
BN_hex2bn(&n, "fabb88b1152463b562317a1ac415043abc136c7d565cb61d21157311a33aeff8");
s=base58_encode(n);
printf("result=%s\n", s);
q=base58_decode(s);
s=BN_bn2hex(q);
printf("result=%s\n", s);
BN_free(n);
return 0;
}