ARK-IoT / Ark-Cpp

Ark: Cpp || a C++ Ark Ecosystem Wrapper for Machines ||
5 stars 4 forks source link

improve on Hash Type #25

Open sleepdefic1t opened 6 years ago

sleepdefic1t commented 6 years ago

Improve on the concept of a Hash type in the Ark-Cpp wrapper

The aim of this issue is to open the discussion of storing hash-types as bytes with optional retrieval as a hex-string.

objectives:

POC Implementation available in

https://github.com/sleepdefic1t/Ark-Cpp/tree/improvements_preview/src/types

Tested implementation uses Hashable as a temple such that hashes, keys, and signatures may be defined via

#define HASH_STORAGE_BYTE_COUNT 32
#define Hash Hashable<HASH_STORAGE_BYTE_COUNT>
#define PUBKEY_STORAGE_BYTE_COUNT 33
#define Publickey Hashable<PUBKEY_STORAGE_BYTE_COUNT>
#define PRIVKEY_STORAGE_BYTE_COUNT 32
#define Privatekey Hashable<PRIVKEY_STORAGE_BYTE_COUNT>
#define SIGNATURE_BYTE_COUNT 71
#define Signature Hashable<SIGNATURE_BYTE_COUNT>

Sample class implementation

template <size_t COUNT>
class Hashable :
    public Printable
{
  public:
    /************************************************** 
    * Constructor 
    * @brief: default empty constructor
    **************************************************/
    Hashable() : bytes_() {};
    /*************************************************/

    /************************************************** 
    * Constructor 
    * @param: const char *const newHash
    * @brief: also checks if Hash is empty before storage
    **************************************************/
    Hashable(const char *const newHash)
    { 
        strlen(newHash) != 0 ?
            this->set(newHash) :
            void(this->bytes_[0] = '\0');
    };
    /*************************************************/

    /************************************************** 
    * Deconstructor 
    * @brief: fill this->bytes_ with random data before deconstruction
    **************************************************/
    ~Hashable() {
        Sanitize(this->bytes_, COUNT);
    };
    /*************************************************/

    /************************************************** 
    * @brief: returns element count of Hashable object
    **************************************************/
    size_t count() const { return COUNT; };
    /*************************************************/

    /************************************************** 
    * @brief: returns size of Hashable object
    **************************************************/
    size_t size() const { return sizeof(this->bytes_); };
    /*************************************************/

    /************************************************** 
    * @brief: returns vector of stored bytes
    **************************************************/
    const inline std::vector<uint8_t> vBytes() const
    {
        return std::vector<uint8_t>(this->bytes_);
    };
    /*************************************************/

    /************************************************** 
    * @brief: returns vector of hex-string representation of stored bytes
    **************************************************/
    const inline std::vector<char> vHex() const
    {
        return (this->bytes_[0] != '\0') ?
                std::vector<char>(this->hex().c_str()) :
                std::vector<char>(1);
    };
    /*************************************************/

    /************************************************** 
    * @brief: returns hex-string representation of stored bytes
    **************************************************/
    std::string hex() const
    {
        if (this->bytes_[0] != '\0')
        {
            char hexBuffer[(COUNT * 2) + 1];
            BytesToHex(this->bytes_, hexBuffer, COUNT);
            return std::string( hexBuffer );
        }
        else
        {
            return std::string("");
        };
    }
    /*************************************************/

    /************************************************** 
    * @brief: returns hex c-string ('\0' or NULL Terminated string) representation of stored bytes
    **************************************************/
    operator const char *() const
    {
        return this->hex().c_str();
    };
    /*************************************************/

    /**************************************************
    * @param: Print& p 
    * @brief: prints Hashable object
    **************************************************/
    virtual size_t printTo(Print& p) const
    {
        size_t size = 0;
        size += p.print( this->hex().c_str() );
        return size;
    };
    /*************************************************/

  protected:
    uint8_t bytes_[COUNT];

    /**************************************************
    * @param: const char *const newHash 
    * @brief: Sets new Hash, copying byte-values to internal storage
    **************************************************/
    void set(const char *const newHash)
    {
        if (isHex(newHash))
        { 
            HexToBytes(newHash, this->bytes_);
        }
        else
        { 
            std::memmove(this->bytes_, newHash, COUNT);
        };
    };
    /*************************************************/

};

note: Sanitize method introduced to randomize byte data before deconstruction. This will necessarily have to use proven T/RNG functions in the crypto libraries, but is currently implemented as follows:

static uint8_t getRandomDigit()
{   
#ifdef USE_IOT
    randomSeed(random(0, 1024));
    return random(0, 255);
#else
    std::default_random_engine generator;
    std::uniform_int_distribution<uint32_t> distribution(0, 255);
    return distribution(generator);
#endif
}

static void Sanitize(uint8_t* buffer, size_t size)
{
    for (unsigned int i = 0; i < size; i++)
    {
        buffer[i] = getRandomDigit();
    };
};
sleepdefic1t commented 6 years ago

Current running implementation @

https://github.com/sleepdefic1t/Ark-Cpp/tree/improvements_preview/src/types

single header src/types/base/byteable.h


#ifndef BYTEABLE_H
#define BYTEABLE_H

#include "utilities/platform.h"
#include "utilities/formatting.h"
#include <vector>
#include <memory>

template <size_t COUNT>
class Byteable
{
    protected:
        uint8_t bytes_[COUNT];
    public:
        /************************************************** 
        * Constructor 
        * @brief: default empty constructor
        **************************************************/
        Byteable() : bytes_() {};
        /*************************************************/

        /************************************************** 
        * Constructor 
        * @brief: default constructor
        * @param: const uint8_t *const newBytes
        **************************************************/
        Byteable(const uint8_t *const newBytes)
        { 
            (sizeof(newBytes) == COUNT)
                ? std::memmove(this->bytes_, newBytes, COUNT)
                : void(this->bytes_[0] = '\0');
        };
        /*************************************************/

        /************************************************** 
        * Deconstructor 
        * @brief: fill this->bytes_ with random data before deconstruction
        **************************************************/
        ~Byteable() { Sanitize(this->bytes_, COUNT); };
        /*************************************************/

        /************************************************** 
        * @brief: returns size of Byteable object
        **************************************************/
        size_t size() const
        {
            return (sizeof(this->bytes_) == COUNT)
                    ? COUNT
                    : 0;
        };
        /*************************************************/

        /************************************************** 
        * @brief: returns vector of stored bytes
        **************************************************/
        const inline std::vector<uint8_t> vBytes() const
        {
            return std::vector<uint8_t>(this->bytes_);
        };
        /*************************************************/

};

#endif

single-header src/types/base/hexable.h


#ifndef HEXABLE_H
#define HEXABLE_H

#include "utilities/platform.h"
#include "utilities/formatting.h"
#include "types/base/byteable.h"
#include <vector>
#include <memory>

template <size_t COUNT>
class Hexable :
        public Printable,
        virtual Byteable<COUNT>
{
    public:
        /************************************************** 
        * Constructor 
        * @brief: default empty constructor
        **************************************************/
        Hexable() { this->bytes_[0] = '\0'; };
        /*************************************************/

        /************************************************** 
        * Constructor 
        * @param: const char *const newHash
        * @brief: also checks if Hash is empty before storage
        **************************************************/
        Hexable(const char *const newValue)
        { 
            (isHex(newValue))
                ? void(
                    std::memmove(
                        this->bytes_,
                        &ParseHex(newValue).data()[0],
                        COUNT
                    )
                )
                : void(this->bytes_[0] = '\0');
        };
        /*************************************************/

        /************************************************** 
        * @brief: returns vector of hex-string representation of stored bytes
        **************************************************/
        const inline std::vector<char> vHex() const
        {
            return (this->bytes_[0] != '\0')
                ? std::vector<char>(this->hex().c_str())
                : std::vector<char>(1);
        };
        /*************************************************/

        /**************************************************
        * @brief: return hex-cstring of Hexable type
        **************************************************/
        const char* c_str() const
        {
            return (this->bytes_[0] != '\0')
                ? BytesToHex(this->bytes_, this->bytes_ + COUNT).c_str()
                : std::string("").c_str();
        };

        /**************************************************
        * @param: Print& p 
        * @brief: prints Hexable object
        **************************************************/
        virtual size_t printTo(Print& p) const
        {
            size_t size = 0;
            size += p.print( this->c_str() );
            return size;
        };
        /*************************************************/

};

#endif

single-header src/types/crypto/eckey.h


#ifndef ECKEY_H
#define ECKEY_H

#include "utilities/platform.h"
#include "types/base/hexable.h"

/********************************************************************************
* Privatekey: 
* Elliptical Curve SECP256K1 Privatekey (essentially a SHA256 in this instance)
* 32 bytes
* 64 Characters
* @brief Represents a 256-bit number
********************************************************************************/

#define PRIVKEY_STORAGE_BYTE_COUNT 32
#define PRIVKEY_STRING_LENGTH 64

#define Privatekey Hexable<PRIVKEY_STORAGE_BYTE_COUNT>

/********************************************************************************
* Publickey: 
* Elliptical Curve SECP256K1 Compressed Publickey
* ex: "0275776018638e5c40f1b922901e96cac2caa734585ef302b4a2801ee9a338a456"
*
* 33 bytes
* 66 Characters
* @brief Represents a 257-bit number
********************************************************************************/

#define PUBKEY_STORAGE_BYTE_COUNT 33
#define PUBKEY_STRING_LENGTH 66

#define Publickey Hexable<PUBKEY_STORAGE_BYTE_COUNT>

#endif

single-header src/types/crypto/ecsignature.h


#ifndef ECSIGNATURE_H
#define ECSIGNATURE_H

#include "utilities/platform.h"
#include "types/base/hexable.h"

/********************************************************************************
* Signature: 
* Elliptical Curve SECP256K1 Signature
* ex: "3045022100e0fc6b066209fd9a70e61372cda2e38431ace5cf79ee0557eb2b1b14315d70f302201978696b71c9a177fa1ce9480ceb1ad04a15471d4c6e8d5b2dcd6d931f350efe"
*
* 71 bytes
* 142 Characters
********************************************************************************/

#define SIGNATURE_BYTE_COUNT 71
#define SIGNATURE_STRING_LENGTH 142

#define Signature Hexable<SIGNATURE_BYTE_COUNT>

#endif

single-header src/types/address.h


#ifndef ADDRESS_H
#define ADDRESS_H

#include "utilities/platform.h"
#include "utilities/formatting.h"
#include "types/base/byteable.h"
#include <cstring>
#include <memory>

/*******************************************************************************
* address: 
* "DHQ4Fjsyiop3qBR4otAjAu6cBHkgRELqGA"
*   
* 34 Characters | Base58-encoded
* Size 272
* 160-bit base58Encoded hash from a RIPEME160 hash
********************************************************************************/
#define ADDRESS_LENGTH 34       /* Actual Length of Address */
/*************************************************
* Address
**************************************************/
class Address :
        public Printable,
        virtual Byteable<ADDRESS_LENGTH>
{
    public:
        /************************************************** 
        * Constructor 
        * @brief: default empty constructor
        **************************************************/
        Address() {};
        /*************************************************/

        /************************************************** 
        * Constructor 
        * @brief: default constructor
        * @param: const char *const newValue
        **************************************************/
        Address(const char *const newValue)
        { 
            (strlen(newValue) == ADDRESS_LENGTH)
                ? void(std::memmove(this->bytes_, newValue, ADDRESS_LENGTH))
                : void(this->bytes_[0] = { '\0' });
        };
        /*************************************************/

        /************************************************** 
        * @brief: returns cstring representation of stored bytes
        **************************************************/
        const char* c_str() const
        {
            return std::string(
                this->bytes_,
                this->bytes_ + ADDRESS_LENGTH
            ).c_str();
        };
        /*************************************************/

        /**************************************************
        * @param: Print& p 
        * @brief: prints Address object
        **************************************************/
        virtual size_t printTo(Print& p) const
        {
            size_t size = 0;
            for (int i = 0; i < ADDRESS_LENGTH; i++)
            {
                size += p.print( this->bytes_[i] );
            };
            return size;
        };
        /*************************************************/

};

#endif

single-header src/types/hash.h


#ifndef ADDRESS_H
#define ADDRESS_H

#include "utilities/platform.h"
#include "utilities/formatting.h"
#include "types/base/byteable.h"
#include <cstring>
#include <memory>

/*******************************************************************************
* address: 
* "DHQ4Fjsyiop3qBR4otAjAu6cBHkgRELqGA"
*   
* 34 Characters | Base58-encoded
* Size 272
* 160-bit base58Encoded hash from a RIPEME160 hash
********************************************************************************/
#define ADDRESS_LENGTH 34       /* Actual Length of Address */
/*************************************************
* Address
**************************************************/
class Address :
        public Printable,
        virtual Byteable<ADDRESS_LENGTH>
{
    public:
        /************************************************** 
        * Constructor 
        * @brief: default empty constructor
        **************************************************/
        Address() {};
        /*************************************************/

        /************************************************** 
        * Constructor 
        * @brief: default constructor
        * @param: const char *const newValue
        **************************************************/
        Address(const char *const newValue)
        { 
            (strlen(newValue) == ADDRESS_LENGTH)
                ? void(std::memmove(this->bytes_, newValue, ADDRESS_LENGTH))
                : void(this->bytes_[0] = { '\0' });
        };
        /*************************************************/

        /************************************************** 
        * @brief: returns cstring representation of stored bytes
        **************************************************/
        const char* c_str() const
        {
            return std::string(
                this->bytes_,
                this->bytes_ + ADDRESS_LENGTH
            ).c_str();
        };
        /*************************************************/

        /**************************************************
        * @param: Print& p 
        * @brief: prints Address object
        **************************************************/
        virtual size_t printTo(Print& p) const
        {
            size_t size = 0;
            for (int i = 0; i < ADDRESS_LENGTH; i++)
            {
                size += p.print( this->bytes_[i] );
            };
            return size;
        };
        /*************************************************/

};

#endif