git / moonbite-core / src/libmw/include/mw/models/crypto/SecretKey.h · raw
#pragma once// Copyright (c) 2018-2019 David Burkett// Distributed under the MIT software license, see the accompanying// file LICENSE or http://www.opensource.org/licenses/mit-license.php.#include <mw/common/Traits.h>#include <mw/models/crypto/Hash.h>#include <crypto/blake3/blake3.h>#include <random.h>class SecretKey : public Traits::ISerializable{public: static constexpr size_t SIZE = 32; // // Constructor // SecretKey() = default; explicit SecretKey(BigInt<SIZE>&& value) : m_value(std::move(value)) { } explicit SecretKey(const BigInt<SIZE>& value) : m_value(value) { } explicit SecretKey(std::vector<uint8_t>&& bytes) : m_value(BigInt<SIZE>(std::move(bytes))) { } explicit SecretKey(const std::vector<uint8_t>& bytes) : m_value(BigInt<SIZE>(bytes)) { } explicit SecretKey(const std::array<uint8_t, SIZE>& bytes) : m_value(BigInt<SIZE>(bytes)) {} explicit SecretKey(std::array<uint8_t, SIZE>&& bytes) : m_value(BigInt<SIZE>(std::move(bytes))) { } explicit SecretKey(const uint8_t* bytes) : m_value(BigInt<SIZE>(bytes)) { } static SecretKey Null() { return SecretKey(); } static SecretKey Random() { SecretKey key; do { GetStrongRandBytes(key.data(), SIZE); } while (!key.IsValid()); return key; } static SecretKey FromHash(const mw::Hash& hash) { SecretKey key(hash); if (key.IsValid()) { return key; } uint32_t counter = 0; do { blake3_hasher hasher; blake3_hasher_init(&hasher); static constexpr char tag[] = "MWEB hash-to-scalar"; blake3_hasher_update(&hasher, tag, sizeof(tag) - 1); blake3_hasher_update(&hasher, hash.data(), hash.size()); std::array<uint8_t, 4> counter_bytes{ static_cast<uint8_t>(counter), static_cast<uint8_t>(counter >> 8), static_cast<uint8_t>(counter >> 16), static_cast<uint8_t>(counter >> 24) }; blake3_hasher_update(&hasher, counter_bytes.data(), counter_bytes.size()); blake3_hasher_finalize(&hasher, key.data(), key.size()); counter++; } while (!key.IsValid()); return key; } // // Destructor // virtual ~SecretKey() = default; // // Operators // bool operator==(const SecretKey& rhs) const noexcept { return m_value == rhs.m_value; } bool operator!=(const SecretKey& rhs) const noexcept { return !(*this == rhs); } // // Getters // const BigInt<SIZE>& GetBigInt() const { return m_value; } std::string ToHex() const noexcept { return m_value.ToHex(); } bool IsNull() const noexcept { return m_value.IsZero(); } bool IsValid() const noexcept { return IsValidBytes(data()); } const std::vector<uint8_t>& vec() const { return m_value.vec(); } std::array<uint8_t, SIZE> array() const noexcept { return m_value.ToArray(); } uint8_t* data() { return m_value.data(); } const uint8_t* data() const { return m_value.data(); } uint8_t& operator[] (const size_t x) { return m_value[x]; } const uint8_t& operator[] (const size_t x) const { return m_value[x]; } size_t size() const { return m_value.size(); } // // Serialization/Deserialization // IMPL_SERIALIZABLE(SecretKey, obj) { READWRITE(obj.m_value); }private: static bool IsValidBytes(const uint8_t* bytes) noexcept { static constexpr std::array<uint8_t, SIZE> SECP256K1_ORDER{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 }}; bool nonzero = false; for (size_t i = 0; i < SIZE; i++) { if (bytes[i] != 0) { nonzero = true; break; } } if (!nonzero) { return false; } for (size_t i = 0; i < SIZE; i++) { if (bytes[i] != SECP256K1_ORDER[i]) { return bytes[i] < SECP256K1_ORDER[i]; } } return false; } BigInt<SIZE> m_value;};