llarp/crypto/types.hpp

Namespaces

Name
llarp
[crypto.hpp]
std
STL namespace.

Classes

Name
class llarp::MemWipe
struct llarp::WipeArray
struct llarp::PubKey
struct llarp::SecretKey
Stores a sodium "secret key" value, which is actually the seed concatenated with the public key.
struct llarp::PrivateKey
PrivateKey is similar to SecretKey except that it only stores the private key value and a hash, unlike SecretKey which stores the seed from which the private key and hash value are generated.
struct llarp::IdentitySecret
IdentitySecret is a secret key from a service node secret seed.
struct llarp::Signature
struct llarp::PQKeyPair
struct std::hash< llarp::PubKey >

Source code

#pragma once

#include "constants.hpp"
#include <llarp/router_id.hpp>
#include <llarp/util/aligned.hpp>
#include <llarp/util/types.hpp>
#include <llarp/util/formattable.hpp>
#include <sodium/utils.h>
#include <llarp/util/mem.hpp>

namespace llarp
{
  template <typename T, size_t sz = sizeof(T)>
  class MemWipe
  {
    void* m_ref{nullptr};

   public:
    explicit MemWipe(T* ref) : m_ref{reinterpret_cast<void*>(ref)}
    {}
    explicit MemWipe(void* ref) : m_ref{ref}
    {}

    MemWipe(MemWipe&&) = delete;

    MemWipe(const MemWipe&) = delete;

    ~MemWipe()
    {
      if (m_ref)
        ::sodium_memzero(m_ref, sz);
    }

    bool
    IsZero() const;
  };
}  // namespace llarp

namespace llarp
{

  template <size_t sz>
  struct WipeArray
  {
    ALIGNED_BUFFER_MEMBERS(WipeArray, sz)
   public:
    ~WipeArray()
    {
      ::sodium_memzero(data(), size());
    }
  };

  template <>
  constexpr inline bool is_aligned_buffer<WipeArray<32>> = true;

  using SharedSecret = WipeArray<SHAREDKEYSIZE>;
  using KeyExchangeNonce = WipeArray<32>;

  struct PubKey final
  {
    ALIGNED_BUFFER_MEMBERS(PubKey, PUBKEYSIZE)

    std::string
    ToString() const;

    bool
    FromString(const std::string& str);

    operator RouterID() const
    {
      return RouterID{data()};
    }

    bool
    operator==(const RouterID& rid) const
    {
      return as_array() == rid.as_array();
    }
  };

  inline auto
  operator<=>(const PubKey& lhs, const PubKey& rhs)
  {
    return lhs.as_array() <=> rhs.as_array();
  }

  inline auto
  operator<=>(const PubKey& lhs, const RouterID& rhs)
  {
    return lhs.as_array() <=> rhs.as_array();
  }

  inline auto
  operator<=>(const RouterID& lhs, const PubKey& rhs)
  {
    return lhs.as_array() <=> rhs.as_array();
  }

  struct PrivateKey;

  struct SecretKey final
  {
    ALIGNED_BUFFER_MEMBERS(SecretKey, SECKEYSIZE)
   public:
    ~SecretKey();
    // The full data
    explicit SecretKey(const std::array<byte_t, SECKEYSIZE>& buf);

    // Just the seed, we recalculate the pubkey
    explicit SecretKey(const std::array<byte_t, SEEDSIZE>& seed);

    bool
    Recalculate();

    std::string_view
    ToString() const
    {
      return "[secretkey]";
    }

    PubKey
    toPublic() const
    {
      return PubKey(data() + 32);
    }

    bool
    toPrivate(PrivateKey& key) const;

    template <typename fspath_t>
    bool
    LoadFromFile(const fspath_t& fname);

    template <typename fspath_t>
    bool
    SaveToFile(const fspath_t& fname) const;
  };

  struct PrivateKey final
  {
    ALIGNED_BUFFER_MEMBERS(PrivateKey, 64)
   public:
    ~PrivateKey();

    explicit PrivateKey(const AlignedBuffer<SIZE>& key_and_hash);

    constexpr const byte_t*
    signingHash() const
    {
      return data() + 32;
    }

    constexpr byte_t*
    signingHash()
    {
      return data() + 32;
    }

    std::string_view
    ToString() const
    {
      return "[privatekey]";
    }

    bool
    toPublic(PubKey& pubkey) const;
  };

  struct IdentitySecret final
  {
    ALIGNED_BUFFER_MEMBERS_NO_CTOR(IdentitySecret, 32)

   public:
    IdentitySecret() = default;
    ~IdentitySecret();

    explicit IdentitySecret(const IdentitySecret&) = delete;
    // no byte data constructor
    explicit IdentitySecret(const byte_t*) = delete;

    template <typename fspath_t>
    bool
    LoadFromFile(const fspath_t& fname);

    std::string_view
    ToString() const
    {
      return "[IdentitySecret]";
    }
  };

  template <>
  constexpr inline bool IsToStringFormattable<PubKey> = true;
  template <>
  constexpr inline bool IsToStringFormattable<SecretKey> = true;
  template <>
  constexpr inline bool IsToStringFormattable<PrivateKey> = true;
  template <>
  constexpr inline bool IsToStringFormattable<IdentitySecret> = true;

  using ShortHash = std::array<byte_t, SHORTHASHSIZE>;
  using LongHash = std::array<byte_t, HASHSIZE>;

  struct Signature final
  {
    ALIGNED_BUFFER_MEMBERS(Signature, SIGSIZE);

   public:
    byte_t*
    Hi();

    const byte_t*
    Hi() const;

    byte_t*
    Lo();

    const byte_t*
    Lo() const;

    bool
    FromBytestring(llarp_buffer_t* buf)
    {
      if (buf->sz != size())
        return false;
      std::copy_n(buf->base, size(), data());
      return true;
    }
  };

  using TunnelNonce = AlignedBuffer<TUNNONCESIZE>;
  using SymmNonce = AlignedBuffer<NONCESIZE>;
  using SymmKey = AlignedBuffer<32>;

  using PQCipherBlock = AlignedBuffer<PQ_CIPHERTEXTSIZE + 1>;
  using PQPubKey = AlignedBuffer<PQ_PUBKEYSIZE>;

  struct PQKeyPair final
  {
    ALIGNED_BUFFER_MEMBERS(PQKeyPair, PQ_KEYPAIRSIZE)
   public:
    ~PQKeyPair();
  };

  template <>
  constexpr inline bool is_aligned_buffer<std::array<uint8_t, 16>> = true;
  template <>
  constexpr inline bool is_aligned_buffer<std::array<uint8_t, 24>> = true;

  template <>
  constexpr inline bool is_aligned_buffer<std::array<uint8_t, 32>> = true;

  template <>
  constexpr inline bool is_aligned_buffer<std::array<uint8_t, 64>> = true;
  template <>
  constexpr inline bool is_aligned_buffer<Signature> = true;

  template <>
  constexpr inline bool is_aligned_buffer<PQCipherBlock> = true;

  template <>
  constexpr inline bool is_aligned_buffer<PQPubKey> = true;

  template <>
  constexpr inline bool is_aligned_buffer<PubKey> = true;

  using path_dh_func =
      std::function<bool(SharedSecret&, const PubKey&, const SecretKey&, const KeyExchangeNonce&)>;

  using transport_dh_func =
      std::function<bool(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&)>;

  using shorthash_func = std::function<bool(ShortHash&, const llarp_buffer_t&)>;
}  // namespace llarp

namespace std
{
  template <>
  struct hash<llarp::PubKey>
  {
    hash<array<byte_t, llarp::PubKey::SIZE>> m_hasher;
    size_t
    operator()(const llarp::PubKey& pk) const noexcept
    {
      return m_hasher(pk.as_array());
    }
  };

  constexpr auto&
  operator^=(array<uint8_t, 32>& lhs, const array<uint8_t, 32>& rhs)
  {
    transform(lhs.begin(), lhs.end(), rhs.begin(), lhs.begin(), std::bit_xor<>{});
    return lhs;
  }

  constexpr array<uint8_t, 32>
  operator^(const array<uint8_t, 32>& lhs, const array<uint8_t, 32>& rhs)
  {
    array<uint8_t, 32> result{};
    transform(lhs.begin(), lhs.end(), rhs.begin(), result.begin(), std::bit_xor<>{});
    return result;
  }

};  // namespace std

Updated on 2026-04-01 at 23:35:40 +0000