Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
elliptic_openssl.cpp
Go to the documentation of this file.
2
5
6#include <fc/fwd_impl.hpp>
8#include <fc/log/logger.hpp>
9
11
12namespace fc { namespace ecc {
13 namespace detail
14 {
16 {
17 public:
18 private_key_impl() BOOST_NOEXCEPT {}
19
20 private_key_impl( const private_key_impl& cpy ) BOOST_NOEXCEPT
21 {
22 *this = cpy;
23 }
24
25 private_key_impl( private_key_impl&& cpy ) BOOST_NOEXCEPT
26 {
27 *this = cpy;
28 }
29
30 ~private_key_impl() BOOST_NOEXCEPT
31 {
32 free_key();
33 }
34
35 private_key_impl& operator=( const private_key_impl& pk ) BOOST_NOEXCEPT
36 {
37 if (pk._key == nullptr)
38 {
39 free_key();
40 } else if ( _key == nullptr ) {
41 _key = EC_KEY_dup( pk._key );
42 } else {
43 EC_KEY_copy( _key, pk._key );
44 }
45 return *this;
46 }
47
49 {
50 if ( this != &pk ) {
51 free_key();
52 _key = pk._key;
53 pk._key = nullptr;
54 }
55 return *this;
56 }
57
58 EC_KEY* _key = nullptr;
59
60 private:
61 void free_key() BOOST_NOEXCEPT
62 {
63 if( _key != nullptr )
64 {
65 EC_KEY_free(_key);
66 _key = nullptr;
67 }
68 }
69 };
70 }
71
73
74 private_key::private_key( const private_key& pk ) : my( pk.my ) {}
75
76 private_key::private_key( private_key&& pk ) : my( std::move( pk.my ) ) {}
77
79
80 private_key& private_key::operator=( private_key&& pk )
81 {
82 my = std::move(pk.my);
83 return *this;
84 }
85
86 private_key& private_key::operator=( const private_key& pk )
87 {
88 my = pk.my;
89 return *this;
90 }
91 static void * ecies_key_derivation(const void *input, size_t ilen, void *output, size_t *olen)
92 {
93 if (*olen < SHA512_DIGEST_LENGTH) {
94 return NULL;
95 }
96 *olen = SHA512_DIGEST_LENGTH;
97 return (void*)SHA512((const unsigned char*)input, ilen, (unsigned char*)output);
98 }
99
100 int static inline EC_KEY_regenerate_key(EC_KEY *eckey, const BIGNUM *priv_key)
101 {
102 int ok = 0;
103 BN_CTX *ctx = NULL;
104 EC_POINT *pub_key = NULL;
105
106 if (!eckey) return 0;
107
108 const EC_GROUP *group = EC_KEY_get0_group(eckey);
109
110 if ((ctx = BN_CTX_new()) == NULL)
111 goto err;
112
113 pub_key = EC_POINT_new(group);
114
115 if (pub_key == NULL)
116 goto err;
117
118 if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
119 goto err;
120
121 EC_KEY_set_private_key(eckey,priv_key);
122 EC_KEY_set_public_key(eckey,pub_key);
123
124 ok = 1;
125
126 err:
127
128 if (pub_key) EC_POINT_free(pub_key);
129 if (ctx != NULL) BN_CTX_free(ctx);
130
131 return(ok);
132 }
133
134 private_key private_key::regenerate( const fc::sha256& secret )
135 {
136 private_key self;
137 self.my->_key = EC_KEY_new_by_curve_name( NID_secp256k1 );
138 if( !self.my->_key ) FC_THROW_EXCEPTION( exception, "Unable to generate EC key" );
139
140 ssl_bignum bn;
141 BN_bin2bn( (const unsigned char*)&secret, 32, bn );
142
143 if( !EC_KEY_regenerate_key(self.my->_key,bn) )
144 {
145 FC_THROW_EXCEPTION( exception, "unable to regenerate key" );
146 }
147 return self;
148 }
149
151 {
152 return get_secret( my->_key );
153 }
154
155 private_key::private_key( EC_KEY* k )
156 {
157 my->_key = k;
158 }
159
160 public_key private_key::get_public_key()const
161 {
162 public_key pub;
163 pub.my->_key = EC_KEY_new_by_curve_name( NID_secp256k1 );
164 EC_KEY_set_public_key( pub.my->_key, EC_KEY_get0_public_key( my->_key ) );
165 return pub;
166 }
167
168
169 fc::sha512 private_key::get_shared_secret( const public_key& other )const
170 {
171 FC_ASSERT( my->_key != nullptr );
172 FC_ASSERT( other.my->_key != nullptr );
174 ECDH_compute_key( (unsigned char*)&buf, sizeof(buf), EC_KEY_get0_public_key(other.my->_key), my->_key, ecies_key_derivation );
175 return buf;
176 }
177
179 {
180 try {
181 FC_ASSERT( my->_key != nullptr );
182 auto my_pub_key = get_public_key().serialize(); // just for good measure
183 //ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&digest, sizeof(digest), my->_key);
184 public_key_data key_data;
185 while( true )
186 {
187 ecdsa_sig sig = ECDSA_do_sign((unsigned char*)&digest, sizeof(digest), my->_key);
188
189 if (sig==nullptr)
190 FC_THROW_EXCEPTION( exception, "Unable to sign" );
191
193 // memset( csig.data, 0, sizeof(csig) );
194
195 int nBitsR = BN_num_bits(sig->r);
196 int nBitsS = BN_num_bits(sig->s);
197 if (nBitsR <= 256 && nBitsS <= 256)
198 {
199 int nRecId = -1;
200 EC_KEY* key = EC_KEY_new_by_curve_name( NID_secp256k1 );
201 FC_ASSERT( key );
202 EC_KEY_set_conv_form( key, POINT_CONVERSION_COMPRESSED );
203 for (int i=0; i<4; i++)
204 {
205 if (detail::public_key_impl::ECDSA_SIG_recover_key_GFp(key, sig, (unsigned char*)&digest, sizeof(digest), i, 1) == 1)
206 {
207 unsigned char* buffer = (unsigned char*) key_data.begin();
208 i2o_ECPublicKey( key, &buffer ); // FIXME: questionable memory handling
209 if ( key_data == my_pub_key )
210 {
211 nRecId = i;
212 break;
213 }
214 }
215 }
216 EC_KEY_free( key );
217
218 if (nRecId == -1)
219 {
220 FC_THROW_EXCEPTION( exception, "unable to construct recoverable key");
221 }
222 unsigned char* result = nullptr;
223 auto bytes = i2d_ECDSA_SIG( sig, &result );
224 auto lenR = result[3];
225 auto lenS = result[5+lenR];
226 //idump( (result[0])(result[1])(result[2])(result[3])(result[3+lenR])(result[4+lenR])(bytes)(lenR)(lenS) );
227 if( lenR != 32 ) { free(result); continue; }
228 if( lenS != 32 ) { free(result); continue; }
229 //idump( (33-(nBitsR+7)/8) );
230 //idump( (65-(nBitsS+7)/8) );
231 //idump( (sizeof(csig) ) );
232 memcpy( &csig.data[1], &result[4], lenR );
233 memcpy( &csig.data[33], &result[6+lenR], lenS );
234 //idump( (csig.data[33]) );
235 //idump( (csig.data[1]) );
236 free(result);
237 //idump( (nRecId) );
238 csig.data[0] = nRecId+27+4;//(fCompressedPubKey ? 4 : 0);
239 /*
240 idump( (csig) );
241 auto rlen = BN_bn2bin(sig->r,&csig.data[33-(nBitsR+7)/8]);
242 auto slen = BN_bn2bin(sig->s,&csig.data[65-(nBitsS+7)/8]);
243 idump( (rlen)(slen) );
244 */
245 }
246 return csig;
247 } // while true
248 } FC_RETHROW_EXCEPTIONS( warn, "sign ${digest}", ("digest", digest)("private_key",*this) );
249 }
250} }
const T * begin() const
Definition array.hpp:29
T data[N]
Definition array.hpp:37
private_key_impl & operator=(private_key_impl &&pk) BOOST_NOEXCEPT
private_key_impl & operator=(const private_key_impl &pk) BOOST_NOEXCEPT
private_key_impl(private_key_impl &&cpy) BOOST_NOEXCEPT
private_key_impl(const private_key_impl &cpy) BOOST_NOEXCEPT
static int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check)
public_key get_public_key() const
private_key_secret get_secret() const
private_key & operator=(private_key &&pk)
fc::sha512 get_shared_secret(const public_key &pub) const
compact_signature sign_compact(const fc::sha256 &digest, bool require_canonical=true) const
static private_key regenerate(const fc::sha256 &secret)
Defines exception's used by fc.
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
#define FC_RETHROW_EXCEPTIONS(LOG_LEVEL, FORMAT,...)
Catchs all exception's, std::exceptions, and ... and rethrows them after appending the provided log m...
bignum_st BIGNUM
Definition bigint.hpp:7
Definition bn.h:56
namespace sysio::chain
Definition authority.cpp:3
fc::sha256 digest(const T &value)
Definition digest.hpp:9
std::vector< char > bytes
Definition alt_bn128.hpp:10
Definition name.hpp:106
@ self
the connection is to itself
Definition protocol.hpp:48
bool pub
uint8_t buf[2048]
memcpy((char *) pInfo->slotDescription, s, l)