FANDOM


Byteball-to-TCP Proxy

With the help of this special chatbot it is possible to develop the actual bot in any programming language. Byteball-to-TCP Proxy (bb2tcp) listens on the Byteball network like a regular chatbot, except that for each paired device it establishes a new TCP connection to a predefined server. Thus, it acts as a proxy between a custom TCP server and the paired Byteball client device.

This software makes it no longer necessary for the Byteball chatbots to be developed in Node.js. Thus, the developer is free to choose whichever programming language they prefer for the bot. What is more, bb2tcp can be configured to send notifications to a custom server upon any pairing attempts. The latter can be used to implement two-factor or passwordless authentication (for example, see Slice&Dice Dungeon ).

To implement passwordless authentication with the help of Byteball, the application should present the user with a customly generated QR code. The payload of that QR code should contain a pairing link such as byteball:A/SCXz5tNuJDLuCO8PXpsfUoL7dCMBGnvSST7z0YPXjd@byteball.org/bb#bki433fsb where the end part (in bold) is randomly generated by the server. When the user scans the given QR code with their Byteball device a pairing attempt with the code bki433fsb is made and the bb2tcp chatbot notifies the application by sending the device address and the provided pairing code to the application server. The application server then knows which Byteball device is attempting to authorize themselves so the respective user session's privileges could be elevated immediately without any input from the user.

The bb2tcp chatbot is developed and maintained by @hyena from the Byteball's official Slack. All questions and ideas for enhancements are welcome.

Byteball address validation in C++

#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>
#include <type_traits>
 
bool is_byteball_addr(const char *addr) {
    static const unsigned char offsets[] = {
          1,   5,   6,  11,  20,  22,  28,  33,
         36,  41,  49,  58,  65,  74,  77,  79,
         82,  90,  94, 100, 102, 108, 112, 115,
        118, 126, 129, 131, 138, 147, 152, 154
    };
    const size_t offsets_sz = std::extent<decltype(offsets)>::value;
    bool bits[32*5];
    unsigned char data[16];
    unsigned char checksum[4];
 
    { // Base32 validation and decoding.
        auto b32 = [](char c) -> unsigned char {
            return ( (c >= 65 && c <= 90) ? (unsigned char) (     c - 65) :
                     (c >= 50 && c <= 55) ? (unsigned char) (26 + c - 50) : 255 );
        };
 
        auto isb32 = [](char c) -> bool {
            return ( (c >= 65 && c <= 90) || (c >= 50 && c <= 55) );
        };
 
        size_t i = 0;
        char *c = (char *) &(*addr);
        while (isb32(*c) && i < 32) {
            unsigned char value = b32(*c++);
            for (size_t j=0; j<5; ++j) {
                bool bit = (value % 2);
                value /= 2;
                bits[5*i + (4-j)] = bit;
            }
            ++i;
        }
        if (i != 32 || *c) return false;
    }
 
    { // Separation of the checksum from the clean data.
        auto bits2bytes = [](bool *b, unsigned char *B, size_t sz) -> void {
            for (size_t i=0; i<sz; ++i) {
                unsigned char byte = 0;
                for (size_t j=0; j<8; ++j) {
                    bool bit = b[i*8 + j];
                    byte ^= (unsigned char) ( (-bit ^ byte) & (1 << (7-j)) );
                }
                B[i] = byte;
            }
        };
 
        bool data_bits[128];
        bool checksum_bits[32];
        size_t start = 0;
        size_t data_bit_i = 0;
        size_t checksum_bit_i = 0;
        for (size_t i=0; i<offsets_sz; ++i) {
            for (size_t j=start; j<offsets[i]; ++j) {
                data_bits[data_bit_i++] = bits[j];
            }
            checksum_bits[checksum_bit_i++] = bits[offsets[i]];
            start = offsets[i]+1;
        }
        memcpy(data_bits+123, bits+155, 5); // Add last fragment.
 
        bits2bytes(data_bits, data, 16);
        bits2bytes(checksum_bits, checksum, 4);
    }
 
    { // Validate the checksum (requires the openssl/sha.h header).
        SHA256_CTX context;
        unsigned char md[SHA256_DIGEST_LENGTH];
 
        SHA256_Init(&context);
        SHA256_Update(&context, (unsigned char*) data, 16);
        SHA256_Final(md, &context);
 
        if (md[ 5] == checksum[0]
        &&  md[13] == checksum[1]
        &&  md[21] == checksum[2]
        &&  md[29] == checksum[3]) return true;
    }
 
    return false;
}
 
int main( int argc, char * argv [] ) {
    int i;
 
    for (i = 1; i < argc; ++i ) {
        bool valid = is_byteball_addr(argv[i]);
        printf( "%s is %s\n", argv[i], valid ? "VALID." : "INVALID!");
    }
 
    return 0;
}
byteball github repo[1]

References

  1. https://github.com/byteball/byteball