From 7bc5ce1aa3e78beb4447b1859b9c4ab6391f045e Mon Sep 17 00:00:00 2001 From: "Dmitriy A. Gerasimov" <dmitriy.gerasimov@demlabs.net> Date: Mon, 4 Feb 2019 22:50:58 +0700 Subject: [PATCH] [+] Base58 encode/decode function --- crypto/dap_enc_base58.c | 187 ++++++++++++++++++++++++++++++++++++++++ crypto/dap_enc_base58.h | 47 ++++++++++ 2 files changed, 234 insertions(+) create mode 100755 crypto/dap_enc_base58.c create mode 100755 crypto/dap_enc_base58.h diff --git a/crypto/dap_enc_base58.c b/crypto/dap_enc_base58.c new file mode 100755 index 0000000..b23b3ed --- /dev/null +++ b/crypto/dap_enc_base58.c @@ -0,0 +1,187 @@ +/* + * Authors: + * Dmitriy A. Gearasimov <kahovski@gmail.com> + * DeM Labs Inc. https://demlabs.net + * Kelvin Blockchain community https://github.com/kelvinblockchain + * Copyright (c) 2017-2019 + * All rights reserved. + + This file is part of DAP (Deus Applications Prototypes) the open source project + + DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + DAP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> +#include "dap_common.h" +#include "dap_enc_base58.h" + +#define LOG_TAG "dap_enc_base58" + +const char c_b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; +const int8_t c_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, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1, + -1, 9,10,11,12,13,14,15,16,-1,17,18,19,20,21,-1, + 22,23,24,25,26,27,28,29,30,31,32,-1,-1,-1,-1,-1, + -1,33,34,35,36,37,38,39,40,41,42,43,-1,44,45,46, + 47,48,49,50,51,52,53,54,55,56,57,-1,-1,-1,-1,-1, +}; + +/** + * @brief dap_enc_base58_decode + * @param a_in + * @param a_out + * @return + */ +size_t dap_enc_base58_decode(const char * a_in, void * a_out) +{ + size_t l_out_size_max = DAP_ENC_BASE58_DECODE_SIZE(strlen(a_in )); + size_t l_out_size = l_out_size_max; + + const unsigned char *l_in_u8 = (const unsigned char*)a_in; + unsigned char *l_out_u8 = a_out; + size_t l_outi_size = (l_out_size_max + 3) / 4; + + uint32_t l_outi[l_outi_size]; + memzero(l_outi,l_outi_size); + uint64_t t; + uint32_t c; + size_t i, j; + uint8_t bytesleft = l_out_size_max % 4; + uint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0; + unsigned zerocount = 0; + size_t l_in_len = strlen(a_in); + + + // Leading zeros, just count + for (i = 0; i < l_in_len && l_in_u8[i] == '1'; ++i) + ++zerocount; + + for ( ; i < l_in_len; ++i) + { + if (l_in_u8[i] & 0x80) + // High-bit set on invalid digit + return false; + if (c_b58digits_map[l_in_u8[i]] == -1) + // Invalid base58 digit + return false; + c = (unsigned)c_b58digits_map[l_in_u8[i]]; + for (j = l_outi_size; j--; ) + { + t = ((uint64_t)l_outi[j]) * 58 + c; + c = (t & 0x3f00000000) >> 32; + l_outi[j] = t & 0xffffffff; + } + if (c) + // Output number too big (carry to the next int32) + return 0; + if (l_outi[0] & zeromask) + // Output number too big (last int32 filled too far) + return 0; + } + + j = 0; + switch (bytesleft) { + case 3: + *(l_out_u8++) = (l_outi[0] & 0xff0000) >> 16; + //-fallthrough + case 2: + *(l_out_u8++) = (l_outi[0] & 0xff00) >> 8; + //-fallthrough + case 1: + *(l_out_u8++) = (l_outi[0] & 0xff); + ++j; + //-fallthrough + default: + break; + } + + for (; j < l_outi_size; ++j) + { + *(l_out_u8++) = (l_outi[j] >> 0x18) & 0xff; + *(l_out_u8++) = (l_outi[j] >> 0x10) & 0xff; + *(l_out_u8++) = (l_outi[j] >> 8) & 0xff; + *(l_out_u8++) = (l_outi[j] >> 0) & 0xff; + } + + // Count canonical base58 byte count + l_out_u8 = a_out; + for (i = 0; i < l_out_size_max; ++i) + { + if (l_out_u8[i]) { + if (zerocount > i) { + /* result too large */ + return 0; + } + break; + } + --l_out_size; + } + l_out_size += zerocount; + + return l_out_size; +} + + + +//bool b58enc(char *a_out, size_t *l_out_size, const void *a_in, size_t a_in_size) +size_t dap_enc_base58_encode(const void * a_in, size_t a_in_size, char * a_out) +{ + const uint8_t *l_in_u8 = a_in; + int carry; + ssize_t i, j, high, zcount = 0; + size_t size; + size_t l_out_size = DAP_ENC_BASE58_ENCODE_SIZE (a_in_size); + while (zcount < (ssize_t)a_in_size && !l_in_u8[zcount]) + ++zcount; + + size = (a_in_size - zcount) * 138 / 100 + 1; + uint8_t buf[size]; + memzero(buf, size); + + for (i = zcount, high = size - 1; i < (ssize_t)a_in_size; ++i, high = j) + { + for (carry = l_in_u8[i], j = size - 1; (j > high) || carry; --j) + { + carry += 256 * buf[j]; + buf[j] = carry % 58; + carry /= 58; + } + } + + for (j = 0; j < (ssize_t)size && !buf[j]; ++j); + + if (l_out_size <= ( zcount + size - j) ){ + l_out_size = ( zcount + size - j + 1 ); + return l_out_size; + } + + if (zcount) + memset(a_out, '1', zcount); + for (i = zcount; j < (ssize_t)size; ++i, ++j) + a_out[i] = c_b58digits_ordered[buf[j]]; + a_out[i] = '\0'; + l_out_size = i + 1; + + return l_out_size; +} + + + + diff --git a/crypto/dap_enc_base58.h b/crypto/dap_enc_base58.h new file mode 100755 index 0000000..0ca469c --- /dev/null +++ b/crypto/dap_enc_base58.h @@ -0,0 +1,47 @@ +/* + * Authors: + * Dmitriy A. Gearasimov <kahovski@gmail.com> + * DeM Labs Inc. https://demlabs.net + * Kelvin Blockchain community https://github.com/kelvinblockchain + * Copyright (c) 2017-2019 + * All rights reserved. + + This file is part of DAP (Deus Applications Prototypes) the open source project + + DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + DAP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _DAP_ENC_BASE64_H_ +#define _DAP_ENC_BASE64_H_ +#include <stddef.h> +#include <stdint.h> +#include "dap_enc_key.h" +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Calculates encode size from input size + */ +#define DAP_ENC_BASE58_ENCODE_SIZE(a_in_size) ( (size_t) ((137 * a_in_size / 100)+1)) +#define DAP_ENC_BASE58_DECODE_SIZE(a_in_size) ( (size_t) ( 2 * a_in_size +1) ) + +size_t dap_enc_base58_encode(const void * a_in, size_t a_in_size, char * a_out); +size_t dap_enc_base58_decode(const char * a_in, void * a_out); + +#ifdef __cplusplus +} +#endif + +#endif -- GitLab