-
Notifications
You must be signed in to change notification settings - Fork 66
Expand file tree
/
Copy pathkeys.h
More file actions
147 lines (123 loc) · 5.06 KB
/
Copy pathkeys.h
File metadata and controls
147 lines (123 loc) · 5.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#pragma once
#include <array>
#include <cstddef>
#include <functional>
#include <string>
#include <string_view>
#include <oxenss/common/formattable.h>
namespace oxenss::crypto {
using namespace std::literals;
constexpr std::string_view SUBKEY_HASH_KEY = "OxenSSSubkey"sv;
namespace detail {
template <size_t Length>
inline constexpr std::array<unsigned char, Length> null_bytes = {0};
void load_from_hex(void* buffer, size_t length, std::string_view hex);
void load_from_bytes(void* buffer, size_t length, std::string_view bytes);
std::string to_hex(const unsigned char* buffer, size_t length);
} // namespace detail
template <typename Derived, size_t KeyLength>
struct alignas(size_t) key_base : std::array<unsigned char, KeyLength> {
std::string_view view() const {
return {reinterpret_cast<const char*>(this->data()), KeyLength};
}
std::string str() const { return {reinterpret_cast<const char*>(this->data()), KeyLength}; }
std::string hex() const { return detail::to_hex(this->data(), KeyLength); }
explicit operator bool() const { return *this != detail::null_bytes<KeyLength>; }
// Loads the key from a hex string; throws if the hex is the wrong size or not hex.
[[nodiscard]] static Derived from_hex(std::string_view hex) {
Derived d;
d.load_from_hex(hex);
return d;
}
void load_from_hex(std::string_view hex) {
detail::load_from_hex(this->data(), this->size(), hex);
}
// Loads the key from a byte string; throws if the wrong size.
[[nodiscard]] static Derived from_bytes(std::string_view bytes) {
Derived d;
d.load_from_bytes(bytes);
return d;
}
void load_from_bytes(std::string_view bytes) {
detail::load_from_bytes(this->data(), this->size(), bytes);
}
};
template <typename Derived, size_t KeyLength>
struct pubkey_base : key_base<Derived, KeyLength> {
using PubKeyBase = pubkey_base<Derived, KeyLength>;
std::string to_string() const { return PubKeyBase::hex(); }
};
struct legacy_pubkey : pubkey_base<legacy_pubkey, 32> {};
struct x25519_pubkey : pubkey_base<x25519_pubkey, 32> {};
struct ed25519_pubkey : pubkey_base<ed25519_pubkey, 32> {
// Returns the {base32z}.snode representation of this pubkey
std::string snode_address() const;
};
template <typename Derived, size_t KeyLength>
struct seckey_base : key_base<Derived, KeyLength> {};
struct legacy_seckey : seckey_base<legacy_seckey, 32> {
legacy_pubkey pubkey() const;
};
struct ed25519_seckey : seckey_base<ed25519_seckey, 64> {
ed25519_pubkey pubkey() const;
};
struct x25519_seckey : seckey_base<x25519_seckey, 32> {
x25519_pubkey pubkey() const;
};
template <typename Pubkey, typename Seckey>
struct keypair {
Pubkey pub;
Seckey sec;
// Populates the keypair by loading from a secret value then computing the pubkey from the
// secret.
[[nodiscard]] static keypair from_secret_hex(std::string_view hex) {
keypair k;
k.sec.load_from_hex(hex);
k.pub = k.sec.pubkey();
return k;
}
[[nodiscard]] static keypair from_secret_bytes(std::string_view bytes) {
keypair k;
k.sec.load_from_bytes(bytes);
k.pub = k.sec.pubkey();
return k;
}
};
using legacy_keypair = keypair<legacy_pubkey, legacy_seckey>;
using ed25519_keypair = keypair<ed25519_pubkey, ed25519_seckey>;
using x25519_keypair = keypair<x25519_pubkey, x25519_seckey>;
/// Parse a pubkey string value encoded in any of base32z, b64, hex, or raw bytes, based on the
/// length of the value. Returns a null pk (i.e. operator bool() returns false) and warns on
/// invalid input (i.e. wrong length or invalid encoding).
legacy_pubkey parse_legacy_pubkey(std::string_view pubkey_in);
ed25519_pubkey parse_ed25519_pubkey(std::string_view pubkey_in);
x25519_pubkey parse_x25519_pubkey(std::string_view pubkey_in);
struct snode_keypairs {
legacy_keypair legacy;
ed25519_keypair ed25519;
x25519_keypair x25519;
};
} // namespace oxenss::crypto
template <>
inline constexpr bool oxenss::to_string_formattable<oxenss::crypto::legacy_pubkey> = true;
template <>
inline constexpr bool oxenss::to_string_formattable<oxenss::crypto::ed25519_pubkey> = true;
template <>
inline constexpr bool oxenss::to_string_formattable<oxenss::crypto::x25519_pubkey> = true;
namespace std {
template <typename Derived, size_t N>
struct hash<oxenss::crypto::pubkey_base<Derived, N>> {
size_t operator()(const oxenss::crypto::pubkey_base<Derived, N>& pk) const {
// pubkeys are already random enough to use the first bytes directly as a good (and
// fast) hash value
static_assert(alignof(decltype(pk)) >= alignof(size_t));
return *reinterpret_cast<const size_t*>(pk.data());
}
};
template <>
struct hash<oxenss::crypto::legacy_pubkey> : hash<oxenss::crypto::legacy_pubkey::PubKeyBase> {};
template <>
struct hash<oxenss::crypto::x25519_pubkey> : hash<oxenss::crypto::x25519_pubkey::PubKeyBase> {};
template <>
struct hash<oxenss::crypto::ed25519_pubkey> : hash<oxenss::crypto::ed25519_pubkey::PubKeyBase> {};
} // namespace std