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.
*/
#ifndef WIN32
#include <arpa/inet.h>
#else
#include <winsock2.h>
#endif
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include <stdint.h>
#include <sys/types.h>
#include "base58.h"
bool (*b58_sha256_impl)(void *, const void *, size_t) = NULL;
static const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
static const int8_t b58digits_map[] = {
-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,
};
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;
const unsigned char *b58u = (void*)b58;
unsigned char *binu = bin;
const unsigned char* b58u = (const void*)b58;
unsigned char* binu = *bin;
size_t outisz = (binsz + 3) / 4;
uint32_t outi[outisz];
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;
uint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0;
unsigned zerocount = 0;
size_t b58sz;
if (!b58sz)
b58sz = strlen(b58);
b58sz = strlen(b58);
memset(outi, 0, outisz * sizeof(*outi));
// Leading zeros, just count
for (i = 0; i < b58sz && b58u[i] == '1'; ++i)
for (i = 0; i < b58sz && !b58digits_map[b58u[i]]; ++i) {
++zerocount;
}
for ( ; i < b58sz; ++i)
{
if (b58u[i] & 0x80)
for (; i < b58sz; ++i) {
if (b58u[i] & 0x80) {
// High-bit set on invalid digit
return false;
if (b58digits_map[b58u[i]] == -1)
return 0;
}
if (b58digits_map[b58u[i]] == -1) {
// Invalid base58 digit
return false;
return 0;
}
c = (unsigned)b58digits_map[b58u[i]];
for (j = outisz; j--; )
{
for (j = outisz; j--;) {
t = ((uint64_t)outi[j]) * 58 + c;
c = (t & 0x3f00000000) >> 32;
outi[j] = t & 0xffffffff;
}
if (c)
if (c) {
// Output number too big (carry to the next int32)
return false;
if (outi[0] & zeromask)
memset(outi, 0, outisz * sizeof(*outi));
return 0;
}
if (outi[0] & zeromask) {
// Output number too big (last int32 filled too far)
return false;
memset(outi, 0, outisz * sizeof(*outi));
return 0;
}
}
j = 0;
switch (bytesleft) {
case 3:
*(binu++) = (outi[0] & 0xff0000) >> 16;
*(binu++) = (outi[0] & 0xff0000) >> 16;
case 2:
*(binu++) = (outi[0] & 0xff00) >> 8;
*(binu++) = (outi[0] & 0xff00) >> 8;
case 1:
*(binu++) = (outi[0] & 0xff);
*(binu++) = (outi[0] & 0xff);
++j;
default:
break;
}
for (; j < outisz; ++j)
{
for (; j < outisz; ++j) {
*(binu++) = (outi[j] >> 0x18) & 0xff;
*(binu++) = (outi[j] >> 0x10) & 0xff;
*(binu++) = (outi[j] >> 8) & 0xff;
*(binu++) = (outi[j] >> 0) & 0xff;
*(binu++) = (outi[j] >> 8) & 0xff;
*(binu++) = (outi[j] >> 0) & 0xff;
}
// Count canonical base58 byte count
binu = bin;
for (i = 0; i < binsz; ++i)
{
if (binu[i])
binu = *bin;
for (i = 0; i < binsz; ++i) {
if (binu[i]) {
break;
}
--*binszp;
}
*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];
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;
const uint8_t* bin = data;
int carry;
ssize_t i, j, high, zcount = 0;
size_t size;
while (zcount < binsz && !bin[zcount])
while (zcount < (ssize_t)binsz && !bin[zcount]) {
++zcount;
}
size = (binsz - zcount) * 138 / 100 + 1;
uint8_t buf[size];
memset(buf, 0, size);
for (i = zcount, high = size - 1; i < binsz; ++i, high = j)
{
for (carry = bin[i], j = size - 1; (j > high) || carry; --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) {
carry += 256 * buf[j];
buf[j] = 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;
return false;
memset(buf, 0, size);
return 0;
}
if (zcount)
if (zcount) {
memset(b58, '1', zcount);
for (i = zcount; j < size; ++i, ++j)
b58[i] = b58digits_ordered[buf[j]];
b58[i] = '\0';
}
for (i = zcount; j < (ssize_t)size; ++i, ++j) {
(*b58)[i] = b58digits_ordered[buf[j]];
}
(*b58)[i] = '\0';
*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)
{
uint8_t buf[1 + datasz + 0x20];
uint8_t *hash = &buf[1 + datasz];
/***
* calculate the size of the binary results based on an incoming base58 string
* @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) {
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;
memcpy(&buf[1], data, datasz);
if (!my_dblsha256(hash, buf, datasz + 1))
{
*b58c_sz = 0;
return false;
}
decoded_length = floor(string_length * bits_per_digit / 8);
return decoded_length;
}
/**
* 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>
#include <stddef.h>
#include <stdint.h>
#ifndef base58_h
#define base58_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" {
#endif
/**
* 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);
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
#endif
#endif /* base58_h */

View file

@ -9,8 +9,44 @@
#include "base58.h"
#include "varhexutils.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
#define DELIM "."
@ -196,7 +232,6 @@ int is_valid_ipv6(char *str)
return(err==0);
}
///Still in work
uint64_t ip2int(char * ipconvertint)
{
uint64_t final_result =0;
@ -289,55 +324,104 @@ int bytes_to_string(char * resultzx, uint8_t * catx,int xbsize)
struct protocol * PID;
PID = NULL;
PID = proto_with_deccode(Hex_To_Int(pid));
lastpos = lastpos+2;
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++)
if(strcmp(PID->name,"ipfs")!=0)
{
address[x] = hex[i];
//printf("HEX[%d]=%c\n",i,hex[i]);
x++;
}
//////////Stage 3 Process it back to string
//printf("Protocol: %s\n", PID->name);
//printf("Address : %s\n", address);
lastpos= lastpos+(PID->size/4);
//printf("lastpos: %d",lastpos);
//////////Address:
//Keeping Valgrind happy
char name[30];
bzero(name,30);
strcpy(name, PID->name);
//
strcat(resultzx, "/");
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];
lastpos = lastpos+2;
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];
//printf("HEX[%d]=%c\n",i,hex[i]);
x++;
}
//////////Stage 3 Process it back to string
//printf("Protocol: %s\n", PID->name);
//printf("Address : %s\n", address);
lastpos= lastpos+(PID->size/4);
//printf("lastpos: %d",lastpos);
//////////Address:
//Keeping Valgrind happy
char name[30];
bzero(name,30);
strcpy(name, PID->name);
//
strcat(resultzx, "/");
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));
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));
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;
lastpos = lastpos + 4;
//FETCHING SIZE OF ADDRESS
char prefixedvarint[3];
bzero(prefixedvarint,3);
int pvi;
pvi=0;
for(int i=lastpos-2;i<lastpos;i++)
{
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, "/");
@ -475,8 +559,48 @@ char * address_string_to_bytes(struct protocol * xx, char * abc,size_t getsznow)
}
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;
}
case 480://http