-
Notifications
You must be signed in to change notification settings - Fork 73
/
Copy pathelliptic.hpp
239 lines (194 loc) · 8.27 KB
/
elliptic.hpp
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#pragma once
#include <fc/crypto/bigint.hpp>
#include <fc/crypto/common.hpp>
#include <fc/crypto/openssl.hpp>
#include <fc/crypto/sha256.hpp>
#include <fc/crypto/sha512.hpp>
#include <fc/fwd.hpp>
#include <fc/array.hpp>
#include <fc/io/raw_fwd.hpp>
namespace fc {
namespace ecc {
namespace detail
{
class public_key_impl;
class private_key_impl;
}
typedef fc::sha256 blind_factor_type;
typedef fc::array<char,33> commitment_type;
typedef fc::array<char,33> public_key_data;
typedef fc::sha256 private_key_secret;
typedef fc::array<char,65> public_key_point_data; ///< the full non-compressed version of the ECC point
typedef fc::array<char,72> signature;
typedef fc::array<unsigned char,65> compact_signature;
typedef fc::array<char,78> extended_key_data;
typedef fc::sha256 blinded_hash;
typedef fc::sha256 blind_signature;
/**
* @class public_key
* @brief contains only the public point of an elliptic curve key.
*/
class public_key
{
public:
public_key();
public_key(const public_key& k);
~public_key();
// bool verify( const fc::sha256& digest, const signature& sig );
public_key_data serialize()const;
public_key_point_data serialize_ecc_point()const;
operator public_key_data()const { return serialize(); }
public_key( const public_key_data& v );
public_key( const public_key_point_data& v );
public_key( const compact_signature& c, const fc::sha256& digest, bool check_canonical = true );
public_key child( const fc::sha256& offset )const;
bool valid()const;
public_key( public_key&& pk );
public_key& operator=( public_key&& pk );
public_key& operator=( const public_key& pk );
inline friend bool operator==( const public_key& a, const public_key& b )
{
return a.serialize() == b.serialize();
}
inline friend bool operator!=( const public_key& a, const public_key& b )
{
return a.serialize() != b.serialize();
}
/// Allows to convert current public key object into base58 number.
std::string to_base58() const;
static std::string to_base58( const public_key_data &key );
static public_key from_base58( const std::string& b58 );
unsigned int fingerprint() const;
private:
friend class private_key;
static public_key from_key_data( const public_key_data& v );
static bool is_canonical( const compact_signature& c );
fc::fwd<detail::public_key_impl,33> my;
};
/**
* @class private_key
* @brief an elliptic curve private key.
*/
class private_key
{
public:
private_key();
private_key( private_key&& pk );
private_key( const private_key& pk );
~private_key();
private_key& operator=( private_key&& pk );
private_key& operator=( const private_key& pk );
static private_key generate();
static private_key regenerate( const fc::sha256& secret );
private_key child( const fc::sha256& offset )const;
/**
* This method of generation enables creating a new private key in a deterministic manner relative to
* an initial seed. A public_key created from the seed can be multiplied by the offset to calculate
* the new public key without having to know the private key.
*/
static private_key generate_from_seed( const fc::sha256& seed, const fc::sha256& offset = fc::sha256() );
private_key_secret get_secret()const; // get the private key secret
operator private_key_secret ()const { return get_secret(); }
/**
* Given a public key, calculatse a 512 bit shared secret between that
* key and this private key.
*/
fc::sha512 get_shared_secret( const public_key& pub )const;
// signature sign( const fc::sha256& digest )const;
compact_signature sign_compact( const fc::sha256& digest, bool require_canonical = true )const;
// bool verify( const fc::sha256& digest, const signature& sig );
public_key get_public_key()const;
inline friend bool operator==( const private_key& a, const private_key& b )
{
return a.get_secret() == b.get_secret();
}
inline friend bool operator!=( const private_key& a, const private_key& b )
{
return a.get_secret() != b.get_secret();
}
inline friend bool operator<( const private_key& a, const private_key& b )
{
return a.get_secret() < b.get_secret();
}
unsigned int fingerprint() const { return get_public_key().fingerprint(); }
private:
private_key( EC_KEY* k );
static fc::sha256 get_secret( const EC_KEY * const k );
fc::fwd<detail::private_key_impl,32> my;
};
/**
* Shims
*/
struct public_key_shim : public crypto::shim<public_key_data> {
using crypto::shim<public_key_data>::shim;
bool valid()const {
return public_key(_data).valid();
}
};
struct signature_shim : public crypto::shim<compact_signature> {
using public_key_type = public_key_shim;
using crypto::shim<compact_signature>::shim;
public_key_type recover(const sha256& digest, bool check_canonical) const {
return public_key_type(public_key(_data, digest, check_canonical).serialize());
}
};
struct private_key_shim : public crypto::shim<private_key_secret> {
using crypto::shim<private_key_secret>::shim;
using signature_type = signature_shim;
using public_key_type = public_key_shim;
signature_type sign( const sha256& digest, bool require_canonical = true ) const
{
return signature_type(private_key::regenerate(_data).sign_compact(digest, require_canonical));
}
public_key_type get_public_key( ) const
{
return public_key_type(private_key::regenerate(_data).get_public_key().serialize());
}
sha512 generate_shared_secret( const public_key_type &pub_key ) const
{
return private_key::regenerate(_data).get_shared_secret(public_key(pub_key.serialize()));
}
static private_key_shim generate()
{
return private_key_shim(private_key::generate().get_secret());
}
};
} // namespace ecc
void to_variant( const ecc::private_key& var, variant& vo );
void from_variant( const variant& var, ecc::private_key& vo );
void to_variant( const ecc::public_key& var, variant& vo );
void from_variant( const variant& var, ecc::public_key& vo );
namespace raw
{
template<typename Stream>
void unpack( Stream& s, fc::ecc::public_key& pk)
{
ecc::public_key_data ser;
fc::raw::unpack(s,ser);
pk = fc::ecc::public_key( ser );
}
template<typename Stream>
void pack( Stream& s, const fc::ecc::public_key& pk)
{
fc::raw::pack( s, pk.serialize() );
}
template<typename Stream>
void unpack( Stream& s, fc::ecc::private_key& pk)
{
fc::sha256 sec;
unpack( s, sec );
pk = ecc::private_key::regenerate(sec);
}
template<typename Stream>
void pack( Stream& s, const fc::ecc::private_key& pk)
{
fc::raw::pack( s, pk.get_secret() );
}
} // namespace raw
} // namespace fc
#include <fc/reflect/reflect.hpp>
FC_REFLECT_TYPENAME( fc::ecc::private_key )
FC_REFLECT_TYPENAME( fc::ecc::public_key )
FC_REFLECT_DERIVED( fc::ecc::public_key_shim, (fc::crypto::shim<fc::ecc::public_key_data>), BOOST_PP_SEQ_NIL )
FC_REFLECT_DERIVED( fc::ecc::signature_shim, (fc::crypto::shim<fc::ecc::compact_signature>), BOOST_PP_SEQ_NIL )
FC_REFLECT_DERIVED( fc::ecc::private_key_shim, (fc::crypto::shim<fc::ecc::private_key_secret>), BOOST_PP_SEQ_NIL )