added ipfs support with proper base58

This commit is contained in:
xethyrion 2016-11-10 00:53:11 +02:00 committed by GitHub
parent 7574846553
commit d7a90c513d
3 changed files with 314 additions and 166 deletions

203
base58.c
View file

@ -5,20 +5,12 @@
* under the terms of the standard MIT license. See COPYING for more details. * under the terms of the standard MIT license. See COPYING for more details.
*/ */
#ifndef WIN32
#include <arpa/inet.h>
#else
#include <winsock2.h>
#endif
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h> #include <string.h>
#include <math.h>
#include <stdint.h>
#include <sys/types.h>
#include "base58.h" static const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
bool (*b58_sha256_impl)(void *, const void *, size_t) = NULL;
static const int8_t b58digits_map[] = { static const int8_t b58digits_map[] = {
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
@ -31,11 +23,19 @@ static const int8_t b58digits_map[] = {
47,48,49,50,51,52,53,54, 55,56,57,-1,-1,-1,-1,-1, 47,48,49,50,51,52,53,54, 55,56,57,-1,-1,-1,-1,-1,
}; };
bool b58tobin(void *bin, size_t *binszp, const char *b58, size_t b58sz) /**
* convert a base58 encoded string into a binary array
* @param b58 the base58 encoded string
* @param base58_size the size of the encoded string
* @param bin the results buffer
* @param binszp the size of the results buffer
* @returns true(1) on success
*/
int libp2p_crypto_encoding_base58_decode(const char* b58, size_t base58_size, unsigned char** bin, size_t* binszp)
{ {
size_t binsz = *binszp; size_t binsz = *binszp;
const unsigned char *b58u = (void*)b58; const unsigned char* b58u = (const void*)b58;
unsigned char *binu = bin; unsigned char* binu = *bin;
size_t outisz = (binsz + 3) / 4; size_t outisz = (binsz + 3) / 4;
uint32_t outi[outisz]; uint32_t outi[outisz];
uint64_t t; uint64_t t;
@ -44,157 +44,158 @@ bool b58tobin(void *bin, size_t *binszp, const char *b58, size_t b58sz)
uint8_t bytesleft = binsz % 4; uint8_t bytesleft = binsz % 4;
uint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0; uint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0;
unsigned zerocount = 0; unsigned zerocount = 0;
size_t b58sz;
if (!b58sz) b58sz = strlen(b58);
b58sz = strlen(b58);
memset(outi, 0, outisz * sizeof(*outi)); memset(outi, 0, outisz * sizeof(*outi));
// Leading zeros, just count // Leading zeros, just count
for (i = 0; i < b58sz && b58u[i] == '1'; ++i) for (i = 0; i < b58sz && !b58digits_map[b58u[i]]; ++i) {
++zerocount; ++zerocount;
}
for ( ; i < b58sz; ++i) for (; i < b58sz; ++i) {
{ if (b58u[i] & 0x80) {
if (b58u[i] & 0x80)
// High-bit set on invalid digit // High-bit set on invalid digit
return false; return 0;
if (b58digits_map[b58u[i]] == -1) }
if (b58digits_map[b58u[i]] == -1) {
// Invalid base58 digit // Invalid base58 digit
return false; return 0;
}
c = (unsigned)b58digits_map[b58u[i]]; c = (unsigned)b58digits_map[b58u[i]];
for (j = outisz; j--; ) for (j = outisz; j--;) {
{
t = ((uint64_t)outi[j]) * 58 + c; t = ((uint64_t)outi[j]) * 58 + c;
c = (t & 0x3f00000000) >> 32; c = (t & 0x3f00000000) >> 32;
outi[j] = t & 0xffffffff; outi[j] = t & 0xffffffff;
} }
if (c) if (c) {
// Output number too big (carry to the next int32) // Output number too big (carry to the next int32)
return false; memset(outi, 0, outisz * sizeof(*outi));
if (outi[0] & zeromask) return 0;
}
if (outi[0] & zeromask) {
// Output number too big (last int32 filled too far) // Output number too big (last int32 filled too far)
return false; memset(outi, 0, outisz * sizeof(*outi));
return 0;
}
} }
j = 0; j = 0;
switch (bytesleft) { switch (bytesleft) {
case 3: case 3:
*(binu++) = (outi[0] & 0xff0000) >> 16; *(binu++) = (outi[0] & 0xff0000) >> 16;
case 2: case 2:
*(binu++) = (outi[0] & 0xff00) >> 8; *(binu++) = (outi[0] & 0xff00) >> 8;
case 1: case 1:
*(binu++) = (outi[0] & 0xff); *(binu++) = (outi[0] & 0xff);
++j; ++j;
default: default:
break; break;
} }
for (; j < outisz; ++j) for (; j < outisz; ++j) {
{
*(binu++) = (outi[j] >> 0x18) & 0xff; *(binu++) = (outi[j] >> 0x18) & 0xff;
*(binu++) = (outi[j] >> 0x10) & 0xff; *(binu++) = (outi[j] >> 0x10) & 0xff;
*(binu++) = (outi[j] >> 8) & 0xff; *(binu++) = (outi[j] >> 8) & 0xff;
*(binu++) = (outi[j] >> 0) & 0xff; *(binu++) = (outi[j] >> 0) & 0xff;
} }
// Count canonical base58 byte count // Count canonical base58 byte count
binu = bin; binu = *bin;
for (i = 0; i < binsz; ++i) for (i = 0; i < binsz; ++i) {
{ if (binu[i]) {
if (binu[i])
break; break;
}
--*binszp; --*binszp;
} }
*binszp += zerocount; *binszp += zerocount;
return true; memset(outi, 0, outisz * sizeof(*outi));
return 1;
} }
static /**
bool my_dblsha256(void *hash, const void *data, size_t datasz) * encode an array of bytes into a base58 string
* @param binary_data the data to be encoded
* @param binary_data_size the size of the data to be encoded
* @param base58 the results buffer
* @param base58_size the size of the results buffer
* @returns true(1) on success
*/
//int libp2p_crypto_encoding_base58_encode(const unsigned char* binary_data, size_t binary_data_size, unsigned char* base58, size_t* base58_size)
int libp2p_crypto_encoding_base58_encode(const unsigned char* data, size_t binsz, unsigned char** b58, size_t* b58sz)
{ {
uint8_t buf[0x20]; const uint8_t* bin = data;
return b58_sha256_impl(buf, data, datasz) && b58_sha256_impl(hash, buf, sizeof(buf));
}
int b58check(const void *bin, size_t binsz, const char *base58str, size_t b58sz)
{
unsigned char buf[32];
const uint8_t *binc = bin;
unsigned i;
if (binsz < 4)
return -4;
if (!my_dblsha256(buf, bin, binsz - 4))
return -2;
if (memcmp(&binc[binsz - 4], buf, 4))
return -1;
// Check number of zeros is correct AFTER verifying checksum (to avoid possibility of accessing base58str beyond the end)
for (i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i)
{} // Just finding the end of zeros, nothing to do in loop
if (binc[i] == '\0' || base58str[i] == '1')
return -3;
return binc[0];
}
static const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz)
{
const uint8_t *bin = data;
int carry; int carry;
ssize_t i, j, high, zcount = 0; ssize_t i, j, high, zcount = 0;
size_t size; size_t size;
while (zcount < binsz && !bin[zcount]) while (zcount < (ssize_t)binsz && !bin[zcount]) {
++zcount; ++zcount;
}
size = (binsz - zcount) * 138 / 100 + 1; size = (binsz - zcount) * 138 / 100 + 1;
uint8_t buf[size]; uint8_t buf[size];
memset(buf, 0, size); memset(buf, 0, size);
for (i = zcount, high = size - 1; i < binsz; ++i, high = j) for (i = zcount, high = size - 1; i < (ssize_t)binsz; ++i, high = j) {
{ for (carry = bin[i], j = size - 1; (j > high) || carry; --j) {
for (carry = bin[i], j = size - 1; (j > high) || carry; --j)
{
carry += 256 * buf[j]; carry += 256 * buf[j];
buf[j] = carry % 58; buf[j] = carry % 58;
carry /= 58; carry /= 58;
} }
} }
for (j = 0; j < size && !buf[j]; ++j); for (j = 0; j < (ssize_t)size && !buf[j]; ++j)
;
if (*b58sz <= zcount + size - j) if (*b58sz <= zcount + size - j) {
{
*b58sz = zcount + size - j + 1; *b58sz = zcount + size - j + 1;
return false; memset(buf, 0, size);
return 0;
} }
if (zcount) if (zcount) {
memset(b58, '1', zcount); memset(b58, '1', zcount);
for (i = zcount; j < size; ++i, ++j) }
b58[i] = b58digits_ordered[buf[j]]; for (i = zcount; j < (ssize_t)size; ++i, ++j) {
b58[i] = '\0'; (*b58)[i] = b58digits_ordered[buf[j]];
}
(*b58)[i] = '\0';
*b58sz = i + 1; *b58sz = i + 1;
return true; memset(buf, 0, size);
return 1;
} }
bool b58check_enc(char *b58c, size_t *b58c_sz, uint8_t ver, const void *data, size_t datasz) /***
{ * calculate the size of the binary results based on an incoming base58 string
uint8_t buf[1 + datasz + 0x20]; * @param base58_string the string
uint8_t *hash = &buf[1 + datasz]; * @returns the size in bytes had the string been decoded
*/
size_t libp2p_crypto_encoding_base58_decode_size(const unsigned char* base58_string) {
size_t string_length = strlen((char*)base58_string);
size_t decoded_length = 0;
size_t radix = strlen(b58digits_ordered);
double bits_per_digit = log2(radix);
buf[0] = ver; decoded_length = floor(string_length * bits_per_digit / 8);
memcpy(&buf[1], data, datasz); return decoded_length;
if (!my_dblsha256(hash, buf, datasz + 1)) }
{
*b58c_sz = 0; /**
return false; * calculate the max length in bytes of an encoding of n source bits
} * @param base58_string the string
* @returns the maximum size in bytes had the string been decoded
*/
size_t libp2p_crypto_encoding_base58_decode_max_size(const unsigned char* base58_string) {
size_t string_length = strlen((char*)base58_string);
size_t decoded_length = 0;
size_t radix = strlen(b58digits_ordered);
double bits_per_digit = log2(radix);
return b58enc(b58c, b58c_sz, buf, 1 + datasz + 4); decoded_length = ceil(string_length * bits_per_digit / 8);
} return decoded_length;
}

View file

@ -1,24 +1,47 @@
#ifndef LIBBASE58_H //
#define LIBBASE58_H // base58.h
// libp2p_xcode
//
// Created by John Jones on 11/7/16.
// Copyright © 2016 JMJAtlanta. All rights reserved.
//
#include <stdbool.h> #ifndef base58_h
#include <stddef.h> #define base58_h
#include <stdint.h> #include "varint.h"
/**
* convert a base58 encoded string into a binary array
* @param base58 the base58 encoded string
* @param base58_size the size of the encoded string
* @param binary_data the results buffer
* @param binary_data_size the size of the results buffer
* @returns true(1) on success
*/
int libp2p_crypto_encoding_base58_decode(const unsigned char* base58, size_t base58_size, unsigned char** binary_data, size_t *binary_data_size);
#ifdef __cplusplus /**
extern "C" { * encode an array of bytes into a base58 string
#endif * @param binary_data the data to be encoded
* @param binary_data_size the size of the data to be encoded
* @param base58 the results buffer
* @param base58_size the size of the results buffer
* @returns true(1) on success
*/
int libp2p_crypto_encoding_base58_encode(const unsigned char* binary_data, size_t binary_data_size, unsigned char** base58, size_t* base58_size);
extern bool (*b58_sha256_impl)(void *, const void *, size_t); /***
* calculate the size of the binary results based on an incoming base58 string with no initial padding
* @param base58_string the string
* @returns the size in bytes had the string been decoded
*/
size_t libp2p_crypto_encoding_base58_decode_size(const unsigned char* base58_string);
extern bool b58tobin(void *bin, size_t *binsz, const char *b58, size_t b58sz); /**
extern int b58check(const void *bin, size_t binsz, const char *b58, size_t b58sz); * calculate the max length in bytes of an encoding of n source bits
* @param base58_string the string
* @returns the maximum size in bytes had the string been decoded
*/
size_t libp2p_crypto_encoding_base58_decode_max_size(const unsigned char* base58_string);
extern bool b58enc(char *b58, size_t *b58sz, const void *bin, size_t binsz);
extern bool b58check_enc(char *b58c, size_t *b58c_sz, uint8_t ver, const void *data, size_t datasz);
#ifdef __cplusplus #endif /* base58_h */
}
#endif
#endif

View file

@ -9,8 +9,44 @@
#include "base58.h" #include "base58.h"
#include "varhexutils.h" #include "varhexutils.h"
#include "protocols.h" #include "protocols.h"
//IP2INT //////////////////////////////////////////////////////////
char ASCII2bits(char ch) {
if (ch >= '0' && ch <= '9') {
return (ch - '0');
} else if (ch >= 'a' && ch <= 'z') {
return (ch - 'a') + 10;
} else if (ch >= 'A' && ch <= 'Z') {
return (ch - 'A') + 10;
}
return 0; // fail
}
void hex2bin (char *dst, char *src, int len)
{
while (len--) {
*dst = ASCII2bits(*src++) << 4; // higher bits
*dst++ |= ASCII2bits(*src++); // lower bits
}
}
char bits2ASCII(char b) {
if (b >= 0 && b < 10) {
return (b + '0');
} else if (b >= 10 && b <= 15) {
return (b - 10 + 'a');
}
return 0; // fail
}
void bin2hex (char *dst, char *src, int len)
{
while (len--) {
*dst++ = bits2ASCII((*src >> 4) & 0xf); // higher bits
*dst++ = bits2ASCII(*src++ & 0xf); // lower bits
}
*dst = '\0';
}
//////////////////////////////////////////////////////////
//IPv4 VALIDATOR //IPv4 VALIDATOR
#define DELIM "." #define DELIM "."
@ -196,7 +232,6 @@ int is_valid_ipv6(char *str)
return(err==0); return(err==0);
} }
///Still in work
uint64_t ip2int(char * ipconvertint) uint64_t ip2int(char * ipconvertint)
{ {
uint64_t final_result =0; uint64_t final_result =0;
@ -289,55 +324,104 @@ int bytes_to_string(char * resultzx, uint8_t * catx,int xbsize)
struct protocol * PID; struct protocol * PID;
PID = NULL; PID = NULL;
PID = proto_with_deccode(Hex_To_Int(pid)); PID = proto_with_deccode(Hex_To_Int(pid));
lastpos = lastpos+2; if(strcmp(PID->name,"ipfs")!=0)
char address[(PID->size/4)+1];
bzero(address,(PID->size/4)+1);
address[(PID->size/4)]='\0';
int x=0;
//printf("\nHEX TO DECODE: %s\n",hex);
for(int i = lastpos;i<(PID->size/4)+lastpos;i++)
{ {
address[x] = hex[i]; lastpos = lastpos+2;
//printf("HEX[%d]=%c\n",i,hex[i]); char address[(PID->size/4)+1];
x++; bzero(address,(PID->size/4)+1);
} address[(PID->size/4)]='\0';
//////////Stage 3 Process it back to string int x=0;
//printf("Protocol: %s\n", PID->name); //printf("\nHEX TO DECODE: %s\n",hex);
//printf("Address : %s\n", address); for(int i = lastpos;i<(PID->size/4)+lastpos;i++)
lastpos= lastpos+(PID->size/4); {
//printf("lastpos: %d",lastpos); address[x] = hex[i];
//printf("HEX[%d]=%c\n",i,hex[i]);
//////////Address: x++;
//Keeping Valgrind happy }
char name[30]; //////////Stage 3 Process it back to string
bzero(name,30); //printf("Protocol: %s\n", PID->name);
strcpy(name, PID->name); //printf("Address : %s\n", address);
// lastpos= lastpos+(PID->size/4);
strcat(resultzx, "/"); //printf("lastpos: %d",lastpos);
strcat(resultzx, name);
strcat(resultzx, "/"); //////////Address:
if(strcmp(name, "ip4")==0) //Keeping Valgrind happy
{ char name[30];
strcat(resultzx,int2ip(Hex_To_Int(address))); bzero(name,30);
} strcpy(name, PID->name);
else if(strcmp(name, "tcp")==0) //
{ strcat(resultzx, "/");
char a[5]; strcat(resultzx, name);
strcat(resultzx, "/");
if(strcmp(name, "ip4")==0)
{
strcat(resultzx,int2ip(Hex_To_Int(address)));
}
else if(strcmp(name, "tcp")==0)
{
char a[5];
sprintf(a,"%lu",Hex_To_Int(address));
strcat(resultzx,a);
}
else if(strcmp(name, "udp")==0)
{
char a[5];
sprintf(a,"%lu",Hex_To_Int(address)); sprintf(a,"%lu",Hex_To_Int(address));
strcat(resultzx,a); strcat(resultzx,a);
}
//printf("Address(hex):%s\n",address);
//printf("TESTING: %s\n",resultzx);
/////////////Done processing this, move to next if there is more.
if(lastpos<size*2)
{
goto NAX;
}
} }
else if(strcmp(name, "udp")==0) else//IPFS CASE
{ {
char a[5];
sprintf(a,"%lu",Hex_To_Int(address)); lastpos = lastpos + 4;
strcat(resultzx,a); //FETCHING SIZE OF ADDRESS
} char prefixedvarint[3];
//printf("Address(hex):%s\n",address); bzero(prefixedvarint,3);
//printf("TESTING: %s\n",resultzx); int pvi;
/////////////Done processing this, move to next if there is more. pvi=0;
if(lastpos<size*2) for(int i=lastpos-2;i<lastpos;i++)
{ {
goto NAX; prefixedvarint[pvi] = hex[i];
pvi++;
}
int addrsize;
addrsize = HexVar_To_Num_32(prefixedvarint);
unsigned char IPFS_ADDR[addrsize+1];
bzero(IPFS_ADDR,addrsize+1);
int IPFS_PARSE;
IPFS_PARSE = 0;
for(int i = lastpos;i<lastpos+addrsize;i++)
{
IPFS_ADDR[IPFS_PARSE] = hex[i];
//printf("\nIPFS_ADDR[%d] = %c\n\n",IPFS_PARSE,hex[i]);
IPFS_PARSE++;
}
unsigned char addrbuf[strlen(IPFS_ADDR)/2];
bzero(addrbuf,strlen(IPFS_ADDR)/2);
memcpy(addrbuf,Hex_To_Var(IPFS_ADDR),sizeof(addrbuf));
size_t rezbuflen = strlen(IPFS_ADDR);
unsigned char rezultat[rezbuflen];
bzero(rezultat,rezbuflen);
unsigned char * pointyaddr = NULL;
pointyaddr = rezultat;
int returnstatus = 0;
returnstatus = libp2p_crypto_encoding_base58_encode(addrbuf, sizeof(addrbuf), &pointyaddr, &rezbuflen);
if(returnstatus == 0)
{
printf("\nERROR!!!!!\n");
return 0;
}
strcat(resultzx, "/");
strcat(resultzx, PID->name);
strcat(resultzx, "/");
strcat(resultzx, rezultat);
} }
} }
strcat(resultzx, "/"); strcat(resultzx, "/");
@ -475,8 +559,48 @@ char * address_string_to_bytes(struct protocol * xx, char * abc,size_t getsznow)
} }
case 42://IPFS - !!! case 42://IPFS - !!!
{ {
return "ERR"; char * x_data = NULL;
x_data = abc;
size_t x_data_length = strlen(x_data);
size_t result_buffer_length = libp2p_crypto_encoding_base58_decode_max_size(x_data);
unsigned char result_buffer[result_buffer_length];
unsigned char* ptr_to_result = result_buffer;
memset(result_buffer, 0, result_buffer_length);
// now get the decoded address
int return_value = libp2p_crypto_encoding_base58_decode(x_data, x_data_length, &ptr_to_result, &result_buffer_length);
if (return_value == 0)
{
return "ERR";
}
// throw everything in a hex string so we can debug the results
static char returning_result[300];
bzero(returning_result,300);
char ADDR_ENCODED[300];
bzero(ADDR_ENCODED,300);
int ilen = 0;
bzero(returning_result,300);
for(int i = 0; i < result_buffer_length; i++)
{
// get the char so we can see it in the debugger
unsigned char c = ptr_to_result[i];
char miu[3];
bzero(miu, 3);
miu[3] = '\0';
sprintf(miu,"%02x", c);
strcat(ADDR_ENCODED, miu);
}
ilen = strlen(ADDR_ENCODED);
char prefixed[3];
strcpy(prefixed,Num_To_HexVar_32(ilen));
prefixed[3] = '\0';
strcat(returning_result, prefixed);
strcat(returning_result, ADDR_ENCODED);
//printf("ADDRESS: %s\nSIZEADDR: %d\n",ADDR_ENCODED,ilen);
//printf("NOW DECODED VARINT: %d", HexVar_To_Num_32(prefixed));
return returning_result;
break; break;
} }
case 480://http case 480://http